react-native-theoplayer 9.7.1 → 9.9.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 (109) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/android/build.gradle +6 -2
  3. package/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt +12 -0
  4. package/android/src/main/java/com/theoplayer/source/SourceAdapter.kt +10 -4
  5. package/android/src/main/java/com/theoplayer/theolive/EndpointAdapter.kt +68 -0
  6. package/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt +63 -0
  7. package/ios/THEOplayerRCTBridge.m +2 -2
  8. package/ios/THEOplayerRCTDeviceEventHandler.swift +38 -0
  9. package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +5 -2
  10. package/ios/THEOplayerRCTView.swift +23 -0
  11. package/ios/theoAds/THEOplayerRCTSourceDescriptionBuilder+TheoAds.swift +4 -1
  12. package/ios/theolive/THEOplayerRCTTHEOliveAPI.swift +4 -4
  13. package/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift +146 -0
  14. package/lib/commonjs/api/barrel.js.map +1 -1
  15. package/lib/commonjs/api/event/TheoAdsEvent.js +1 -1
  16. package/lib/commonjs/api/event/TheoLiveEvent.js +39 -0
  17. package/lib/commonjs/api/event/TheoLiveEvent.js.map +1 -0
  18. package/lib/commonjs/api/event/barrel.js +11 -0
  19. package/lib/commonjs/api/event/barrel.js.map +1 -1
  20. package/lib/commonjs/api/player/PlayerEventMap.js +1 -0
  21. package/lib/commonjs/api/player/PlayerEventMap.js.map +1 -1
  22. package/lib/commonjs/api/source/SourceDescription.js +1 -0
  23. package/lib/commonjs/api/source/SourceDescription.js.map +1 -1
  24. package/lib/commonjs/api/source/ads/TheoAdDescription.js.map +1 -1
  25. package/lib/commonjs/api/theolive/TheoLiveEndpoint.js +2 -0
  26. package/lib/commonjs/api/theolive/TheoLiveEndpoint.js.map +1 -0
  27. package/lib/commonjs/api/theolive/barrel.js +19 -8
  28. package/lib/commonjs/api/theolive/barrel.js.map +1 -1
  29. package/lib/commonjs/internal/THEOplayerView.js +17 -1
  30. package/lib/commonjs/internal/THEOplayerView.js.map +1 -1
  31. package/lib/commonjs/internal/adapter/WebEventForwarder.js +18 -0
  32. package/lib/commonjs/internal/adapter/WebEventForwarder.js.map +1 -1
  33. package/lib/commonjs/internal/adapter/event/PlayerEvents.js +24 -1
  34. package/lib/commonjs/internal/adapter/event/PlayerEvents.js.map +1 -1
  35. package/lib/commonjs/internal/adapter/event/native/NativeTheoLiveEvent.js +24 -0
  36. package/lib/commonjs/internal/adapter/event/native/NativeTheoLiveEvent.js.map +1 -0
  37. package/lib/commonjs/manifest.json +1 -1
  38. package/lib/module/api/barrel.js +1 -0
  39. package/lib/module/api/barrel.js.map +1 -1
  40. package/lib/module/api/event/TheoAdsEvent.js +1 -1
  41. package/lib/module/api/event/TheoLiveEvent.js +38 -0
  42. package/lib/module/api/event/TheoLiveEvent.js.map +1 -0
  43. package/lib/module/api/event/barrel.js +1 -0
  44. package/lib/module/api/event/barrel.js.map +1 -1
  45. package/lib/module/api/player/PlayerEventMap.js +1 -0
  46. package/lib/module/api/player/PlayerEventMap.js.map +1 -1
  47. package/lib/module/api/source/SourceDescription.js +1 -0
  48. package/lib/module/api/source/SourceDescription.js.map +1 -1
  49. package/lib/module/api/source/ads/TheoAdDescription.js.map +1 -1
  50. package/lib/module/api/theolive/TheoLiveEndpoint.js +2 -0
  51. package/lib/module/api/theolive/TheoLiveEndpoint.js.map +1 -0
  52. package/lib/module/api/theolive/barrel.js +3 -2
  53. package/lib/module/api/theolive/barrel.js.map +1 -1
  54. package/lib/module/internal/THEOplayerView.js +17 -1
  55. package/lib/module/internal/THEOplayerView.js.map +1 -1
  56. package/lib/module/internal/adapter/WebEventForwarder.js +20 -2
  57. package/lib/module/internal/adapter/WebEventForwarder.js.map +1 -1
  58. package/lib/module/internal/adapter/event/PlayerEvents.js +20 -0
  59. package/lib/module/internal/adapter/event/PlayerEvents.js.map +1 -1
  60. package/lib/module/internal/adapter/event/native/NativeTheoLiveEvent.js +20 -0
  61. package/lib/module/internal/adapter/event/native/NativeTheoLiveEvent.js.map +1 -0
  62. package/lib/module/manifest.json +1 -1
  63. package/lib/typescript/api/barrel.d.ts +1 -0
  64. package/lib/typescript/api/barrel.d.ts.map +1 -1
  65. package/lib/typescript/api/event/TheoAdsEvent.d.ts +1 -1
  66. package/lib/typescript/api/event/TheoLiveEvent.d.ts +77 -0
  67. package/lib/typescript/api/event/TheoLiveEvent.d.ts.map +1 -0
  68. package/lib/typescript/api/event/barrel.d.ts +1 -0
  69. package/lib/typescript/api/event/barrel.d.ts.map +1 -1
  70. package/lib/typescript/api/player/PlayerEventMap.d.ts +6 -0
  71. package/lib/typescript/api/player/PlayerEventMap.d.ts.map +1 -1
  72. package/lib/typescript/api/source/SourceDescription.d.ts +5 -0
  73. package/lib/typescript/api/source/SourceDescription.d.ts.map +1 -1
  74. package/lib/typescript/api/source/ads/TheoAdDescription.d.ts +4 -0
  75. package/lib/typescript/api/source/ads/TheoAdDescription.d.ts.map +1 -1
  76. package/lib/typescript/api/theolive/TheoLiveAPI.d.ts +5 -3
  77. package/lib/typescript/api/theolive/TheoLiveAPI.d.ts.map +1 -1
  78. package/lib/typescript/api/theolive/TheoLiveEndpoint.d.ts +32 -0
  79. package/lib/typescript/api/theolive/TheoLiveEndpoint.d.ts.map +1 -0
  80. package/lib/typescript/api/theolive/TheoLiveSource.d.ts +1 -0
  81. package/lib/typescript/api/theolive/TheoLiveSource.d.ts.map +1 -1
  82. package/lib/typescript/api/theolive/barrel.d.ts +3 -2
  83. package/lib/typescript/api/theolive/barrel.d.ts.map +1 -1
  84. package/lib/typescript/internal/THEOplayerView.d.ts +2 -0
  85. package/lib/typescript/internal/THEOplayerView.d.ts.map +1 -1
  86. package/lib/typescript/internal/adapter/WebEventForwarder.d.ts +1 -0
  87. package/lib/typescript/internal/adapter/WebEventForwarder.d.ts.map +1 -1
  88. package/lib/typescript/internal/adapter/event/PlayerEvents.d.ts +15 -1
  89. package/lib/typescript/internal/adapter/event/PlayerEvents.d.ts.map +1 -1
  90. package/lib/typescript/internal/adapter/event/native/NativeTheoLiveEvent.d.ts +18 -0
  91. package/lib/typescript/internal/adapter/event/native/NativeTheoLiveEvent.d.ts.map +1 -0
  92. package/package.json +2 -2
  93. package/react-native-theoplayer.podspec +7 -7
  94. package/src/api/barrel.ts +1 -0
  95. package/src/api/event/TheoAdsEvent.ts +1 -1
  96. package/src/api/event/TheoLiveEvent.ts +83 -0
  97. package/src/api/event/barrel.ts +1 -0
  98. package/src/api/player/PlayerEventMap.ts +7 -0
  99. package/src/api/source/SourceDescription.ts +5 -0
  100. package/src/api/source/ads/TheoAdDescription.ts +5 -0
  101. package/src/api/theolive/TheoLiveAPI.ts +5 -3
  102. package/src/api/theolive/TheoLiveEndpoint.ts +32 -0
  103. package/src/api/theolive/TheoLiveSource.ts +1 -0
  104. package/src/api/theolive/barrel.ts +3 -2
  105. package/src/internal/THEOplayerView.tsx +22 -2
  106. package/src/internal/adapter/WebEventForwarder.ts +27 -1
  107. package/src/internal/adapter/event/PlayerEvents.ts +29 -0
  108. package/src/internal/adapter/event/native/NativeTheoLiveEvent.ts +34 -0
  109. package/src/manifest.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,7 +5,31 @@ 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
- ## [9.7.1]
8
+ ## [9.9.0] - 25-07-14
9
+
10
+ ### Added
11
+
12
+ - Added initializationDelay to TheoAdsDecription, to delay THEOads session creation for more optimal ads monetisation.
13
+
14
+ ### Fixed
15
+
16
+ - Fixed an issue on iOS where on iPads the fullscreen dimensions were not correctly updated after the first device orientation change.
17
+
18
+ ## [9.8.0] - 25-07-08
19
+
20
+ ### Changed
21
+
22
+ - Deprecated the `BaseSource.integration` property in favor of `TypedSource.type`.
23
+
24
+ ## Added
25
+
26
+ - Added support for `THEOlive` events.
27
+
28
+ ## Fixed
29
+
30
+ - Fixed an issue on Android where, depending on the project structure, the Maven repository list would be incorrect.
31
+
32
+ ## [9.7.1] - 25-07-03
9
33
 
10
34
  ### Fixed
11
35
 
@@ -118,10 +118,14 @@ rootProject.allprojects {
118
118
  repositories {
119
119
  google()
120
120
  mavenCentral()
121
+ maven { url "https://maven.theoplayer.com/releases" }
122
+ maven { url "https://maven.theoplayer.com/snapshots" }
123
+ maven { url("$rootDir/../node_modules/react-native-theoplayer/android/local") }
124
+ mavenLocal()
121
125
  }
122
126
 
123
- // The minimum supported THEOplayer version is 9.7.0
124
- def theoVersion = safeExtGet('THEOplayer_sdk', '[9.7.0, 10.0.0)')
127
+ // The minimum supported THEOplayer version is 9.8.0
128
+ def theoVersion = safeExtGet('THEOplayer_sdk', '[9.8.0, 10.0.0)')
125
129
  def theoMediaSessionVersion = safeExtGet('THEOplayer_mediasession', '[8.0.0, 10.0.0)')
126
130
  def theoAdsWrapperVersion = "9.0.0"
127
131
  def coroutinesVersion = safeExtGet('coroutinesVersion', '1.7.3')
@@ -43,6 +43,7 @@ import com.theoplayer.android.api.player.track.texttrack.TextTrackKind
43
43
  import com.theoplayer.android.api.player.track.texttrack.TextTrackMode
44
44
  import com.theoplayer.cast.CastEventAdapter
45
45
  import com.theoplayer.presentation.PresentationModeChangeContext
46
+ import com.theoplayer.theolive.THEOliveEventAdapter
46
47
  import com.theoplayer.track.*
47
48
  import com.theoplayer.util.PayloadBuilder
48
49
  import kotlin.math.floor
@@ -75,6 +76,7 @@ private const val EVENT_MEDIATRACK_LIST_EVENT = "onNativeMediaTrackListEvent"
75
76
  private const val EVENT_MEDIATRACK_EVENT = "onNativeMediaTrackEvent"
76
77
  private const val EVENT_AD_EVENT = "onNativeAdEvent"
77
78
  private const val EVENT_CAST_EVENT = "onNativeCastEvent"
79
+ private const val EVENT_THEOLIVE_EVENT = "onNativeTHEOliveEvent"
78
80
  private const val EVENT_PRESENTATIONMODECHANGE = "onNativePresentationModeChange"
79
81
  private const val EVENT_VOLUMECHANGE = "onNativeVolumeChange"
80
82
  private const val EVENT_RESIZE = "onNativeResize"
@@ -117,6 +119,7 @@ class PlayerEventEmitter internal constructor(
117
119
  EVENT_MEDIATRACK_EVENT,
118
120
  EVENT_AD_EVENT,
119
121
  EVENT_CAST_EVENT,
122
+ EVENT_THEOLIVE_EVENT,
120
123
  EVENT_PRESENTATIONMODECHANGE,
121
124
  EVENT_VOLUMECHANGE,
122
125
  EVENT_RESIZE
@@ -151,6 +154,7 @@ class PlayerEventEmitter internal constructor(
151
154
  EVENT_MEDIATRACK_EVENT,
152
155
  EVENT_AD_EVENT,
153
156
  EVENT_CAST_EVENT,
157
+ EVENT_THEOLIVE_EVENT,
154
158
  EVENT_PRESENTATIONMODECHANGE,
155
159
  EVENT_VOLUMECHANGE,
156
160
  EVENT_RESIZE
@@ -164,6 +168,7 @@ class PlayerEventEmitter internal constructor(
164
168
  private val videoTrackListeners = HashMap<EventType<*>, EventListener<*>>()
165
169
  private var adEventAdapter: AdEventAdapter? = null
166
170
  private var castEventAdapter: CastEventAdapter? = null
171
+ private var theoLiveEventAdapter: THEOliveEventAdapter? = null
167
172
  private var lastTimeUpdate: Long = 0
168
173
  private var lastCurrentTime = 0.0
169
174
  private var resizeListener = View.OnLayoutChangeListener { v, _, _, _, _, oldLeft, oldTop, oldRight, oldBottom ->
@@ -672,6 +677,12 @@ class PlayerEventEmitter internal constructor(
672
677
  }
673
678
  }
674
679
 
680
+ theoLiveEventAdapter = THEOliveEventAdapter(player.theoLive, object : THEOliveEventAdapter.Emitter {
681
+ override fun emit(payload: WritableMap?) {
682
+ receiveEvent(EVENT_THEOLIVE_EVENT, payload)
683
+ }
684
+ })
685
+
675
686
  // Attach view size listener
676
687
  playerView.addOnLayoutChangeListener(resizeListener)
677
688
  }
@@ -714,5 +725,6 @@ class PlayerEventEmitter internal constructor(
714
725
 
715
726
  castEventAdapter?.destroy()
716
727
  adEventAdapter?.destroy()
728
+ theoLiveEventAdapter?.destroy()
717
729
  }
718
730
  }
@@ -67,6 +67,7 @@ private const val PROP_OVERRIDE_LAYOUT = "overrideLayout"
67
67
  private const val PROP_NETWORK_CODE = "networkCode"
68
68
  private const val PROP_USE_ID3 = "useId3"
69
69
  private const val PROP_RETRIEVE_POD_ID_URI = "retrievePodIdURI"
70
+ private const val PROP_INITIALIZATION_DELAY = "initializationDelay"
70
71
  private const val PROP_SSE_ENDPOINT = "sseEndpoint"
71
72
  private const val PROP_LATENCY_CONFIGURATION = "latencyConfiguration"
72
73
  private const val PROP_PLAYBACK_PIPELINE = "playbackPipeline"
@@ -78,7 +79,7 @@ private const val ERROR_MISSING_CSAI_INTEGRATION = "Missing CSAI integration"
78
79
 
79
80
  private const val PROP_SSAI_INTEGRATION_GOOGLE_DAI = "google-dai"
80
81
 
81
- private const val INTEGRATION_THEOLIVE = "theolive"
82
+ private const val TYPE_THEOLIVE = "theolive"
82
83
  private const val TYPE_MILLICAST = "millicast"
83
84
  private const val PLAYBACK_PIPELINE_LEGACY = "legacy"
84
85
 
@@ -184,10 +185,14 @@ class SourceAdapter {
184
185
 
185
186
  @Throws(THEOplayerException::class)
186
187
  private fun parseTypedSource(jsonTypedSource: JSONObject, cmcdTransmissionMode: CMCDTransmissionMode? = null): TypedSource {
187
- // Some integrations do not support the Builder pattern
188
+ // Property `integration` will be replaced with `type`.
189
+ val integration = jsonTypedSource.optString(PROP_INTEGRATION)
190
+ val type = jsonTypedSource.optString(PROP_TYPE)
191
+
192
+ // Note: Some integrations do not support the Builder pattern
188
193
  return when {
189
- (jsonTypedSource.optString(PROP_INTEGRATION)) == INTEGRATION_THEOLIVE -> parseTheoLiveSource(jsonTypedSource)
190
- (jsonTypedSource.optString(PROP_TYPE)) == TYPE_MILLICAST -> parseMillicastSource(jsonTypedSource)
194
+ type == TYPE_THEOLIVE || integration == TYPE_THEOLIVE -> parseTheoLiveSource(jsonTypedSource)
195
+ type == TYPE_MILLICAST -> parseMillicastSource(jsonTypedSource)
191
196
  else -> parseTypedSourceFromBuilder(jsonTypedSource, cmcdTransmissionMode)
192
197
  }
193
198
  }
@@ -361,6 +366,7 @@ class SourceAdapter {
361
366
  overrideLayout = parseOverrideLayout(jsonAdDescription.optString(PROP_OVERRIDE_LAYOUT)),
362
367
  useId3 = jsonAdDescription.optBoolean(PROP_USE_ID3, false),
363
368
  retrievePodIdURI = jsonAdDescription.optString(PROP_RETRIEVE_POD_ID_URI).takeIf { it.isNotEmpty() },
369
+ initializationDelay = jsonAdDescription.optDouble(PROP_INITIALIZATION_DELAY),
364
370
  sseEndpoint = jsonAdDescription.optString(PROP_SSE_ENDPOINT).takeIf { it.isNotEmpty() },
365
371
  )
366
372
  }
@@ -0,0 +1,68 @@
1
+ package com.theoplayer.theolive
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.theoplayer.android.api.theolive.ContentProtectionConfiguration
6
+ import com.theoplayer.android.api.theolive.Endpoint
7
+ import com.theoplayer.android.api.theolive.FairPlayConfiguration
8
+ import com.theoplayer.android.api.theolive.KeySystemConfiguration
9
+
10
+ private const val PROP_HESP_SRC = "hespSrc"
11
+ private const val PROP_HLS_SRC = "hlsSrc"
12
+ private const val PROP_AD_SRC = "adSrc"
13
+ private const val PROP_TARGET_LATENCY = "targetLatency"
14
+ private const val PROP_WEIGHT = "weight"
15
+ private const val PROP_PRIORITY = "priority"
16
+ private const val PROP_CONTENT_PROTECTION = "contentProtection"
17
+ private const val PROP_INTEGRATION = "integration"
18
+
19
+ private const val PROP_WIDEVINE = "widevine"
20
+ private const val PROP_PLAYREADY = "playready"
21
+ private const val PROP_FAIRPLAY = "fairplay"
22
+ private const val PROP_LICENSE_URL = "licenseUrl"
23
+ private const val PROP_CERTIFICATE_URL = "certificateUrl"
24
+
25
+ object EndpointAdapter {
26
+
27
+ fun fromEndpoint(endPoint: Endpoint): WritableMap {
28
+ return Arguments.createMap().apply {
29
+ endPoint.hespSrc?.let { putString(PROP_HESP_SRC, it) }
30
+ endPoint.hlsSrc?.let { putString(PROP_HLS_SRC, it) }
31
+ endPoint.adSrc?.let { putString(PROP_AD_SRC, it) }
32
+ endPoint.targetLatency?.let { putDouble(PROP_TARGET_LATENCY, it) }
33
+ putInt(PROP_WEIGHT, endPoint.weight)
34
+ putInt(PROP_PRIORITY, endPoint.priority)
35
+ endPoint.contentProtection?.let {
36
+ putMap(PROP_CONTENT_PROTECTION, fromContentProtection(it))
37
+ }
38
+ }
39
+ }
40
+
41
+ fun fromContentProtection(contentProtection: ContentProtectionConfiguration): WritableMap {
42
+ return Arguments.createMap().apply {
43
+ putString(PROP_INTEGRATION, contentProtection.integration)
44
+ contentProtection.widevine?.let { config ->
45
+ putMap(PROP_WIDEVINE, fromKeySystemConfiguration(config))
46
+ }
47
+ contentProtection.playready?.let { config ->
48
+ putMap(PROP_PLAYREADY, fromKeySystemConfiguration(config))
49
+ }
50
+ contentProtection.fairplay?.let { config ->
51
+ putMap(PROP_FAIRPLAY, fromFairPlayConfiguration(config))
52
+ }
53
+ }
54
+ }
55
+
56
+ fun fromKeySystemConfiguration(config: KeySystemConfiguration): WritableMap {
57
+ return Arguments.createMap().apply {
58
+ config.licenseUrl?.let { url -> putString(PROP_LICENSE_URL, url) }
59
+ }
60
+ }
61
+
62
+ fun fromFairPlayConfiguration(config: FairPlayConfiguration): WritableMap {
63
+ return Arguments.createMap().apply {
64
+ config.licenseUrl?.let { url -> putString(PROP_LICENSE_URL, url) }
65
+ config.certificateUrl?.let { url -> putString(PROP_CERTIFICATE_URL, url) }
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,63 @@
1
+ package com.theoplayer.theolive
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.theoplayer.android.api.event.player.theolive.DistributionLoadStartEvent
6
+ import com.theoplayer.android.api.event.player.theolive.DistributionOfflineEvent
7
+ import com.theoplayer.android.api.event.player.theolive.EndpointLoadedEvent
8
+ import com.theoplayer.android.api.event.player.theolive.IntentToFallbackEvent
9
+ import com.theoplayer.android.api.event.player.theolive.TheoLiveEventTypes
10
+ import com.theoplayer.android.api.player.theolive.TheoLive
11
+
12
+ private const val EVENT_PROP_TYPE = "type"
13
+
14
+ private const val EVENT_PROP_DISTRIBUTION_ID = "distributionId"
15
+ private const val EVENT_PROP_ENDPOINT = "endpoint"
16
+
17
+ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitter: Emitter) {
18
+
19
+ interface Emitter {
20
+ fun emit(payload: WritableMap?)
21
+ }
22
+
23
+ init {
24
+ theoLiveApi.addEventListener(TheoLiveEventTypes.DISTRIBUTIONLOADSTART, this::onDistributionLoadStart)
25
+ theoLiveApi.addEventListener(TheoLiveEventTypes.DISTRIBUTIONOFFLINE, this::onDistributionOffline)
26
+ theoLiveApi.addEventListener(TheoLiveEventTypes.ENDPOINTLOADED, this::onEndPointLoaded)
27
+ theoLiveApi.addEventListener(TheoLiveEventTypes.INTENTTOFALLBACK, this::onIntentOfFallback)
28
+ }
29
+
30
+ fun destroy() {
31
+ theoLiveApi.removeEventListener(TheoLiveEventTypes.DISTRIBUTIONLOADSTART, this::onDistributionLoadStart)
32
+ theoLiveApi.removeEventListener(TheoLiveEventTypes.DISTRIBUTIONOFFLINE, this::onDistributionOffline)
33
+ theoLiveApi.removeEventListener(TheoLiveEventTypes.ENDPOINTLOADED, this::onEndPointLoaded)
34
+ theoLiveApi.removeEventListener(TheoLiveEventTypes.INTENTTOFALLBACK, this::onIntentOfFallback)
35
+ }
36
+
37
+ private fun onDistributionLoadStart(event: DistributionLoadStartEvent) {
38
+ emitter.emit(Arguments.createMap().apply {
39
+ putString(EVENT_PROP_TYPE, "distributionloadstart")
40
+ putString(EVENT_PROP_DISTRIBUTION_ID, event.getDistributionId())
41
+ })
42
+ }
43
+
44
+ private fun onDistributionOffline(event: DistributionOfflineEvent) {
45
+ emitter.emit(Arguments.createMap().apply {
46
+ putString(EVENT_PROP_TYPE, "distributionoffline")
47
+ putString(EVENT_PROP_DISTRIBUTION_ID, event.getDistributionId())
48
+ })
49
+ }
50
+
51
+ private fun onEndPointLoaded(event: EndpointLoadedEvent) {
52
+ emitter.emit(Arguments.createMap().apply {
53
+ putString(EVENT_PROP_TYPE, "endpointloaded")
54
+ putMap(EVENT_PROP_ENDPOINT, EndpointAdapter.fromEndpoint(event.getEndpoint()))
55
+ })
56
+ }
57
+
58
+ private fun onIntentOfFallback(_event: IntentToFallbackEvent) {
59
+ emitter.emit(Arguments.createMap().apply {
60
+ putString(EVENT_PROP_TYPE, "intenttofallback")
61
+ })
62
+ }
63
+ }
@@ -43,12 +43,12 @@ RCT_EXPORT_VIEW_PROPERTY(onNativeTextTrackListEvent, RCTDirectEventBlock);
43
43
  RCT_EXPORT_VIEW_PROPERTY(onNativeTextTrackEvent, RCTDirectEventBlock);
44
44
  RCT_EXPORT_VIEW_PROPERTY(onNativeMediaTrackListEvent, RCTDirectEventBlock);
45
45
  RCT_EXPORT_VIEW_PROPERTY(onNativeMediaTrackEvent, RCTDirectEventBlock);
46
+ RCT_EXPORT_VIEW_PROPERTY(onNativeDeviceOrientationChanged, RCTDirectEventBlock);
46
47
  RCT_EXPORT_VIEW_PROPERTY(onNativePlayerReady, RCTDirectEventBlock);
47
48
  RCT_EXPORT_VIEW_PROPERTY(onNativePresentationModeChange, RCTDirectEventBlock);
48
49
  RCT_EXPORT_VIEW_PROPERTY(onNativeResize, RCTDirectEventBlock);
49
-
50
50
  RCT_EXPORT_VIEW_PROPERTY(onNativeAdEvent, RCTDirectEventBlock);
51
-
51
+ RCT_EXPORT_VIEW_PROPERTY(onNativeTHEOliveEvent, RCTDirectEventBlock);
52
52
  RCT_EXPORT_VIEW_PROPERTY(onNativeCastEvent, RCTDirectEventBlock);
53
53
 
54
54
  @end
@@ -0,0 +1,38 @@
1
+ // THEOplayerRCTDeviceEventHandler.swift
2
+
3
+ import Foundation
4
+ import THEOplayerSDK
5
+
6
+ public class THEOplayerRCTDeviceEventHandler {
7
+ // MARK: Events
8
+ var onNativeDeviceOrientationChanged: RCTDirectEventBlock?
9
+
10
+ init() {
11
+ #if os(iOS)
12
+ UIDevice.current.beginGeneratingDeviceOrientationNotifications()
13
+ NotificationCenter.default.addObserver(
14
+ self,
15
+ selector: #selector(self.handleOrientationChange),
16
+ name: UIDevice.orientationDidChangeNotification,
17
+ object: nil
18
+ )
19
+ #endif
20
+ }
21
+
22
+ func destroy() {
23
+ #if os(iOS)
24
+ NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
25
+ UIDevice.current.endGeneratingDeviceOrientationNotifications()
26
+ #endif
27
+ }
28
+
29
+ #if os(iOS)
30
+ @objc private func handleOrientationChange() {
31
+ DispatchQueue.main.async {
32
+ if let forwardedNativeOrientationChanged = self.onNativeDeviceOrientationChanged {
33
+ forwardedNativeOrientationChanged([:])
34
+ }
35
+ }
36
+ }
37
+ #endif
38
+ }
@@ -59,6 +59,7 @@ let SD_PROP_OVERRIDE_LAYOUT: String = "overrideLayout"
59
59
  let SD_PROP_OVERRIDE_AD_SRC: String = "overrideAdSrc"
60
60
  let SD_PROP_USE_ID3: String = "useId3"
61
61
  let SD_PROP_RETRIEVE_POD_ID_URI: String = "retrievePodIdURI"
62
+ let SD_PROP_INITIALIZATION_DELAY: String = "initializationDelay"
62
63
  let SD_PROP_HLS_DATE_RANGE: String = "hlsDateRange"
63
64
  let SD_PROP_CMCD: String = "cmcd"
64
65
 
@@ -185,12 +186,14 @@ class THEOplayerRCTSourceDescriptionBuilder {
185
186
  */
186
187
  private static func buildTypedSource(_ typedSourceData: [String:Any]) -> TypedSource? {
187
188
  let contentProtection = extractDrmConfiguration(from: typedSourceData)
189
+ let integration = typedSourceData[SD_PROP_INTEGRATION] as? String
190
+ let type = typedSourceData[SD_PROP_TYPE] as? String
188
191
 
189
- if let integration = typedSourceData[SD_PROP_INTEGRATION] as? String, integration == "theolive" {
192
+ if integration == "theolive" || type == "theolive" {
190
193
  return THEOplayerRCTSourceDescriptionBuilder.buildTHEOliveDescription(typedSourceData)
191
194
  }
192
195
 
193
- if let type = typedSourceData[SD_PROP_TYPE] as? String, type == "millicast" {
196
+ if type == "millicast" {
194
197
  return THEOplayerRCTSourceDescriptionBuilder.buildMillicastDescription(typedSourceData)
195
198
  }
196
199
 
@@ -28,8 +28,10 @@ public class THEOplayerRCTView: UIView {
28
28
  public private(set) var broadcastEventHandler: THEOplayerRCTBroadcastEventHandler
29
29
  var textTrackEventHandler: THEOplayerRCTTextTrackEventHandler
30
30
  var mediaTrackEventHandler: THEOplayerRCTMediaTrackEventHandler
31
+ var deviceEventHandler: THEOplayerRCTDeviceEventHandler
31
32
  var metadataTrackEventHandler: THEOplayerRCTSideloadedMetadataTrackEventHandler
32
33
  var adEventHandler: THEOplayerRCTAdsEventHandler
34
+ var theoliveEventHandler: THEOplayerRCTTHEOliveEventHandler
33
35
  var castEventHandler: THEOplayerRCTCastEventHandler
34
36
  var presentationModeManager: THEOplayerRCTPresentationModeManager
35
37
  var backgroundAudioManager: THEOplayerRCTBackgroundAudioManager
@@ -93,8 +95,10 @@ public class THEOplayerRCTView: UIView {
93
95
  self.broadcastEventHandler = THEOplayerRCTBroadcastEventHandler()
94
96
  self.textTrackEventHandler = THEOplayerRCTTextTrackEventHandler()
95
97
  self.mediaTrackEventHandler = THEOplayerRCTMediaTrackEventHandler()
98
+ self.deviceEventHandler = THEOplayerRCTDeviceEventHandler()
96
99
  self.metadataTrackEventHandler = THEOplayerRCTSideloadedMetadataTrackEventHandler()
97
100
  self.adEventHandler = THEOplayerRCTAdsEventHandler()
101
+ self.theoliveEventHandler = THEOplayerRCTTHEOliveEventHandler()
98
102
  self.castEventHandler = THEOplayerRCTCastEventHandler()
99
103
  self.presentationModeManager = THEOplayerRCTPresentationModeManager()
100
104
  self.backgroundAudioManager = THEOplayerRCTBackgroundAudioManager()
@@ -114,7 +118,9 @@ public class THEOplayerRCTView: UIView {
114
118
  self.mainEventHandler.destroy()
115
119
  self.textTrackEventHandler.destroy()
116
120
  self.mediaTrackEventHandler.destroy()
121
+ self.deviceEventHandler.destroy()
117
122
  self.adEventHandler.destroy()
123
+ self.theoliveEventHandler.destroy()
118
124
  self.castEventHandler.destroy()
119
125
  self.nowPlayingManager.destroy()
120
126
  self.remoteCommandsManager.destroy()
@@ -149,6 +155,7 @@ public class THEOplayerRCTView: UIView {
149
155
  self.textTrackEventHandler.setPlayer(player)
150
156
  self.mediaTrackEventHandler.setPlayer(player)
151
157
  self.adEventHandler.setPlayer(player)
158
+ self.theoliveEventHandler.setPlayer(player)
152
159
  self.castEventHandler.setPlayer(player)
153
160
  self.nowPlayingManager.setPlayer(player)
154
161
  self.remoteCommandsManager.setPlayer(player)
@@ -389,6 +396,14 @@ public class THEOplayerRCTView: UIView {
389
396
  if DEBUG_VIEW { PrintUtils.printLog(logText: "[NATIVE] nativeMediaTrackEvent prop set.") }
390
397
  }
391
398
 
399
+ // MARK: - Observer based device event bridging
400
+
401
+ @objc(setOnNativeDeviceOrientationChanged:)
402
+ func setOnNativeDeviceOrientationChanged(nativeDeviceOrientationChanged: @escaping RCTDirectEventBlock) {
403
+ self.deviceEventHandler.onNativeDeviceOrientationChanged = nativeDeviceOrientationChanged
404
+ if DEBUG_VIEW { PrintUtils.printLog(logText: "[NATIVE] nativeDeviceOrientationChanged prop set.") }
405
+ }
406
+
392
407
  // MARK: - Listener based CAST event bridging
393
408
 
394
409
  @objc(setOnNativeCastEvent:)
@@ -404,4 +419,12 @@ public class THEOplayerRCTView: UIView {
404
419
  self.adEventHandler.onNativeAdEvent = nativeAdEvent
405
420
  if DEBUG_VIEW { PrintUtils.printLog(logText: "[NATIVE] nativeAdEvent prop set.") }
406
421
  }
422
+
423
+ // MARK: - Listener based THEOLIVE event bridging
424
+
425
+ @objc(setOnNativeTHEOliveEvent:)
426
+ func setOnNativeTHEOliveEvent(nativeTHEOliveEvent: @escaping RCTDirectEventBlock) {
427
+ self.theoliveEventHandler.onNativeTHEOliveEvent = nativeTHEOliveEvent
428
+ if DEBUG_VIEW { PrintUtils.printLog(logText: "[NATIVE] nativeTHEOliveEvent prop set.") }
429
+ }
407
430
  }
@@ -48,6 +48,8 @@ extension THEOplayerRCTSourceDescriptionBuilder {
48
48
  let adTagParameters = adsData[SD_PROP_AD_TAG_PARAMETERS] as? [String:String]
49
49
  let useId3 = adsData[SD_PROP_USE_ID3] as? Bool
50
50
  let retrievePodIdURI = adsData[SD_PROP_RETRIEVE_POD_ID_URI] as? String
51
+ let initializationDelay = adsData[SD_PROP_INITIALIZATION_DELAY] as? Double
52
+
51
53
  return THEOAdDescription(networkCode: networkCode,
52
54
  customAssetKey: customAssetKey,
53
55
  backdropDoubleBox: backdropDoubleBox,
@@ -57,7 +59,8 @@ extension THEOplayerRCTSourceDescriptionBuilder {
57
59
  adTagParameters: adTagParameters,
58
60
  useId3: useId3,
59
61
  sseEndpoint: sseEndpoint,
60
- retrievePodIdURI: retrievePodIdURI)
62
+ retrievePodIdURI: retrievePodIdURI,
63
+ initializationDelay: initializationDelay)
61
64
  #else
62
65
  return nil
63
66
  #endif
@@ -32,9 +32,9 @@ class THEOplayerRCTTHEOliveAPI: NSObject, RCTBridgeModule {
32
32
  let player = theView.player,
33
33
  let theolive = player.theoLive {
34
34
  var foundLatency: Double = -1
35
- /*if let currentLatency = theolive.currentLatency {
35
+ if let currentLatency = theolive.currentLatency {
36
36
  foundLatency = currentLatency
37
- }*/
37
+ }
38
38
  resolve(foundLatency)
39
39
  } else {
40
40
  if DEBUG_THEOLIVE_API { PrintUtils.printLog(logText: "[NATIVE] Could not get currentLatency (THEOlive module unavailable).") }
@@ -50,14 +50,14 @@ class THEOplayerRCTTHEOliveAPI: NSObject, RCTBridgeModule {
50
50
  let player = theView.player,
51
51
  let theolive = player.theoLive {
52
52
  var foundLatencies: [String:Any] = [:]
53
- /*if let latencies = theolive.latencies {
53
+ if let latencies = theolive.latencies {
54
54
  foundLatencies = [
55
55
  "engineLatency": latencies.engineLatency,
56
56
  "distributionLatency": latencies.distributionLatency,
57
57
  "playerLatency": latencies.playerLatency,
58
58
  "theoliveLatency": latencies.theoliveLatency
59
59
  ]
60
- }*/
60
+ }
61
61
  resolve(foundLatencies)
62
62
  } else {
63
63
  if DEBUG_THEOLIVE_API { PrintUtils.printLog(logText: "[NATIVE] Could not get latencies (THEOlive module unavailable).") }
@@ -0,0 +1,146 @@
1
+ // THEOplayerRCTTHEOliveEventHandler.swift
2
+
3
+ import Foundation
4
+ import THEOplayerSDK
5
+
6
+ #if canImport(THEOplayerTHEOliveIntegration)
7
+ import THEOplayerTHEOliveIntegration
8
+ #endif
9
+
10
+ let EVENT_TYPE_DISTRIBUTION_LOAD_START: String = "distributionloadstart"
11
+ let EVENT_TYPE_DISTRIBUTION_OFFLINE: String = "distributionoffline"
12
+ let EVENT_TYPE_ENDPOINT_LOADED: String = "endpointloaded"
13
+ let EVENT_TYPE_INTENT_TO_FALLBACK: String = "intenttofallback"
14
+
15
+ let THEOLIVE_EVENT_PROP_TYPE: String = "type"
16
+ let THEOLIVE_EVENT_PROP_DISTRIBUTION_ID: String = "distributionId"
17
+
18
+ class THEOplayerRCTTHEOliveEventHandler {
19
+ // MARK: Members
20
+ private weak var player: THEOplayer?
21
+
22
+ // MARK: Events
23
+ var onNativeTHEOliveEvent: RCTDirectEventBlock?
24
+
25
+ // MARK: Ad Listeners
26
+ private var distributionLoadStartListener: EventListener?
27
+ private var distributionOfflineListener: EventListener?
28
+ private var endPointLoadedListener: EventListener?
29
+ private var intentToFallbackListener: EventListener?
30
+
31
+ // MARK: - destruction
32
+ func destroy() {
33
+ // dettach listeners
34
+ self.dettachListeners()
35
+ }
36
+
37
+ // MARK: - player setup / breakdown
38
+ func setPlayer(_ player: THEOplayer) {
39
+ self.player = player;
40
+
41
+ // attach listeners
42
+ self.attachListeners()
43
+ }
44
+
45
+ // MARK: - attach/dettach Listeners
46
+ private func attachListeners() {
47
+ guard let player = self.player else {
48
+ return
49
+ }
50
+
51
+ #if canImport(THEOplayerTHEOliveIntegration)
52
+ // DISTRIBUTION_LOAD_START
53
+ self.distributionLoadStartListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.DISTRIBUTION_LOAD_START) { [weak self] event in
54
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received DistributionLoadStart event from THEOlive") }
55
+ if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent {
56
+ forwardedTHEOliveEvent([
57
+ THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_DISTRIBUTION_LOAD_START,
58
+ THEOLIVE_EVENT_PROP_DISTRIBUTION_ID: event.distributionId
59
+ ])
60
+ }
61
+ }
62
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionLoadStart listener attached to THEOplayer.theolive") }
63
+
64
+
65
+ // DISTRIBUTION_OFFLINE
66
+ self.distributionOfflineListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.DISTRIBUTION_OFFLINE) { [weak self] event in
67
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received DistributionOffline event from THEOlive") }
68
+ if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent {
69
+ forwardedTHEOliveEvent([
70
+ THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_DISTRIBUTION_OFFLINE,
71
+ THEOLIVE_EVENT_PROP_DISTRIBUTION_ID: event.distributionId
72
+ ])
73
+ }
74
+ }
75
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionOffline listener attached to THEOplayer.theolive") }
76
+
77
+ // ENDPOINT_LOADED
78
+ self.endPointLoadedListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.ENDPOINT_LOADED) { [weak self] event in
79
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received EndPointLoaded event from THEOlive") }
80
+ if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent {
81
+ forwardedTHEOliveEvent([
82
+ THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_ENDPOINT_LOADED
83
+ ])
84
+ }
85
+ }
86
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] EndPointLoaded listener attached to THEOplayer.theolive") }
87
+
88
+ // INTENT_TO_FALLBACK
89
+ self.intentToFallbackListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.INTENT_TO_FALLBACK) { [weak self] event in
90
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received IntentToFallback event from THEOlive") }
91
+ if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent {
92
+ forwardedTHEOliveEvent([
93
+ THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_INTENT_TO_FALLBACK
94
+ ])
95
+ }
96
+ }
97
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] IntentToFallback listener attached to THEOplayer.theolive") }
98
+ #endif
99
+ }
100
+
101
+ private func dettachListeners() {
102
+ guard let player = self.player else {
103
+ return
104
+ }
105
+
106
+ #if canImport(THEOplayerTHEOliveIntegration)
107
+ // DISTRIBUTION_LOAD_START
108
+ if let distributionLoadStartListener = self.distributionLoadStartListener {
109
+ player.theoLive?.removeEventListener(
110
+ type: THEOliveEventTypes.DISTRIBUTION_LOAD_START,
111
+ listener: distributionLoadStartListener
112
+ )
113
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionLoadStart listener detached from THEOplayer.theolive") }
114
+ }
115
+
116
+ // DISTRIBUTION_OFFLINE
117
+ if let distributionOfflineListener = self.distributionOfflineListener {
118
+ player.theoLive?.removeEventListener(
119
+ type: THEOliveEventTypes.DISTRIBUTION_OFFLINE,
120
+ listener: distributionOfflineListener
121
+ )
122
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionOffline listener detached from THEOplayer.theolive") }
123
+ }
124
+
125
+ // ENDPOINT_LOADED
126
+ if let endPointLoadedListener = self.endPointLoadedListener {
127
+ player.theoLive?.removeEventListener(
128
+ type: THEOliveEventTypes.ENDPOINT_LOADED,
129
+ listener: endPointLoadedListener
130
+ )
131
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] EndPointLoaded listener detached from THEOplayer.theolive") }
132
+ }
133
+
134
+ // INTENT_TO_FALLBACK
135
+ if let intentToFallbackListener = self.intentToFallbackListener {
136
+ player.theoLive?.removeEventListener(
137
+ type: THEOliveEventTypes.INTENT_TO_FALLBACK,
138
+ listener: intentToFallbackListener
139
+ )
140
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] IntentToFallback listener detached from THEOplayer.theolive") }
141
+ }
142
+
143
+ #endif
144
+
145
+ }
146
+ }