react-native-theoplayer 7.5.1 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/android/src/main/java/com/theoplayer/cache/CacheModule.kt +27 -25
  3. package/android/src/main/java/com/theoplayer/player/PlayerModule.kt +11 -0
  4. package/ios/THEOplayerRCTBridge.m +3 -1
  5. package/ios/THEOplayerRCTMainEventHandler.swift +2 -2
  6. package/ios/THEOplayerRCTMediaTrackEventHandler.swift +129 -2
  7. package/ios/THEOplayerRCTSourceDescriptionAggregator.swift +15 -2
  8. package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +12 -0
  9. package/ios/THEOplayerRCTTrackEventTypes.swift +4 -0
  10. package/ios/ads/THEOplayerRCTAdAdapter.swift +19 -15
  11. package/ios/ads/THEOplayerRCTAdsNative.swift +25 -8
  12. package/ios/cache/THEOplayerRCTCacheAPI.swift +7 -3
  13. package/ios/cache/THEOplayerRCTCacheAggregator.swift +1 -1
  14. package/lib/commonjs/api/player/THEOplayer.js +16 -2
  15. package/lib/commonjs/api/player/THEOplayer.js.map +1 -1
  16. package/lib/commonjs/internal/adapter/DefaultNativePlayerState.js +1 -0
  17. package/lib/commonjs/internal/adapter/DefaultNativePlayerState.js.map +1 -1
  18. package/lib/commonjs/internal/adapter/THEOplayerAdapter.js +10 -1
  19. package/lib/commonjs/internal/adapter/THEOplayerAdapter.js.map +1 -1
  20. package/lib/commonjs/internal/adapter/web/WebPresentationModeManager.js +6 -4
  21. package/lib/commonjs/internal/adapter/web/WebPresentationModeManager.js.map +1 -1
  22. package/lib/module/api/player/THEOplayer.js +16 -1
  23. package/lib/module/api/player/THEOplayer.js.map +1 -1
  24. package/lib/module/internal/adapter/DefaultNativePlayerState.js +2 -1
  25. package/lib/module/internal/adapter/DefaultNativePlayerState.js.map +1 -1
  26. package/lib/module/internal/adapter/THEOplayerAdapter.js +10 -1
  27. package/lib/module/internal/adapter/THEOplayerAdapter.js.map +1 -1
  28. package/lib/module/internal/adapter/web/WebPresentationModeManager.js +6 -4
  29. package/lib/module/internal/adapter/web/WebPresentationModeManager.js.map +1 -1
  30. package/lib/typescript/api/player/THEOplayer.d.ts +22 -1
  31. package/lib/typescript/api/player/THEOplayer.d.ts.map +1 -1
  32. package/lib/typescript/internal/adapter/DefaultNativePlayerState.d.ts +2 -1
  33. package/lib/typescript/internal/adapter/DefaultNativePlayerState.d.ts.map +1 -1
  34. package/lib/typescript/internal/adapter/NativePlayerState.d.ts +2 -1
  35. package/lib/typescript/internal/adapter/NativePlayerState.d.ts.map +1 -1
  36. package/lib/typescript/internal/adapter/THEOplayerAdapter.d.ts +3 -1
  37. package/lib/typescript/internal/adapter/THEOplayerAdapter.d.ts.map +1 -1
  38. package/lib/typescript/internal/adapter/web/WebPresentationModeManager.d.ts.map +1 -1
  39. package/package.json +3 -3
  40. package/react-native-theoplayer.podspec +5 -5
  41. package/src/api/player/THEOplayer.ts +24 -1
  42. package/src/internal/adapter/DefaultNativePlayerState.ts +4 -1
  43. package/src/internal/adapter/NativePlayerState.ts +2 -1
  44. package/src/internal/adapter/THEOplayerAdapter.ts +14 -2
  45. package/src/internal/adapter/web/WebPresentationModeManager.ts +6 -4
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [7.7.0] - 24-07-25
9
+
10
+ ### Added
11
+
12
+ - Added ActiveQualityChanged event support for iOS.
13
+
14
+ ### Fixed
15
+
16
+ - Fixed an issue where on iOS a cached asset would not play when setting the tasks's source on the player.
17
+ - Fixed an issue where on iOS the createTask method (CacheAPI) was not returning the created task.
18
+ - Fixed an issue where on iOS the Ad and AdBreak protocols where extended in the underlying native SDK and required some modifications.
19
+ - Fixed an issue where on Android the native module preparation would fail due to a change in the Android SDK 7.8.0 on eventDispatching.
20
+
21
+ ## [7.6.0] - 24-07-01
22
+
23
+ ### Added
24
+
25
+ - Added `'root'` as an alternative id for the root div element in Web applications, supporting fullscreen presentation mode in Expo-based apps.
26
+ - Added `renderingTarget` property to `THEOplayer` API for Android, enabling the option to choose between either rendering to a `SurfaceView` (default) or `TextureView`.
27
+
28
+ ### Changed
29
+
30
+ - Lowered the required node version to v16+.
31
+
8
32
  ## [7.5.1] - 24-06-20
9
33
 
10
34
  ### Added
@@ -52,34 +52,36 @@ class CacheModule(private val context: ReactApplicationContext) :
52
52
 
53
53
  init {
54
54
  // Add cache event listeners
55
- cache?.apply {
56
- // Listen for cache state changes
57
- addEventListener(CacheEventTypes.CACHE_STATE_CHANGE) { event ->
58
- emit("onCacheStatusChange", Arguments.createMap().apply {
59
- putString(PROP_STATUS, CacheAdapter.fromCacheStatus(event.status))
60
- })
61
- }
62
- // Listen for add task events
63
- tasks.addEventListener(CachingTaskListEventTypes.ADD_TASK) { event ->
64
- event.task?.let { task ->
65
- // Notify AddCachingTaskEvent event
66
- emit("onAddCachingTaskEvent", Arguments.createMap().apply {
67
- putMap(PROP_TASK, CacheAdapter.fromCachingTask(task))
55
+ handler.post {
56
+ cache?.apply {
57
+ // Listen for cache state changes
58
+ addEventListener(CacheEventTypes.CACHE_STATE_CHANGE) { event ->
59
+ emit("onCacheStatusChange", Arguments.createMap().apply {
60
+ putString(PROP_STATUS, CacheAdapter.fromCacheStatus(event.status))
68
61
  })
69
- // Add CachingTask listeners
70
- addCachingTaskListeners(task)
62
+ }
63
+ // Listen for add task events
64
+ tasks.addEventListener(CachingTaskListEventTypes.ADD_TASK) { event ->
65
+ event.task?.let { task ->
66
+ // Notify AddCachingTaskEvent event
67
+ emit("onAddCachingTaskEvent", Arguments.createMap().apply {
68
+ putMap(PROP_TASK, CacheAdapter.fromCachingTask(task))
69
+ })
70
+ // Add CachingTask listeners
71
+ addCachingTaskListeners(task)
72
+ }
71
73
  }
72
- }
73
74
 
74
- // Listen for task removal
75
- tasks.addEventListener(CachingTaskListEventTypes.REMOVE_TASK) { event ->
76
- event.task?.let { task ->
77
- // Notify RemoveCachingTaskEvent event
78
- emit("onRemoveCachingTaskEvent", Arguments.createMap().apply {
79
- putMap(PROP_TASK, CacheAdapter.fromCachingTask(event.task))
80
- })
81
- // Remove CachingTask listeners
82
- removeCachingTaskListeners(task)
75
+ // Listen for task removal
76
+ tasks.addEventListener(CachingTaskListEventTypes.REMOVE_TASK) { event ->
77
+ event.task?.let { task ->
78
+ // Notify RemoveCachingTaskEvent event
79
+ emit("onRemoveCachingTaskEvent", Arguments.createMap().apply {
80
+ putMap(PROP_TASK, CacheAdapter.fromCachingTask(event.task))
81
+ })
82
+ // Remove CachingTask listeners
83
+ removeCachingTaskListeners(task)
84
+ }
83
85
  }
84
86
  }
85
87
  }
@@ -6,6 +6,7 @@ import com.theoplayer.abr.ABRConfigurationAdapter
6
6
  import com.theoplayer.android.api.player.AspectRatio
7
7
  import com.theoplayer.android.api.player.PreloadType
8
8
  import com.theoplayer.android.api.player.PresentationMode
9
+ import com.theoplayer.android.api.player.RenderingTarget
9
10
  import com.theoplayer.android.api.player.track.mediatrack.MediaTrack
10
11
  import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality
11
12
  import com.theoplayer.android.api.player.track.texttrack.TextTrackMode
@@ -228,4 +229,14 @@ class PlayerModule(context: ReactApplicationContext) : ReactContextBaseJavaModul
228
229
  }
229
230
  }
230
231
  }
232
+
233
+ @ReactMethod
234
+ fun setRenderingTarget(tag: Int, target: String) {
235
+ viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? ->
236
+ view?.player?.setRenderingTarget(when (target) {
237
+ "textureView" -> RenderingTarget.TEXTURE_VIEW
238
+ else -> RenderingTarget.SURFACE_VIEW
239
+ })
240
+ }
241
+ }
231
242
  }
@@ -228,7 +228,9 @@ RCT_EXTERN_METHOD(getInitialState:(RCTPromiseResolveBlock)resolve
228
228
  rejecter:(RCTPromiseRejectBlock)reject)
229
229
 
230
230
  RCT_EXTERN_METHOD(createTask:(NSDictionary)src
231
- params:(NSDictionary)params)
231
+ params:(NSDictionary)params
232
+ resolver:(RCTPromiseResolveBlock)resolve
233
+ rejecter:(RCTPromiseRejectBlock)reject)
232
234
 
233
235
  RCT_EXTERN_METHOD(startCachingTask:(nonnull NSString *)id)
234
236
 
@@ -317,8 +317,8 @@ public class THEOplayerRCTMainEventHandler {
317
317
  let forwardedResizeEvent = self?.onNativeResize {
318
318
  forwardedResizeEvent(
319
319
  [
320
- "width": wplayer.videoWidth,
321
- "height": wplayer.videoHeight,
320
+ "width": wplayer.frame.width,
321
+ "height": wplayer.frame.height,
322
322
  ]
323
323
  )
324
324
  }
@@ -20,8 +20,8 @@ class THEOplayerRCTMediaTrackEventHandler {
20
20
  private var videoChangeTrackListener: EventListener?
21
21
 
22
22
  // MARK: mediaTrack listeners (attached dynamically to new mediatracks)
23
- private var audioChangeTrackListeners: [Int:EventListener] = [:]
24
- private var videoChangeTrackListeners: [Int:EventListener] = [:]
23
+ private var videoQualityChangeListeners: [Int:EventListener] = [:]
24
+ private var audioQualityChangeListeners: [Int:EventListener] = [:]
25
25
 
26
26
 
27
27
  // MARK: - destruction
@@ -56,6 +56,10 @@ class THEOplayerRCTMediaTrackEventHandler {
56
56
  "type" : TrackListEventType.ADD_TRACK.rawValue,
57
57
  "trackType": MediaTrackType.AUDIO.rawValue
58
58
  ])
59
+
60
+ // start listening for qualityChange events on this track
61
+ welf.audioQualityChangeListeners[audioTrack.uid] = audioTrack.addEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: welf.addAudioQualityChangeListener(_:))
62
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] QualityChange listener attached to THEOplayer audioTrack with uid \(audioTrack.uid)") }
59
63
  }
60
64
  }
61
65
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AddTrack listener attached to THEOplayer audioTrack list") }
@@ -72,6 +76,12 @@ class THEOplayerRCTMediaTrackEventHandler {
72
76
  "type" : TrackListEventType.REMOVE_TRACK.rawValue,
73
77
  "trackType": MediaTrackType.AUDIO.rawValue
74
78
  ])
79
+
80
+ // stop listening for qualityChange events on this track
81
+ if let audioQualityChangeListener = welf.audioQualityChangeListeners.removeValue(forKey: audioTrack.uid) {
82
+ audioTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: audioQualityChangeListener)
83
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer audioTrack with uid \(audioTrack.uid)") }
84
+ }
75
85
  }
76
86
  }
77
87
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] RemoveTrack listener attached to THEOplayer audioTrack list") }
@@ -104,6 +114,10 @@ class THEOplayerRCTMediaTrackEventHandler {
104
114
  "type" : TrackListEventType.ADD_TRACK.rawValue,
105
115
  "trackType": MediaTrackType.VIDEO.rawValue
106
116
  ])
117
+
118
+ // start listening for qualityChange events on this track
119
+ welf.videoQualityChangeListeners[videoTrack.uid] = videoTrack.addEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: welf.addVideoQualityChangeListener(_:))
120
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] QualityChange listener attached to THEOplayer videoTrack with uid \(videoTrack.uid)") }
107
121
  }
108
122
  }
109
123
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AddTrack listener attached to THEOplayer videoTrack list") }
@@ -120,6 +134,12 @@ class THEOplayerRCTMediaTrackEventHandler {
120
134
  "type" : TrackListEventType.REMOVE_TRACK.rawValue,
121
135
  "trackType": MediaTrackType.VIDEO.rawValue
122
136
  ])
137
+
138
+ // stop listening for qualityChange events on this track
139
+ if let videoQualityChangeListener = welf.videoQualityChangeListeners.removeValue(forKey: videoTrack.uid) {
140
+ videoTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: videoQualityChangeListener)
141
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer videoTrack with uid \(videoTrack.uid)") }
142
+ }
123
143
  }
124
144
  }
125
145
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] RemoveTrack listener attached to THEOplayer videoTrack list") }
@@ -181,5 +201,112 @@ class THEOplayerRCTMediaTrackEventHandler {
181
201
  player.videoTracks.removeEventListener(type: VideoTrackListEventTypes.CHANGE, listener: videoChangeTrackListener)
182
202
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ChangeTrack listener dettached from THEOplayer videoTrack list") }
183
203
  }
204
+
205
+ // QUALITY CHANGE - AUDIO
206
+ let audioTrackCount = player.audioTracks.count
207
+ if audioTrackCount > 0 {
208
+ for i in 0..<audioTrackCount {
209
+ let audioTrack = player.audioTracks[i]
210
+ // stop listening for quality change events on this track
211
+ if let audioQualityChangeListener = self.audioQualityChangeListeners.removeValue(forKey: audioTrack.uid) {
212
+ audioTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: audioQualityChangeListener)
213
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer audioTrack with uid \(audioTrack.uid)") }
214
+ }
215
+ }
216
+ }
217
+
218
+ // QUALITY CHANGE - VIDEO
219
+ let videoTrackCount = player.videoTracks.count
220
+ if videoTrackCount > 0 {
221
+ for i in 0..<videoTrackCount {
222
+ let videoTrack = player.videoTracks[i]
223
+ // stop listening for quality change events on this track
224
+ if let videoQualityChangeListener = self.videoQualityChangeListeners.removeValue(forKey: videoTrack.uid) {
225
+ videoTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: videoQualityChangeListener)
226
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer videoTrack with uid \(videoTrack.uid)") }
227
+ }
228
+ }
229
+ }
230
+ }
231
+
232
+ // MARK: - dynamic mediaTrack Listeners
233
+ private func addVideoQualityChangeListener(_ event: ActiveQualityChangedEvent) {
234
+ if let forwardedMediaTrackEvent = self.onNativeMediaTrackEvent,
235
+ let player = self.player,
236
+ let track = self.activeTrack(tracks: player.videoTracks) {
237
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for videoTrack") }
238
+ let identifier = String(track.activeQualityBandwidth)
239
+ let label = self.labelFromBandWidth(track.activeQualityBandwidth)
240
+ forwardedMediaTrackEvent([
241
+ "trackUid" : track.uid,
242
+ "type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
243
+ "trackType": MediaTrackType.VIDEO.rawValue,
244
+ "qualities": [
245
+ "bandwidth": track.activeQualityBandwidth,
246
+ "codecs": "",
247
+ "id": identifier,
248
+ "uid": identifier,
249
+ "name": label,
250
+ "label": label,
251
+ "available": true,
252
+ "width": player.videoWidth,
253
+ "height": player.videoHeight,
254
+ //"frameRate": 0, // not available on iOS SDK
255
+ //"firstFrame": 0 // not available on iOS SDK
256
+
257
+ ]
258
+ ])
259
+ }
260
+ }
261
+
262
+ private func addAudioQualityChangeListener(_ event: ActiveQualityChangedEvent) {
263
+ if let forwardedMediaTrackEvent = self.onNativeMediaTrackEvent,
264
+ let player = self.player,
265
+ let track = self.activeTrack(tracks: player.audioTracks) {
266
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for audioTrack") }
267
+ let identifier = String(track.activeQualityBandwidth)
268
+ let label = self.labelFromBandWidth(track.activeQualityBandwidth)
269
+
270
+ forwardedMediaTrackEvent([
271
+ "trackUid" : track.uid,
272
+ "type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
273
+ "trackType": MediaTrackType.AUDIO.rawValue,
274
+ "qualities": [
275
+ "bandwidth": track.activeQualityBandwidth,
276
+ "codecs": "",
277
+ "id": identifier,
278
+ "uid": identifier,
279
+ "name": label,
280
+ "label": label,
281
+ "available": true,
282
+ //"audioSamplingRate": 0 // not available on iOS SDK
283
+ ]
284
+ ])
285
+ }
286
+ }
287
+
288
+ // MARK: - Helpers
289
+ private func activeTrack(tracks: THEOplayerSDK.MediaTrackList) -> MediaTrack? {
290
+ guard tracks.count > 0 else {
291
+ return nil;
292
+ }
293
+ var track: MediaTrack?
294
+ for i in 0...tracks.count-1 {
295
+ track = tracks.get(i)
296
+ if (track != nil && track!.enabled) {
297
+ return track
298
+ }
299
+ }
300
+ return nil;
301
+ }
302
+
303
+ private func labelFromBandWidth(_ bandWidth: Int) -> String {
304
+ if bandWidth > 1000000 {
305
+ return "\(Double(bandWidth / 1000) / 1000) Mbps"
306
+ } else if bandWidth > 1000 {
307
+ return "\(bandWidth / 1000) kbps"
308
+ } else {
309
+ return "No Label"
310
+ }
184
311
  }
185
312
  }
@@ -6,12 +6,14 @@ import UIKit
6
6
 
7
7
  #if os(iOS)
8
8
  class THEOplayerRCTSourceDescriptionAggregator {
9
- class func aggregateCacheTaskSourceDescription(sourceDescription: SourceDescription) -> [String:Any]? {
9
+ class func aggregateCacheTaskSourceDescription(sourceDescription: SourceDescription, cachingTaskId: String) -> [String:Any]? {
10
10
  do {
11
11
  let jsonEncoder = JSONEncoder()
12
12
  let data = try jsonEncoder.encode(sourceDescription)
13
13
  if let result = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] {
14
- return THEOplayerRCTSourceDescriptionAggregator.sanitiseSourceDescriptionMetadata(input: result)
14
+ let srcDescription = THEOplayerRCTSourceDescriptionAggregator.sanitiseSourceDescriptionMetadata(input: result)
15
+ let extendedSrcDescription = THEOplayerRCTSourceDescriptionAggregator.addCachingTaskIdToMetadata(input: srcDescription, cachingTaskId: cachingTaskId)
16
+ return extendedSrcDescription
15
17
  }
16
18
  } catch {
17
19
  if DEBUG { PrintUtils.printLog(logText: "[NATIVE] Could not aggregate sourceDescription for caching task: \(error.localizedDescription)")}
@@ -39,5 +41,16 @@ class THEOplayerRCTSourceDescriptionAggregator {
39
41
  }
40
42
  return output
41
43
  }
44
+
45
+ private class func addCachingTaskIdToMetadata(input: [String:Any], cachingTaskId: String) -> [String:Any] {
46
+ var output: [String:Any] = input
47
+ if var metadata = output[SD_PROP_METADATA] as? [String:Any] {
48
+ metadata[SD_PROP_METADATA_CACHINGTASK_ID] = cachingTaskId
49
+ output[SD_PROP_METADATA] = metadata
50
+ } else {
51
+ output[SD_PROP_METADATA] = [SD_PROP_METADATA_CACHINGTASK_ID: cachingTaskId]
52
+ }
53
+ return output
54
+ }
42
55
  }
43
56
  #endif
@@ -12,6 +12,7 @@ let SD_PROP_SOURCES: String = "sources"
12
12
  let SD_PROP_POSTER: String = "poster"
13
13
  let SD_PROP_TEXTTRACKS: String = "textTracks"
14
14
  let SD_PROP_METADATA: String = "metadata"
15
+ let SD_PROP_METADATA_CACHINGTASK_ID: String = "cachingTaskId"
15
16
  let SD_PROP_METADATAKEYS: String = "metadataKeys"
16
17
  let SD_PROP_SRC: String = "src"
17
18
  let SD_PROP_TYPE: String = "type"
@@ -73,6 +74,17 @@ class THEOplayerRCTSourceDescriptionBuilder {
73
74
  guard let sourcesData = sourceData[SD_PROP_SOURCES] else {
74
75
  return (nil, nil)
75
76
  }
77
+
78
+ if let metadataData = sourceData[SD_PROP_METADATA] as? [String:Any],
79
+ let cachingTaskId = metadataData[SD_PROP_METADATA_CACHINGTASK_ID] as? String {
80
+ // this is a MediaCache src, so fetch the original SourceDescription from the MediaCache
81
+ let cachingTaskWithId = THEOplayer.cache.tasks.first { cachingTask in
82
+ cachingTask.id == cachingTaskId
83
+ }
84
+ if let foundTask = cachingTaskWithId {
85
+ return (foundTask.source, nil)
86
+ }
87
+ }
76
88
 
77
89
  var typedSources: [TypedSource] = []
78
90
  // case: array of source objects
@@ -17,3 +17,7 @@ enum TrackCueEventType: Int {
17
17
  case ENTER_CUE = 2
18
18
  case EXIT_CUE = 3
19
19
  }
20
+
21
+ enum MediaTrackEventType: Int {
22
+ case ACTIVE_QUALITY_CHANGED = 0
23
+ }
@@ -4,6 +4,7 @@ import Foundation
4
4
  import THEOplayerSDK
5
5
 
6
6
  let PROP_AD_INTEGRATION: String = "integration"
7
+ let PROP_AD_CUSTOM_INTEGRATION: String = "customIntegration"
7
8
  let PROP_AD_TYPE: String = "type"
8
9
  let PROP_AD_ID: String = "id"
9
10
  let PROP_AD_BREAK: String = "adBreak"
@@ -31,6 +32,7 @@ let PROP_ADBREAK_TIME_OFFSET: String = "timeOffset"
31
32
  let PROP_ADBREAK_MAX_REMAINING_DURATION: String = "maxRemainingDuration"
32
33
  let PROP_ADBREAK_ADS: String = "ads"
33
34
  let PROP_ADBREAK_INTEGRATION: String = "integration"
35
+ let PROP_ADBREAK_CUSTOM_INTEGRATION: String = "customIntegration"
34
36
  let PROP_COMPANION_AD_SLOT_ID: String = "adSlotId"
35
37
  let PROP_COMPANION_ALT_TEXT: String = "altText"
36
38
  let PROP_COMPANION_CLICK_THROUGH: String = "clickThrough"
@@ -43,6 +45,9 @@ class THEOplayerRCTAdAdapter {
43
45
  class func fromAd(ad: Ad, processAdBreak: Bool = true) -> [String:Any] {
44
46
  var adData: [String:Any] = [:]
45
47
  adData[PROP_AD_INTEGRATION] = ad.integration._rawValue
48
+ if let customIntegration = ad.customIntegration {
49
+ adData[PROP_AD_CUSTOM_INTEGRATION] = customIntegration
50
+ }
46
51
  adData[PROP_AD_TYPE] = ad.type
47
52
  if let adId = ad.id {
48
53
  adData[PROP_AD_ID] = adId
@@ -50,6 +55,9 @@ class THEOplayerRCTAdAdapter {
50
55
  if let resourceURI = ad.resourceURI {
51
56
  adData[PROP_AD_RESOURCE_URI] = resourceURI
52
57
  }
58
+ if let clickThrough = ad.clickThrough {
59
+ adData[PROP_AD_CLICK_THROUGH] = clickThrough
60
+ }
53
61
  if let skipOffset = ad.skipOffset {
54
62
  adData[PROP_AD_SKIP_OFFSET] = (skipOffset == -1) ? skipOffset : skipOffset
55
63
  }
@@ -65,20 +73,14 @@ class THEOplayerRCTAdAdapter {
65
73
  adData[PROP_AD_UNIVERSAL_AD_IDS] = []
66
74
 
67
75
  // Add additional properties for Linear Ads
68
- if let linearAd = ad as? LinearAd {
69
- if let adDuration = linearAd.duration {
70
- adData[PROP_AD_DURATION] = adDuration
71
- }
76
+ if let adDuration = ad.duration {
77
+ adData[PROP_AD_DURATION] = adDuration
72
78
  }
73
79
 
74
80
  // Add additional properties for NonLinear Ads
75
- #if os(iOS)
76
- if let nonLinearAd = ad as? NonLinearAd {
77
- if let adClickThrough = nonLinearAd.clickThrough {
78
- adData[PROP_AD_CLICK_THROUGH] = adClickThrough
79
- }
81
+ if let adClickThrough = ad.clickThrough {
82
+ adData[PROP_AD_CLICK_THROUGH] = adClickThrough
80
83
  }
81
- #endif
82
84
 
83
85
  // Add additional properties for GoogleIma Ads
84
86
  if let googleImaAd = ad as? GoogleImaAd {
@@ -142,6 +144,8 @@ class THEOplayerRCTAdAdapter {
142
144
  height: adData[PROP_GOOGLE_AD_HEIGHT] as? Int,
143
145
  integration: THEOplayerRCTTypeUtils.adIntegrationKind((adData[PROP_AD_INTEGRATION] as? String) ?? ""),
144
146
  duration: lround((adData[PROP_AD_DURATION] as? Double) ?? 0.0),
147
+ clickThrough: adData[PROP_AD_CLICK_THROUGH] as? String,
148
+ customIntegration: adData[PROP_AD_CUSTOM_INTEGRATION] as? String,
145
149
  mediaFiles: [], // TODO
146
150
  adSystem: adData[PROP_GOOGLE_AD_AD_SYSTEM] as? String,
147
151
  creativeId: adData[PROP_GOOGLE_AD_CREATIVE_ID] as? String,
@@ -173,6 +177,8 @@ class THEOplayerRCTAdAdapter {
173
177
  adBreakData[PROP_ADBREAK_MAX_DURATION] = adBreak.maxDuration
174
178
  adBreakData[PROP_ADBREAK_TIME_OFFSET] = adBreak.timeOffset
175
179
  adBreakData[PROP_ADBREAK_MAX_REMAINING_DURATION] = adBreak.maxRemainingDuration
180
+ adBreakData[PROP_ADBREAK_INTEGRATION] = adBreak.integration
181
+ adBreakData[PROP_ADBREAK_CUSTOM_INTEGRATION] = adBreak.customIntegration
176
182
  // process adds when adbreak contains them
177
183
  if !adBreak.ads.isEmpty {
178
184
  var adList: [[String:Any]] = []
@@ -180,10 +186,6 @@ class THEOplayerRCTAdAdapter {
180
186
  adList.append(THEOplayerRCTAdAdapter.fromAd(ad: ad, processAdBreak: false))
181
187
  }
182
188
  adBreakData[PROP_ADBREAK_ADS] = adList
183
- if adList.count > 0,
184
- let integration = adList[0][PROP_AD_INTEGRATION] {
185
- adBreakData[PROP_ADBREAK_INTEGRATION] = integration
186
- }
187
189
  }
188
190
  return adBreakData
189
191
  }
@@ -205,7 +207,9 @@ class THEOplayerRCTAdAdapter {
205
207
  return NativeAdBreak(ads: ads,
206
208
  maxDuration: lround((adBreakData[PROP_ADBREAK_MAX_DURATION] as? Double) ?? 0),
207
209
  maxRemainingDuration: (adBreakData[PROP_ADBREAK_MAX_REMAINING_DURATION] as? Double) ?? 0,
208
- timeOffset: lround((adBreakData[PROP_ADBREAK_TIME_OFFSET] as? Double) ?? 0))
210
+ timeOffset: lround((adBreakData[PROP_ADBREAK_TIME_OFFSET] as? Double) ?? 0),
211
+ integration: THEOplayerRCTTypeUtils.adIntegrationKind((adBreakData[PROP_ADBREAK_INTEGRATION] as? String) ?? ""),
212
+ customIntegration: adBreakData[PROP_ADBREAK_CUSTOM_INTEGRATION] as? String)
209
213
  }
210
214
 
211
215
  class private func fromCompanionAds(companionAds: [CompanionAd?]) -> [[String:Any]] {
@@ -22,8 +22,14 @@ class NativeAd: THEOplayerSDK.Ad {
22
22
  var height: Int? = nil
23
23
  /** The kind of the ad integration.*/
24
24
  var integration: THEOplayerSDK.AdIntegrationKind = THEOplayerSDK.AdIntegrationKind.defaultKind
25
+ /** The duration of the LinearAd, as provided by the VAST file, in seconds.*/
26
+ var duration: Int? = 0
27
+ /** The url that redirects to the website of the advertiser.*/
28
+ var clickThrough: String? = nil
29
+ /**The type of custom ad integration.*/
30
+ var customIntegration: String? = nil
25
31
 
26
- init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind) {
32
+ init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String?, customIntegration: String?) {
27
33
  self.adBreak = adBreak
28
34
  self.companions = companions
29
35
  self.type = type
@@ -33,18 +39,18 @@ class NativeAd: THEOplayerSDK.Ad {
33
39
  self.width = width
34
40
  self.height = height
35
41
  self.integration = integration
42
+ self.duration = duration
43
+ self.clickThrough = clickThrough
44
+ self.customIntegration = customIntegration
36
45
  }
37
46
  }
38
47
 
39
48
  class NativeLinearAd: NativeAd, THEOplayerSDK.LinearAd {
40
- /** The duration of the LinearAd, as provided by the VAST file, in seconds.*/
41
- var duration: Int? = 0
42
49
  /** An array of mediafiles, which provides some meta data retrieved from the VAST file.*/
43
50
  var mediaFiles: [THEOplayerSDK.MediaFile] = []
44
51
 
45
- init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, mediaFiles: [THEOplayerSDK.MediaFile] = []) {
52
+ init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String? = nil, customIntegration: String? = nil, mediaFiles: [THEOplayerSDK.MediaFile] = []) {
46
53
 
47
- self.duration = duration
48
54
  self.mediaFiles = mediaFiles
49
55
 
50
56
  super.init(adBreak:adBreak,
@@ -55,7 +61,10 @@ class NativeLinearAd: NativeAd, THEOplayerSDK.LinearAd {
55
61
  resourceURI: resourceURI,
56
62
  width: width,
57
63
  height: height,
58
- integration: integration)
64
+ integration: integration,
65
+ duration: duration,
66
+ clickThrough: clickThrough,
67
+ customIntegration: customIntegration)
59
68
  }
60
69
  }
61
70
 
@@ -77,7 +86,7 @@ class NativeLinearGoogleImaAd: NativeLinearAd, THEOplayerSDK.GoogleImaAd {
77
86
  /** The String representing custom trafficking parameters from the VAST response.*/
78
87
  var traffickingParameters: String = ""
79
88
 
80
- init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, mediaFiles: [THEOplayerSDK.MediaFile] = [], adSystem: String? = nil, creativeId: String? = nil, wrapperAdIds: [String], wrapperAdSystems: [String], wrapperCreativeIds: [String], vastMediaBitrate: Int, universalAdIds: [UniversalAdId], traffickingParameters: String) {
89
+ init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String? = nil, customIntegration: String? = nil, mediaFiles: [THEOplayerSDK.MediaFile] = [], adSystem: String? = nil, creativeId: String? = nil, wrapperAdIds: [String], wrapperAdSystems: [String], wrapperCreativeIds: [String], vastMediaBitrate: Int, universalAdIds: [UniversalAdId], traffickingParameters: String) {
81
90
  self.adSystem = adSystem
82
91
  self.creativeId = creativeId
83
92
  self.wrapperAdIds = wrapperAdIds
@@ -97,6 +106,8 @@ class NativeLinearGoogleImaAd: NativeLinearAd, THEOplayerSDK.GoogleImaAd {
97
106
  height: height,
98
107
  integration:integration,
99
108
  duration: duration,
109
+ clickThrough: clickThrough,
110
+ customIntegration: customIntegration,
100
111
  mediaFiles: mediaFiles)
101
112
  }
102
113
  }
@@ -110,12 +121,18 @@ class NativeAdBreak: THEOplayerSDK.AdBreak {
110
121
  var maxRemainingDuration: Double = -1
111
122
  /** The time offset at which point the content will be paused to play the ad break, in seconds.*/
112
123
  var timeOffset: Int = 0
124
+ /** The kind of the ad integration.*/
125
+ var integration: THEOplayerSDK.AdIntegrationKind = THEOplayerSDK.AdIntegrationKind.defaultKind
126
+ /**The type of custom ad integration.*/
127
+ var customIntegration: String? = nil
113
128
 
114
- init(ads: [Ad], maxDuration: Int, maxRemainingDuration: Double, timeOffset: Int) {
129
+ init(ads: [Ad], maxDuration: Int, maxRemainingDuration: Double, timeOffset: Int, integration: THEOplayerSDK.AdIntegrationKind, customIntegration: String? = nil) {
115
130
  self.ads = ads
116
131
  self.maxDuration = maxDuration
117
132
  self.maxRemainingDuration = maxRemainingDuration
118
133
  self.timeOffset = timeOffset
134
+ self.integration = integration
135
+ self.customIntegration = customIntegration
119
136
  }
120
137
  }
121
138
 
@@ -17,6 +17,8 @@ let CACHE_EVENT_PROP_TASKS: String = "tasks"
17
17
  let CACHE_TAG: String = "[CacheAPI]"
18
18
 
19
19
  let ERROR_MESSAGE_CACHE_API_UNSUPPORTED_FEATURE = "Cache API is not supported for tvOS"
20
+ let ERROR_CODE_CREATE_CACHINGTASK_FAILED = "create_cachingtask_failure"
21
+ let ERROR_MESSAGE_CREATE_CACHINGTASK_FAILURE = "Creating a new cachingTask failed."
20
22
 
21
23
  @objc(THEOplayerRCTCacheAPI)
22
24
  class THEOplayerRCTCacheAPI: RCTEventEmitter {
@@ -140,15 +142,15 @@ class THEOplayerRCTCacheAPI: RCTEventEmitter {
140
142
  ] as [String : Any])
141
143
  }
142
144
 
143
- @objc(createTask:params:)
144
- func createTask(_ src: NSDictionary, params: NSDictionary) -> Void {
145
+ @objc(createTask:params:resolver:rejecter:)
146
+ func createTask(_ src: NSDictionary, params: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
145
147
  if DEBUG_CACHE_API { PrintUtils.printLog(logText: "[NATIVE] createTask triggered on Cache API.") }
146
148
  let params = THEOplayerRCTCachingParametersBuilder.buildCachingParameters(params)
147
149
  let (sourceDescription, _) = THEOplayerRCTSourceDescriptionBuilder.buildSourceDescription(src)
148
150
  if let srcDescription = sourceDescription,
149
151
  let newTask = THEOplayer.cache.createTask(source: srcDescription, parameters: params) {
150
152
  if DEBUG_CACHE_API { PrintUtils.printLog(logText: "[NATIVE] New cache task created with id \(newTask.id)") }
151
-
153
+ resolve(THEOplayerRCTCacheAggregator.aggregateCacheTask(task: newTask))
152
154
  // emit onAddCachingTaskEvent
153
155
  self.sendEvent(withName: "onAddCachingTaskEvent", body: [
154
156
  CACHE_EVENT_PROP_TASK: THEOplayerRCTCacheAggregator.aggregateCacheTask(task: newTask)
@@ -156,6 +158,8 @@ class THEOplayerRCTCacheAPI: RCTEventEmitter {
156
158
 
157
159
  // attach the state and progress listeners to the new task
158
160
  self.attachTaskListenersToTask(newTask)
161
+ } else {
162
+ reject(ERROR_CODE_CREATE_CACHINGTASK_FAILED, ERROR_MESSAGE_CREATE_CACHINGTASK_FAILURE, nil)
159
163
  }
160
164
  }
161
165
 
@@ -41,7 +41,7 @@ class THEOplayerRCTCacheAggregator {
41
41
  aggregatedData[CACHETASK_PROP_ID] = task.id
42
42
  aggregatedData[CACHETASK_PROP_STATUS] = THEOplayerRCTTypeUtils.cachingTaskStatusToString(task.status)
43
43
  aggregatedData[CACHETASK_PROP_PARAMETERS] = THEOplayerRCTCacheAggregator.aggregateCacheTaskParameters(params: task.parameters)
44
- aggregatedData[CACHETASK_PROP_SOURCE] = THEOplayerRCTSourceDescriptionAggregator.aggregateCacheTaskSourceDescription(sourceDescription: task.source)
44
+ aggregatedData[CACHETASK_PROP_SOURCE] = THEOplayerRCTSourceDescriptionAggregator.aggregateCacheTaskSourceDescription(sourceDescription: task.source, cachingTaskId: task.id)
45
45
  for (key, value) in THEOplayerRCTCacheAggregator.aggregateCacheTaskProgress(task: task) {
46
46
  aggregatedData[key] = value
47
47
  }
@@ -3,11 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.AspectRatio = void 0;
6
+ exports.RenderingTarget = exports.AspectRatio = void 0;
7
7
  /**
8
8
  * Specifies an aspect ratio for the player.
9
9
  *
10
- * <br/> - `FIT` (default): Scales the player so that all content fits inside its bounding box, keeping the original aspect ratio of the content..
10
+ * <br/> - `FIT` (default): Scales the player so that all content fits inside its bounding box, keeping the original aspect ratio of the content.
11
11
  * <br/> - `FILL`: Scales the player so that all content fits inside the bounding box, which will be stretched to fill it entirely.
12
12
  * <br/> - `ASPECT_FILL`: Scales the player so that the content fills up the entire bounding box, keeping the original aspect ratio of the content.
13
13
  *
@@ -20,6 +20,20 @@ let AspectRatio = exports.AspectRatio = /*#__PURE__*/function (AspectRatio) {
20
20
  AspectRatio["ASPECT_FILL"] = "aspectFill";
21
21
  return AspectRatio;
22
22
  }({});
23
+ /**
24
+ * Specifies the rendering target for the player.
25
+ *
26
+ * <br/> - `SURFACE_VIEW` (default): Render video to a {@link https://developer.android.com/reference/android/view/SurfaceView | SurfaceView}.
27
+ * <br/> - `TEXTURE_VIEW`: Render video to a {@link https://developer.android.com/reference/android/view/TextureView | TextureView}.
28
+ *
29
+ * @public
30
+ * @defaultValue `'SURFACE_VIEW'`
31
+ */
32
+ let RenderingTarget = exports.RenderingTarget = /*#__PURE__*/function (RenderingTarget) {
33
+ RenderingTarget["SURFACE_VIEW"] = "surfaceView";
34
+ RenderingTarget["TEXTURE_VIEW"] = "textureView";
35
+ return RenderingTarget;
36
+ }({});
23
37
  /**
24
38
  * The THEOplayer API.
25
39
  */