bitmovin-player-react-native 1.0.0-alpha.1 → 1.0.0-alpha.2

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.
@@ -16,11 +16,6 @@ import expo.modules.kotlin.modules.Module
16
16
  import expo.modules.kotlin.modules.ModuleDefinition
17
17
 
18
18
  class PlayerModule : Module() {
19
- /**
20
- * In-memory mapping from [NativeId]s to [Player] instances.
21
- * This must match the Registry pattern from legacy PlayerModule
22
- */
23
- private val players: Registry<Player> = mutableMapOf()
24
19
 
25
20
  val mediaSessionPlaybackManager by lazy { MediaSessionPlaybackManager(appContext) }
26
21
 
@@ -33,68 +28,68 @@ class PlayerModule : Module() {
33
28
 
34
29
  OnDestroy {
35
30
  // Clean up all players when module is destroyed
36
- players.values.forEach { player ->
31
+ PlayerRegistry.getAllPlayers().forEach { player ->
37
32
  try {
38
33
  player.destroy()
39
34
  } catch (e: Exception) {
40
35
  // Log but don't crash on cleanup
41
36
  }
42
37
  }
43
- players.clear()
38
+ PlayerRegistry.clear()
44
39
  }
45
40
 
46
41
  AsyncFunction("play") { nativeId: NativeId ->
47
- val player = players[nativeId]
42
+ val player = PlayerRegistry.getPlayer(nativeId)
48
43
  player?.play()
49
44
  }.runOnQueue(Queues.MAIN)
50
45
 
51
46
  AsyncFunction("pause") { nativeId: NativeId ->
52
- val player = players[nativeId]
47
+ val player = PlayerRegistry.getPlayer(nativeId)
53
48
  player?.pause()
54
49
  }.runOnQueue(Queues.MAIN)
55
50
 
56
51
  AsyncFunction("mute") { nativeId: NativeId ->
57
- val player = players[nativeId]
52
+ val player = PlayerRegistry.getPlayer(nativeId)
58
53
  player?.mute()
59
54
  }.runOnQueue(Queues.MAIN)
60
55
 
61
56
  AsyncFunction("unmute") { nativeId: NativeId ->
62
- val player = players[nativeId]
57
+ val player = PlayerRegistry.getPlayer(nativeId)
63
58
  player?.unmute()
64
59
  }.runOnQueue(Queues.MAIN)
65
60
 
66
61
  AsyncFunction("seek") { nativeId: NativeId, time: Double ->
67
- val player = players[nativeId]
62
+ val player = PlayerRegistry.getPlayer(nativeId)
68
63
  player?.seek(time)
69
64
  }.runOnQueue(Queues.MAIN)
70
65
 
71
66
  AsyncFunction("timeShift") { nativeId: NativeId, offset: Double ->
72
- val player = players[nativeId]
67
+ val player = PlayerRegistry.getPlayer(nativeId)
73
68
  player?.timeShift(offset)
74
69
  }.runOnQueue(Queues.MAIN)
75
70
 
76
71
  AsyncFunction("destroy") { nativeId: NativeId ->
77
- val player = players[nativeId]
72
+ val player = PlayerRegistry.getPlayer(nativeId)
78
73
  if (player != null) {
79
74
  // Note: MediaSession cleanup would need to be handled here
80
75
  // For now, just destroy the player and remove from registry
81
76
  player.destroy()
82
- players.remove(nativeId)
77
+ PlayerRegistry.unregister(nativeId)
83
78
  }
84
79
  }.runOnQueue(Queues.MAIN)
85
80
 
86
81
  AsyncFunction("setVolume") { nativeId: NativeId, volume: Double ->
87
- val player = players[nativeId]
82
+ val player = PlayerRegistry.getPlayer(nativeId)
88
83
  player?.volume = volume.toInt()
89
84
  }.runOnQueue(Queues.MAIN)
90
85
 
91
86
  AsyncFunction("getVolume") { nativeId: NativeId ->
92
- val player = players[nativeId]
87
+ val player = PlayerRegistry.getPlayer(nativeId)
93
88
  return@AsyncFunction player?.volume?.toDouble()
94
89
  }
95
90
 
96
91
  AsyncFunction("currentTime") { nativeId: NativeId, mode: String? ->
97
- val player = players[nativeId]
92
+ val player = PlayerRegistry.getPlayer(nativeId)
98
93
  return@AsyncFunction when {
99
94
  player == null -> null
100
95
  mode == "relative" -> player.currentTime + player.playbackTimeOffsetToRelativeTime
@@ -104,62 +99,62 @@ class PlayerModule : Module() {
104
99
  }
105
100
 
106
101
  AsyncFunction("isPlaying") { nativeId: NativeId ->
107
- val player = players[nativeId]
102
+ val player = PlayerRegistry.getPlayer(nativeId)
108
103
  return@AsyncFunction player?.isPlaying
109
104
  }
110
105
 
111
106
  AsyncFunction("isPaused") { nativeId: NativeId ->
112
- val player = players[nativeId]
107
+ val player = PlayerRegistry.getPlayer(nativeId)
113
108
  return@AsyncFunction player?.isPaused
114
109
  }
115
110
 
116
111
  AsyncFunction("duration") { nativeId: NativeId ->
117
- val player = players[nativeId]
112
+ val player = PlayerRegistry.getPlayer(nativeId)
118
113
  return@AsyncFunction player?.duration
119
114
  }
120
115
 
121
116
  AsyncFunction("isMuted") { nativeId: NativeId ->
122
- val player = players[nativeId]
117
+ val player = PlayerRegistry.getPlayer(nativeId)
123
118
  return@AsyncFunction player?.isMuted
124
119
  }
125
120
 
126
121
  AsyncFunction("unload") { nativeId: NativeId ->
127
- val player = players[nativeId]
122
+ val player = PlayerRegistry.getPlayer(nativeId)
128
123
  player?.unload()
129
124
  }.runOnQueue(Queues.MAIN)
130
125
 
131
126
  AsyncFunction("getTimeShift") { nativeId: NativeId ->
132
- val player = players[nativeId]
127
+ val player = PlayerRegistry.getPlayer(nativeId)
133
128
  return@AsyncFunction player?.timeShift
134
129
  }
135
130
 
136
131
  AsyncFunction("isLive") { nativeId: NativeId ->
137
- val player = players[nativeId]
132
+ val player = PlayerRegistry.getPlayer(nativeId)
138
133
  return@AsyncFunction player?.isLive
139
134
  }
140
135
 
141
136
  AsyncFunction("getMaxTimeShift") { nativeId: NativeId ->
142
- val player = players[nativeId]
137
+ val player = PlayerRegistry.getPlayer(nativeId)
143
138
  return@AsyncFunction player?.maxTimeShift
144
139
  }
145
140
 
146
141
  AsyncFunction("getPlaybackSpeed") { nativeId: NativeId ->
147
- val player = players[nativeId]
142
+ val player = PlayerRegistry.getPlayer(nativeId)
148
143
  return@AsyncFunction player?.playbackSpeed?.toDouble()
149
144
  }
150
145
 
151
146
  AsyncFunction("setPlaybackSpeed") { nativeId: NativeId, playbackSpeed: Double ->
152
- val player = players[nativeId]
147
+ val player = PlayerRegistry.getPlayer(nativeId)
153
148
  player?.playbackSpeed = playbackSpeed.toFloat()
154
149
  }.runOnQueue(Queues.MAIN)
155
150
 
156
151
  AsyncFunction("isAd") { nativeId: NativeId ->
157
- val player = players[nativeId]
152
+ val player = PlayerRegistry.getPlayer(nativeId)
158
153
  return@AsyncFunction player?.isAd
159
154
  }
160
155
 
161
156
  AsyncFunction("setMaxSelectableBitrate") { nativeId: NativeId, maxBitrate: Double ->
162
- val player = players[nativeId]
157
+ val player = PlayerRegistry.getPlayer(nativeId)
163
158
  player?.setMaxSelectableVideoBitrate(maxBitrate.toInt())
164
159
  }.runOnQueue(Queues.MAIN)
165
160
 
@@ -174,27 +169,27 @@ class PlayerModule : Module() {
174
169
  }
175
170
 
176
171
  AsyncFunction("isCastAvailable") { nativeId: NativeId ->
177
- val player = players[nativeId]
172
+ val player = PlayerRegistry.getPlayer(nativeId)
178
173
  return@AsyncFunction player?.isCastAvailable
179
174
  }
180
175
 
181
176
  AsyncFunction("isCasting") { nativeId: NativeId ->
182
- val player = players[nativeId]
177
+ val player = PlayerRegistry.getPlayer(nativeId)
183
178
  return@AsyncFunction player?.isCasting
184
179
  }
185
180
 
186
181
  AsyncFunction("castVideo") { nativeId: NativeId ->
187
- val player = players[nativeId]
182
+ val player = PlayerRegistry.getPlayer(nativeId)
188
183
  player?.castVideo()
189
184
  }.runOnQueue(Queues.MAIN)
190
185
 
191
186
  AsyncFunction("castStop") { nativeId: NativeId ->
192
- val player = players[nativeId]
187
+ val player = PlayerRegistry.getPlayer(nativeId)
193
188
  player?.castStop()
194
189
  }.runOnQueue(Queues.MAIN)
195
190
 
196
191
  AsyncFunction("skipAd") { nativeId: NativeId ->
197
- val player = players[nativeId]
192
+ val player = PlayerRegistry.getPlayer(nativeId)
198
193
  player?.skipAd()
199
194
  }.runOnQueue(Queues.MAIN)
200
195
 
@@ -204,57 +199,57 @@ class PlayerModule : Module() {
204
199
  }
205
200
 
206
201
  AsyncFunction("getAudioTrack") { nativeId: NativeId ->
207
- val player = players[nativeId]
202
+ val player = PlayerRegistry.getPlayer(nativeId)
208
203
  return@AsyncFunction player?.source?.selectedAudioTrack?.toJson()
209
204
  }
210
205
 
211
206
  AsyncFunction("getAvailableAudioTracks") { nativeId: NativeId ->
212
- val player = players[nativeId]
207
+ val player = PlayerRegistry.getPlayer(nativeId)
213
208
  return@AsyncFunction player?.source?.availableAudioTracks?.map { it.toJson() } ?: emptyList()
214
209
  }
215
210
 
216
211
  AsyncFunction("setAudioTrack") { nativeId: NativeId, trackIdentifier: String ->
217
- val player = players[nativeId]
212
+ val player = PlayerRegistry.getPlayer(nativeId)
218
213
  player?.source?.setAudioTrack(trackIdentifier)
219
214
  }.runOnQueue(Queues.MAIN)
220
215
 
221
216
  AsyncFunction("getSubtitleTrack") { nativeId: NativeId ->
222
- val player = players[nativeId]
217
+ val player = PlayerRegistry.getPlayer(nativeId)
223
218
  return@AsyncFunction player?.source?.selectedSubtitleTrack?.toJson()
224
219
  }
225
220
 
226
221
  AsyncFunction("getAvailableSubtitles") { nativeId: NativeId ->
227
- val player = players[nativeId]
222
+ val player = PlayerRegistry.getPlayer(nativeId)
228
223
  return@AsyncFunction player?.source?.availableSubtitleTracks?.map { it.toJson() } ?: emptyList()
229
224
  }
230
225
 
231
226
  AsyncFunction("setSubtitleTrack") { nativeId: NativeId, trackIdentifier: String? ->
232
- val player = players[nativeId]
227
+ val player = PlayerRegistry.getPlayer(nativeId)
233
228
  player?.source?.setSubtitleTrack(trackIdentifier)
234
229
  }.runOnQueue(Queues.MAIN)
235
230
 
236
231
  AsyncFunction("getVideoQuality") { nativeId: NativeId ->
237
- val player = players[nativeId]
232
+ val player = PlayerRegistry.getPlayer(nativeId)
238
233
  return@AsyncFunction player?.videoQuality?.toJson()
239
234
  }
240
235
 
241
236
  AsyncFunction("getAvailableVideoQualities") { nativeId: NativeId ->
242
- val player = players[nativeId]
237
+ val player = PlayerRegistry.getPlayer(nativeId)
243
238
  return@AsyncFunction player?.availableVideoQualities?.map { it.toJson() } ?: emptyList()
244
239
  }
245
240
 
246
241
  AsyncFunction("setVideoQuality") { nativeId: NativeId, qualityId: String ->
247
- val player = players[nativeId]
242
+ val player = PlayerRegistry.getPlayer(nativeId)
248
243
  player?.source?.setVideoQuality(qualityId)
249
244
  }.runOnQueue(Queues.MAIN)
250
245
 
251
246
  AsyncFunction("getThumbnail") { nativeId: NativeId, time: Double ->
252
- val player = players[nativeId]
247
+ val player = PlayerRegistry.getPlayer(nativeId)
253
248
  return@AsyncFunction player?.getThumbnail(time)?.toJson()
254
249
  }
255
250
  AsyncFunction("loadOfflineContent") { nativeId: NativeId, offlineContentManagerBridgeId: String,
256
251
  options: Map<String, Any>?, ->
257
- val player = players[nativeId] ?: return@AsyncFunction
252
+ val player = PlayerRegistry.getPlayer(nativeId) ?: return@AsyncFunction
258
253
  val offlineContentManagerBridge = appContext.registry.getModule<OfflineModule>()
259
254
  ?.getOfflineContentManagerBridge(offlineContentManagerBridgeId)
260
255
 
@@ -264,7 +259,7 @@ class PlayerModule : Module() {
264
259
  }.runOnQueue(Queues.MAIN)
265
260
 
266
261
  AsyncFunction("scheduleAd") { nativeId: NativeId, adItemJson: Map<String, Any> ->
267
- val player = players[nativeId]
262
+ val player = PlayerRegistry.getPlayer(nativeId)
268
263
  val adItem = adItemJson.toAdItem()
269
264
  if (player != null && adItem != null) {
270
265
  player.scheduleAd(adItem)
@@ -282,7 +277,7 @@ class PlayerModule : Module() {
282
277
  }.runOnQueue(Queues.MAIN)
283
278
 
284
279
  AsyncFunction("loadSource") { nativeId: NativeId, sourceNativeId: NativeId ->
285
- val player = players[nativeId]
280
+ val player = PlayerRegistry.getPlayer(nativeId)
286
281
  val source = appContext.registry.getModule<SourceModule>()?.getSourceOrNull(sourceNativeId)
287
282
  if (player != null && source != null) {
288
283
  player.load(source)
@@ -290,7 +285,7 @@ class PlayerModule : Module() {
290
285
  }.runOnQueue(Queues.MAIN)
291
286
 
292
287
  AsyncFunction("source") { nativeId: NativeId ->
293
- val player = players[nativeId]
288
+ val player = PlayerRegistry.getPlayer(nativeId)
294
289
  return@AsyncFunction player?.source?.toJson()
295
290
  }
296
291
  }
@@ -302,7 +297,7 @@ class PlayerModule : Module() {
302
297
  decoderNativeId: NativeId?,
303
298
  analyticsConfigJson: Map<String, Any>?,
304
299
  ) {
305
- if (players.containsKey(nativeId)) {
300
+ if (PlayerRegistry.hasPlayer(nativeId)) {
306
301
  // Player already exists for this nativeId
307
302
  return
308
303
  }
@@ -340,7 +335,7 @@ class PlayerModule : Module() {
340
335
  } else {
341
336
  Player.create(applicationContext, playerConfig)
342
337
  }
343
- players[nativeId] = player
338
+ PlayerRegistry.register(player, nativeId)
344
339
 
345
340
  if (enableMediaSession) {
346
341
  mediaSessionPlaybackManager.setupMediaSessionPlayback(nativeId)
@@ -348,5 +343,5 @@ class PlayerModule : Module() {
348
343
  }
349
344
 
350
345
  // CRITICAL: This method must remain available for cross-module access
351
- fun getPlayerOrNull(nativeId: NativeId): Player? = players[nativeId]
346
+ fun getPlayerOrNull(nativeId: NativeId): Player? = PlayerRegistry.getPlayer(nativeId)
352
347
  }
@@ -0,0 +1,78 @@
1
+ package com.bitmovin.player.reactnative
2
+
3
+ import com.bitmovin.player.api.Player
4
+ import java.util.concurrent.ConcurrentHashMap
5
+
6
+ /**
7
+ * Global registry for Player instances that allows static access from anywhere in native code
8
+ * without requiring access to the PlayerModule instance or Expo runtime.
9
+ */
10
+ object PlayerRegistry {
11
+ private val players: Registry<Player> = ConcurrentHashMap()
12
+
13
+ /**
14
+ * Register a player instance with the given native ID.
15
+ */
16
+ @JvmStatic
17
+ fun register(player: Player, nativeId: NativeId) {
18
+ players[nativeId] = player
19
+ }
20
+
21
+ /**
22
+ * Unregister a player instance with the given native ID.
23
+ */
24
+ @JvmStatic
25
+ fun unregister(nativeId: NativeId) {
26
+ players.remove(nativeId)
27
+ }
28
+
29
+ /**
30
+ * Get a player instance by native ID.
31
+ * Returns null if no player is registered with the given ID.
32
+ */
33
+ @JvmStatic
34
+ fun getPlayer(nativeId: NativeId): Player? {
35
+ return players[nativeId]
36
+ }
37
+
38
+ /**
39
+ * Get all registered player instances.
40
+ */
41
+ @JvmStatic
42
+ fun getAllPlayers(): List<Player> {
43
+ return players.values.toList()
44
+ }
45
+
46
+ /**
47
+ * Get all registered native IDs.
48
+ */
49
+ @JvmStatic
50
+ fun getAllNativeIds(): List<NativeId> {
51
+ return players.keys.toList()
52
+ }
53
+
54
+ /**
55
+ * Check if a player is registered with the given native ID.
56
+ */
57
+ @JvmStatic
58
+ fun hasPlayer(nativeId: NativeId): Boolean {
59
+ return players.containsKey(nativeId)
60
+ }
61
+
62
+ /**
63
+ * Clear all registered players.
64
+ * Note: This does not destroy the players, just removes them from the registry.
65
+ */
66
+ @JvmStatic
67
+ fun clear() {
68
+ players.clear()
69
+ }
70
+
71
+ /**
72
+ * Get the count of registered players.
73
+ */
74
+ @JvmStatic
75
+ fun count(): Int {
76
+ return players.size
77
+ }
78
+ }
@@ -6,5 +6,5 @@ import { PlayerViewProps } from './properties';
6
6
  *
7
7
  * @param options configuration options
8
8
  */
9
- export declare function PlayerView({ viewRef, style, player, config, fullscreenHandler, customMessageHandler, isFullscreenRequested, scalingMode, isPictureInPictureRequested, ...props }: PlayerViewProps): false | React.JSX.Element;
9
+ export declare function PlayerView({ viewRef, style, player, config, fullscreenHandler, customMessageHandler, isFullscreenRequested, scalingMode, isPictureInPictureRequested, ...props }: PlayerViewProps): React.JSX.Element | null;
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PlayerView/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAO3D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAW/C;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,KAAK,EACL,MAAM,EACN,MAAM,EACN,iBAAiB,EACjB,oBAAoB,EACpB,qBAA6B,EAC7B,WAAW,EACX,2BAAmC,EACnC,GAAG,KAAK,EACT,EAAE,eAAe,6BAqJjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PlayerView/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAO3D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAW/C;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,KAAK,EACL,MAAM,EACN,MAAM,EACN,iBAAiB,EACjB,oBAAoB,EACpB,qBAA6B,EAC7B,WAAW,EACX,2BAAmC,EACnC,GAAG,KAAK,EACT,EAAE,eAAe,4BAuJjB"}
@@ -67,6 +67,9 @@ export function PlayerView({ viewRef, style, player, config, fullscreenHandler,
67
67
  viewRef.current = nativeView.current;
68
68
  }
69
69
  }, [viewRef, nativeView]);
70
- return (isPlayerInitialized && (<NativePlayerView ref={nativeView} style={nativeViewStyle} config={nativePlayerViewConfig} isFullscreenRequested={isFullscreenRequested} isPictureInPictureRequested={isPictureInPictureRequested} scalingMode={scalingMode} fullscreenBridgeId={fullscreenBridge.current?.nativeId} onBmpAdBreakFinished={proxy(props.onAdBreakFinished)} onBmpAdBreakStarted={proxy(props.onAdBreakStarted)} onBmpAdClicked={proxy(props.onAdClicked)} onBmpAdError={proxy(props.onAdError)} onBmpAdFinished={proxy(props.onAdFinished)} onBmpAdManifestLoad={proxy(props.onAdManifestLoad)} onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)} onBmpAdQuartile={proxy(props.onAdQuartile)} onBmpAdScheduled={proxy(props.onAdScheduled)} onBmpAdSkipped={proxy(props.onAdSkipped)} onBmpAdStarted={proxy(props.onAdStarted)} onBmpCastAvailable={proxy(props.onCastAvailable)} onBmpCastPaused={proxy(props.onCastPaused)} onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)} onBmpCastPlaying={proxy(props.onCastPlaying)} onBmpCastStarted={proxy(props.onCastStarted)} onBmpCastStart={proxy(props.onCastStart)} onBmpCastStopped={proxy(props.onCastStopped)} onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)} onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)} onBmpCueEnter={proxy(props.onCueEnter)} onBmpCueExit={proxy(props.onCueExit)} onBmpDestroy={proxy(props.onDestroy)} onBmpEvent={proxy(props.onEvent)} onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)} onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)} onBmpFullscreenEnter={proxy(props.onFullscreenEnter)} onBmpFullscreenExit={proxy(props.onFullscreenExit)} onBmpMuted={proxy(props.onMuted)} onBmpPaused={proxy(props.onPaused)} onBmpPictureInPictureAvailabilityChanged={proxy(props.onPictureInPictureAvailabilityChanged)} onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)} onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)} onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)} onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)} onBmpPlay={proxy(props.onPlay)} onBmpPlaybackFinished={proxy(props.onPlaybackFinished)} onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)} onBmpPlayerActive={proxy(props.onPlayerActive)} onBmpPlayerError={proxy(props.onPlayerError)} onBmpPlayerWarning={proxy(props.onPlayerWarning)} onBmpPlaying={proxy(props.onPlaying)} onBmpReady={proxy(props.onReady)} onBmpSeek={proxy(props.onSeek)} onBmpSeeked={proxy(props.onSeeked)} onBmpTimeShift={proxy(props.onTimeShift)} onBmpTimeShifted={proxy(props.onTimeShifted)} onBmpStallStarted={proxy(props.onStallStarted)} onBmpStallEnded={proxy(props.onStallEnded)} onBmpSourceError={proxy(props.onSourceError)} onBmpSourceLoad={proxy(props.onSourceLoad)} onBmpSourceLoaded={proxy(props.onSourceLoaded)} onBmpSourceUnloaded={proxy(props.onSourceUnloaded)} onBmpSourceWarning={proxy(props.onSourceWarning)} onBmpAudioAdded={proxy(props.onAudioAdded)} onBmpAudioChanged={proxy(props.onAudioChanged)} onBmpAudioRemoved={proxy(props.onAudioRemoved)} onBmpSubtitleAdded={proxy(props.onSubtitleAdded)} onBmpSubtitleChanged={proxy(props.onSubtitleChanged)} onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)} onBmpTimeChanged={proxy(props.onTimeChanged)} onBmpUnmuted={proxy(props.onUnmuted)} onBmpVideoDownloadQualityChanged={proxy(props.onVideoDownloadQualityChanged)} onBmpVideoPlaybackQualityChanged={proxy(props.onVideoPlaybackQualityChanged)} onBmpDownloadFinished={proxy(props.onDownloadFinished)}/>));
70
+ if (!isPlayerInitialized) {
71
+ return null;
72
+ }
73
+ return (<NativePlayerView ref={nativeView} style={nativeViewStyle} config={nativePlayerViewConfig} isFullscreenRequested={isFullscreenRequested} isPictureInPictureRequested={isPictureInPictureRequested} scalingMode={scalingMode} fullscreenBridgeId={fullscreenBridge.current?.nativeId} onBmpAdBreakFinished={proxy(props.onAdBreakFinished)} onBmpAdBreakStarted={proxy(props.onAdBreakStarted)} onBmpAdClicked={proxy(props.onAdClicked)} onBmpAdError={proxy(props.onAdError)} onBmpAdFinished={proxy(props.onAdFinished)} onBmpAdManifestLoad={proxy(props.onAdManifestLoad)} onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)} onBmpAdQuartile={proxy(props.onAdQuartile)} onBmpAdScheduled={proxy(props.onAdScheduled)} onBmpAdSkipped={proxy(props.onAdSkipped)} onBmpAdStarted={proxy(props.onAdStarted)} onBmpCastAvailable={proxy(props.onCastAvailable)} onBmpCastPaused={proxy(props.onCastPaused)} onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)} onBmpCastPlaying={proxy(props.onCastPlaying)} onBmpCastStarted={proxy(props.onCastStarted)} onBmpCastStart={proxy(props.onCastStart)} onBmpCastStopped={proxy(props.onCastStopped)} onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)} onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)} onBmpCueEnter={proxy(props.onCueEnter)} onBmpCueExit={proxy(props.onCueExit)} onBmpDestroy={proxy(props.onDestroy)} onBmpEvent={proxy(props.onEvent)} onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)} onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)} onBmpFullscreenEnter={proxy(props.onFullscreenEnter)} onBmpFullscreenExit={proxy(props.onFullscreenExit)} onBmpMuted={proxy(props.onMuted)} onBmpPaused={proxy(props.onPaused)} onBmpPictureInPictureAvailabilityChanged={proxy(props.onPictureInPictureAvailabilityChanged)} onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)} onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)} onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)} onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)} onBmpPlay={proxy(props.onPlay)} onBmpPlaybackFinished={proxy(props.onPlaybackFinished)} onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)} onBmpPlayerActive={proxy(props.onPlayerActive)} onBmpPlayerError={proxy(props.onPlayerError)} onBmpPlayerWarning={proxy(props.onPlayerWarning)} onBmpPlaying={proxy(props.onPlaying)} onBmpReady={proxy(props.onReady)} onBmpSeek={proxy(props.onSeek)} onBmpSeeked={proxy(props.onSeeked)} onBmpTimeShift={proxy(props.onTimeShift)} onBmpTimeShifted={proxy(props.onTimeShifted)} onBmpStallStarted={proxy(props.onStallStarted)} onBmpStallEnded={proxy(props.onStallEnded)} onBmpSourceError={proxy(props.onSourceError)} onBmpSourceLoad={proxy(props.onSourceLoad)} onBmpSourceLoaded={proxy(props.onSourceLoaded)} onBmpSourceUnloaded={proxy(props.onSourceUnloaded)} onBmpSourceWarning={proxy(props.onSourceWarning)} onBmpAudioAdded={proxy(props.onAudioAdded)} onBmpAudioChanged={proxy(props.onAudioChanged)} onBmpAudioRemoved={proxy(props.onAudioRemoved)} onBmpSubtitleAdded={proxy(props.onSubtitleAdded)} onBmpSubtitleChanged={proxy(props.onSubtitleChanged)} onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)} onBmpTimeChanged={proxy(props.onTimeChanged)} onBmpUnmuted={proxy(props.onUnmuted)} onBmpVideoDownloadQualityChanged={proxy(props.onVideoDownloadQualityChanged)} onBmpVideoPlaybackQualityChanged={proxy(props.onVideoPlaybackQualityChanged)} onBmpDownloadFinished={proxy(props.onDownloadFinished)}/>);
71
74
  }
72
75
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/PlayerView/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useRef, useEffect, useState } from 'react';\nimport { StyleSheet } from 'react-native';\nimport { useKeepAwake } from 'expo-keep-awake';\nimport { NativePlayerView, NativePlayerViewConfig } from './native';\nimport { useProxy } from '../../hooks/useProxy';\nimport { FullscreenHandlerBridge } from '../../ui/fullscreenhandlerbridge';\nimport { CustomMessageHandlerBridge } from '../../ui/custommessagehandlerbridge';\nimport { PlayerViewProps } from './properties';\n\n/**\n * Base style that initializes the native view frame when no width/height prop has been set.\n */\nconst styles = StyleSheet.create({\n baseStyle: {\n alignSelf: 'stretch',\n },\n});\n\n/**\n * Component that provides the Bitmovin Player UI and default UI handling to an attached `Player` instance.\n * This component needs a `Player` instance to work properly so make sure one is passed to it as a prop.\n *\n * @param options configuration options\n */\nexport function PlayerView({\n viewRef,\n style,\n player,\n config,\n fullscreenHandler,\n customMessageHandler,\n isFullscreenRequested = false,\n scalingMode,\n isPictureInPictureRequested = false,\n ...props\n}: PlayerViewProps) {\n // Keep the device awake while the PlayerView is mounted\n useKeepAwake();\n\n const nativeView = useRef(viewRef?.current || null);\n\n // Native events proxy helper.\n const proxy = useProxy(nativeView);\n // Style resulting from merging `baseStyle` and `props.style`.\n const nativeViewStyle = StyleSheet.flatten([styles.baseStyle, style]);\n\n const fullscreenBridge: React.RefObject<FullscreenHandlerBridge | undefined> =\n useRef(undefined);\n if (fullscreenHandler && !fullscreenBridge.current) {\n fullscreenBridge.current = new FullscreenHandlerBridge();\n }\n if (fullscreenBridge.current) {\n fullscreenBridge.current.setFullscreenHandler(fullscreenHandler);\n }\n\n const customMessageHandlerBridge: React.RefObject<\n CustomMessageHandlerBridge | undefined\n > = useRef(undefined);\n if (customMessageHandler && !customMessageHandlerBridge.current) {\n customMessageHandlerBridge.current = new CustomMessageHandlerBridge();\n }\n if (customMessageHandlerBridge.current && customMessageHandler) {\n customMessageHandlerBridge.current.setCustomMessageHandler(\n customMessageHandler\n );\n }\n\n const nativePlayerViewConfig: NativePlayerViewConfig = {\n playerId: player.nativeId,\n customMessageHandlerBridgeId: customMessageHandlerBridge.current?.nativeId,\n enableBackgroundPlayback:\n player.config?.playbackConfig?.isBackgroundPlaybackEnabled,\n isPictureInPictureEnabledOnPlayer:\n player.config?.playbackConfig?.isPictureInPictureEnabled,\n userInterfaceTypeName: player.config?.styleConfig?.userInterfaceType,\n playerViewConfig: config,\n };\n\n const [isPlayerInitialized, setIsPlayerInitialized] = useState(false);\n\n useEffect(() => {\n player.initialize().then(() => {\n setIsPlayerInitialized(true);\n // call attach player on native view if switched to AsyncFunction for RNPlayerViewExpo\n });\n\n return () => {\n fullscreenBridge.current?.destroy();\n fullscreenBridge.current = undefined;\n customMessageHandlerBridge.current?.destroy();\n customMessageHandlerBridge.current = undefined;\n };\n }, [player, fullscreenBridge, customMessageHandlerBridge]);\n\n useEffect(() => {\n if (viewRef) {\n viewRef.current = nativeView.current;\n }\n }, [viewRef, nativeView]);\n\n return (\n isPlayerInitialized && (\n <NativePlayerView\n ref={nativeView}\n style={nativeViewStyle}\n config={nativePlayerViewConfig}\n isFullscreenRequested={isFullscreenRequested}\n isPictureInPictureRequested={isPictureInPictureRequested}\n scalingMode={scalingMode}\n fullscreenBridgeId={fullscreenBridge.current?.nativeId}\n onBmpAdBreakFinished={proxy(props.onAdBreakFinished)}\n onBmpAdBreakStarted={proxy(props.onAdBreakStarted)}\n onBmpAdClicked={proxy(props.onAdClicked)}\n onBmpAdError={proxy(props.onAdError)}\n onBmpAdFinished={proxy(props.onAdFinished)}\n onBmpAdManifestLoad={proxy(props.onAdManifestLoad)}\n onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)}\n onBmpAdQuartile={proxy(props.onAdQuartile)}\n onBmpAdScheduled={proxy(props.onAdScheduled)}\n onBmpAdSkipped={proxy(props.onAdSkipped)}\n onBmpAdStarted={proxy(props.onAdStarted)}\n onBmpCastAvailable={proxy(props.onCastAvailable)}\n onBmpCastPaused={proxy(props.onCastPaused)}\n onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)}\n onBmpCastPlaying={proxy(props.onCastPlaying)}\n onBmpCastStarted={proxy(props.onCastStarted)}\n onBmpCastStart={proxy(props.onCastStart)}\n onBmpCastStopped={proxy(props.onCastStopped)}\n onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)}\n onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)}\n onBmpCueEnter={proxy(props.onCueEnter)}\n onBmpCueExit={proxy(props.onCueExit)}\n onBmpDestroy={proxy(props.onDestroy)}\n onBmpEvent={proxy(props.onEvent)}\n onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)}\n onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)}\n onBmpFullscreenEnter={proxy(props.onFullscreenEnter)}\n onBmpFullscreenExit={proxy(props.onFullscreenExit)}\n onBmpMuted={proxy(props.onMuted)}\n onBmpPaused={proxy(props.onPaused)}\n onBmpPictureInPictureAvailabilityChanged={proxy(\n props.onPictureInPictureAvailabilityChanged\n )}\n onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)}\n onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)}\n onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)}\n onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)}\n onBmpPlay={proxy(props.onPlay)}\n onBmpPlaybackFinished={proxy(props.onPlaybackFinished)}\n onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)}\n onBmpPlayerActive={proxy(props.onPlayerActive)}\n onBmpPlayerError={proxy(props.onPlayerError)}\n onBmpPlayerWarning={proxy(props.onPlayerWarning)}\n onBmpPlaying={proxy(props.onPlaying)}\n onBmpReady={proxy(props.onReady)}\n onBmpSeek={proxy(props.onSeek)}\n onBmpSeeked={proxy(props.onSeeked)}\n onBmpTimeShift={proxy(props.onTimeShift)}\n onBmpTimeShifted={proxy(props.onTimeShifted)}\n onBmpStallStarted={proxy(props.onStallStarted)}\n onBmpStallEnded={proxy(props.onStallEnded)}\n onBmpSourceError={proxy(props.onSourceError)}\n onBmpSourceLoad={proxy(props.onSourceLoad)}\n onBmpSourceLoaded={proxy(props.onSourceLoaded)}\n onBmpSourceUnloaded={proxy(props.onSourceUnloaded)}\n onBmpSourceWarning={proxy(props.onSourceWarning)}\n onBmpAudioAdded={proxy(props.onAudioAdded)}\n onBmpAudioChanged={proxy(props.onAudioChanged)}\n onBmpAudioRemoved={proxy(props.onAudioRemoved)}\n onBmpSubtitleAdded={proxy(props.onSubtitleAdded)}\n onBmpSubtitleChanged={proxy(props.onSubtitleChanged)}\n onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)}\n onBmpTimeChanged={proxy(props.onTimeChanged)}\n onBmpUnmuted={proxy(props.onUnmuted)}\n onBmpVideoDownloadQualityChanged={proxy(\n props.onVideoDownloadQualityChanged\n )}\n onBmpVideoPlaybackQualityChanged={proxy(\n props.onVideoPlaybackQualityChanged\n )}\n onBmpDownloadFinished={proxy(props.onDownloadFinished)}\n />\n )\n );\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/PlayerView/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useRef, useEffect, useState } from 'react';\nimport { StyleSheet } from 'react-native';\nimport { useKeepAwake } from 'expo-keep-awake';\nimport { NativePlayerView, NativePlayerViewConfig } from './native';\nimport { useProxy } from '../../hooks/useProxy';\nimport { FullscreenHandlerBridge } from '../../ui/fullscreenhandlerbridge';\nimport { CustomMessageHandlerBridge } from '../../ui/custommessagehandlerbridge';\nimport { PlayerViewProps } from './properties';\n\n/**\n * Base style that initializes the native view frame when no width/height prop has been set.\n */\nconst styles = StyleSheet.create({\n baseStyle: {\n alignSelf: 'stretch',\n },\n});\n\n/**\n * Component that provides the Bitmovin Player UI and default UI handling to an attached `Player` instance.\n * This component needs a `Player` instance to work properly so make sure one is passed to it as a prop.\n *\n * @param options configuration options\n */\nexport function PlayerView({\n viewRef,\n style,\n player,\n config,\n fullscreenHandler,\n customMessageHandler,\n isFullscreenRequested = false,\n scalingMode,\n isPictureInPictureRequested = false,\n ...props\n}: PlayerViewProps) {\n // Keep the device awake while the PlayerView is mounted\n useKeepAwake();\n\n const nativeView = useRef(viewRef?.current || null);\n\n // Native events proxy helper.\n const proxy = useProxy(nativeView);\n // Style resulting from merging `baseStyle` and `props.style`.\n const nativeViewStyle = StyleSheet.flatten([styles.baseStyle, style]);\n\n const fullscreenBridge: React.RefObject<FullscreenHandlerBridge | undefined> =\n useRef(undefined);\n if (fullscreenHandler && !fullscreenBridge.current) {\n fullscreenBridge.current = new FullscreenHandlerBridge();\n }\n if (fullscreenBridge.current) {\n fullscreenBridge.current.setFullscreenHandler(fullscreenHandler);\n }\n\n const customMessageHandlerBridge: React.RefObject<\n CustomMessageHandlerBridge | undefined\n > = useRef(undefined);\n if (customMessageHandler && !customMessageHandlerBridge.current) {\n customMessageHandlerBridge.current = new CustomMessageHandlerBridge();\n }\n if (customMessageHandlerBridge.current && customMessageHandler) {\n customMessageHandlerBridge.current.setCustomMessageHandler(\n customMessageHandler\n );\n }\n\n const nativePlayerViewConfig: NativePlayerViewConfig = {\n playerId: player.nativeId,\n customMessageHandlerBridgeId: customMessageHandlerBridge.current?.nativeId,\n enableBackgroundPlayback:\n player.config?.playbackConfig?.isBackgroundPlaybackEnabled,\n isPictureInPictureEnabledOnPlayer:\n player.config?.playbackConfig?.isPictureInPictureEnabled,\n userInterfaceTypeName: player.config?.styleConfig?.userInterfaceType,\n playerViewConfig: config,\n };\n\n const [isPlayerInitialized, setIsPlayerInitialized] = useState(false);\n\n useEffect(() => {\n player.initialize().then(() => {\n setIsPlayerInitialized(true);\n // call attach player on native view if switched to AsyncFunction for RNPlayerViewExpo\n });\n\n return () => {\n fullscreenBridge.current?.destroy();\n fullscreenBridge.current = undefined;\n customMessageHandlerBridge.current?.destroy();\n customMessageHandlerBridge.current = undefined;\n };\n }, [player, fullscreenBridge, customMessageHandlerBridge]);\n\n useEffect(() => {\n if (viewRef) {\n viewRef.current = nativeView.current;\n }\n }, [viewRef, nativeView]);\n\n if (!isPlayerInitialized) {\n return null;\n }\n\n return (\n <NativePlayerView\n ref={nativeView}\n style={nativeViewStyle}\n config={nativePlayerViewConfig}\n isFullscreenRequested={isFullscreenRequested}\n isPictureInPictureRequested={isPictureInPictureRequested}\n scalingMode={scalingMode}\n fullscreenBridgeId={fullscreenBridge.current?.nativeId}\n onBmpAdBreakFinished={proxy(props.onAdBreakFinished)}\n onBmpAdBreakStarted={proxy(props.onAdBreakStarted)}\n onBmpAdClicked={proxy(props.onAdClicked)}\n onBmpAdError={proxy(props.onAdError)}\n onBmpAdFinished={proxy(props.onAdFinished)}\n onBmpAdManifestLoad={proxy(props.onAdManifestLoad)}\n onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)}\n onBmpAdQuartile={proxy(props.onAdQuartile)}\n onBmpAdScheduled={proxy(props.onAdScheduled)}\n onBmpAdSkipped={proxy(props.onAdSkipped)}\n onBmpAdStarted={proxy(props.onAdStarted)}\n onBmpCastAvailable={proxy(props.onCastAvailable)}\n onBmpCastPaused={proxy(props.onCastPaused)}\n onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)}\n onBmpCastPlaying={proxy(props.onCastPlaying)}\n onBmpCastStarted={proxy(props.onCastStarted)}\n onBmpCastStart={proxy(props.onCastStart)}\n onBmpCastStopped={proxy(props.onCastStopped)}\n onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)}\n onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)}\n onBmpCueEnter={proxy(props.onCueEnter)}\n onBmpCueExit={proxy(props.onCueExit)}\n onBmpDestroy={proxy(props.onDestroy)}\n onBmpEvent={proxy(props.onEvent)}\n onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)}\n onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)}\n onBmpFullscreenEnter={proxy(props.onFullscreenEnter)}\n onBmpFullscreenExit={proxy(props.onFullscreenExit)}\n onBmpMuted={proxy(props.onMuted)}\n onBmpPaused={proxy(props.onPaused)}\n onBmpPictureInPictureAvailabilityChanged={proxy(\n props.onPictureInPictureAvailabilityChanged\n )}\n onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)}\n onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)}\n onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)}\n onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)}\n onBmpPlay={proxy(props.onPlay)}\n onBmpPlaybackFinished={proxy(props.onPlaybackFinished)}\n onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)}\n onBmpPlayerActive={proxy(props.onPlayerActive)}\n onBmpPlayerError={proxy(props.onPlayerError)}\n onBmpPlayerWarning={proxy(props.onPlayerWarning)}\n onBmpPlaying={proxy(props.onPlaying)}\n onBmpReady={proxy(props.onReady)}\n onBmpSeek={proxy(props.onSeek)}\n onBmpSeeked={proxy(props.onSeeked)}\n onBmpTimeShift={proxy(props.onTimeShift)}\n onBmpTimeShifted={proxy(props.onTimeShifted)}\n onBmpStallStarted={proxy(props.onStallStarted)}\n onBmpStallEnded={proxy(props.onStallEnded)}\n onBmpSourceError={proxy(props.onSourceError)}\n onBmpSourceLoad={proxy(props.onSourceLoad)}\n onBmpSourceLoaded={proxy(props.onSourceLoaded)}\n onBmpSourceUnloaded={proxy(props.onSourceUnloaded)}\n onBmpSourceWarning={proxy(props.onSourceWarning)}\n onBmpAudioAdded={proxy(props.onAudioAdded)}\n onBmpAudioChanged={proxy(props.onAudioChanged)}\n onBmpAudioRemoved={proxy(props.onAudioRemoved)}\n onBmpSubtitleAdded={proxy(props.onSubtitleAdded)}\n onBmpSubtitleChanged={proxy(props.onSubtitleChanged)}\n onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)}\n onBmpTimeChanged={proxy(props.onTimeChanged)}\n onBmpUnmuted={proxy(props.onUnmuted)}\n onBmpVideoDownloadQualityChanged={proxy(\n props.onVideoDownloadQualityChanged\n )}\n onBmpVideoPlaybackQualityChanged={proxy(\n props.onVideoPlaybackQualityChanged\n )}\n onBmpDownloadFinished={proxy(props.onDownloadFinished)}\n />\n );\n}\n"]}
@@ -8,7 +8,10 @@ public class AppLifecycleDelegate: ExpoAppDelegateSubscriber {
8
8
  ) -> Bool {
9
9
  // TODO: Add support for OfflineConfig via config plugin
10
10
  #if os(iOS)
11
- OfflineManager.initializeOfflineManager()
11
+ if let offlineSupportEnabled = Bundle.main.infoDictionary?["BitmovinPlayerOfflineSupportEnabled"] as? Bool,
12
+ offlineSupportEnabled {
13
+ OfflineManager.initializeOfflineManager()
14
+ }
12
15
  #endif
13
16
  return true
14
17
  }
@@ -2,8 +2,6 @@ import BitmovinPlayer
2
2
  import ExpoModulesCore
3
3
 
4
4
  public class PlayerModule: Module {
5
- private var players: Registry<Player> = [:]
6
-
7
5
  // swiftlint:disable:next function_body_length
8
6
  public func definition() -> ModuleDefinition {
9
7
  Name("PlayerModule")
@@ -12,117 +10,121 @@ public class PlayerModule: Module {
12
10
  // Destroy all players on the main thread when the module is deallocated.
13
11
  // This is necessary when the IMA SDK is present in the app,
14
12
  // as it may crash if the players are destroyed on a background thread.
15
- DispatchQueue.main.async { [players] in
16
- players.values.forEach { $0.destroy() }
13
+ DispatchQueue.main.async {
14
+ PlayerRegistry.getAllPlayers().forEach { $0.destroy() }
15
+ PlayerRegistry.clear()
17
16
  }
18
17
  }
19
- AsyncFunction("play") { [weak self] (nativeId: NativeId) in
20
- self?.players[nativeId]?.play()
18
+ AsyncFunction("play") { (nativeId: NativeId) in
19
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.play()
21
20
  }.runOnQueue(.main)
22
- AsyncFunction("pause") { [weak self] (nativeId: NativeId) in
23
- self?.players[nativeId]?.pause()
21
+ AsyncFunction("pause") { (nativeId: NativeId) in
22
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.pause()
24
23
  }.runOnQueue(.main)
25
- AsyncFunction("mute") { [weak self] (nativeId: NativeId) in
26
- self?.players[nativeId]?.mute()
24
+ AsyncFunction("mute") { (nativeId: NativeId) in
25
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.mute()
27
26
  }.runOnQueue(.main)
28
- AsyncFunction("unmute") { [weak self] (nativeId: NativeId) in
29
- self?.players[nativeId]?.unmute()
27
+ AsyncFunction("unmute") { (nativeId: NativeId) in
28
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.unmute()
30
29
  }.runOnQueue(.main)
31
- AsyncFunction("seek") { [weak self] (nativeId: NativeId, time: Double) in
32
- self?.players[nativeId]?.seek(time: time)
30
+ AsyncFunction("seek") { (nativeId: NativeId, time: Double) in
31
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.seek(time: time)
33
32
  }.runOnQueue(.main)
34
- AsyncFunction("timeShift") { [weak self] (nativeId: NativeId, offset: Double) in
35
- self?.players[nativeId]?.timeShift = offset
33
+ AsyncFunction("timeShift") { (nativeId: NativeId, offset: Double) in
34
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.timeShift = offset
36
35
  }.runOnQueue(.main)
37
- AsyncFunction("destroy") { [weak self] (nativeId: NativeId) in
38
- if let player = self?.players[nativeId] {
36
+ AsyncFunction("destroy") { (nativeId: NativeId) in
37
+ if let player = PlayerRegistry.getPlayer(nativeId: nativeId) {
39
38
  player.destroy()
40
- self?.players[nativeId] = nil
39
+ PlayerRegistry.unregister(nativeId: nativeId)
41
40
  }
42
41
  }.runOnQueue(.main)
43
- AsyncFunction("setVolume") { [weak self] (nativeId: NativeId, volume: Int) in
44
- self?.players[nativeId]?.volume = volume
42
+ AsyncFunction("setVolume") { (nativeId: NativeId, volume: Int) in
43
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.volume = volume
45
44
  }.runOnQueue(.main)
46
- AsyncFunction("unload") { [weak self] (nativeId: NativeId) in
47
- self?.players[nativeId]?.unload()
45
+ AsyncFunction("unload") { (nativeId: NativeId) in
46
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.unload()
48
47
  }.runOnQueue(.main)
49
- AsyncFunction("setPlaybackSpeed") { [weak self] (nativeId: NativeId, playbackSpeed: Float) in
50
- self?.players[nativeId]?.playbackSpeed = playbackSpeed
48
+ AsyncFunction("setPlaybackSpeed") { (nativeId: NativeId, playbackSpeed: Float) in
49
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.playbackSpeed = playbackSpeed
51
50
  }.runOnQueue(.main)
52
- AsyncFunction("setMaxSelectableBitrate") { [weak self] (nativeId: NativeId, maxSelectableBitrate: Int) in
53
- self?.players[nativeId]?.maxSelectableBitrate = UInt(maxSelectableBitrate)
51
+ AsyncFunction("setMaxSelectableBitrate") { (nativeId: NativeId, maxSelectableBitrate: Int) in
52
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.maxSelectableBitrate = UInt(maxSelectableBitrate)
54
53
  }.runOnQueue(.main)
55
- AsyncFunction("getVolume") { [weak self] (nativeId: NativeId) -> Int? in
56
- self?.players[nativeId]?.volume
54
+ AsyncFunction("getVolume") { (nativeId: NativeId) -> Int? in
55
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.volume
57
56
  }.runOnQueue(.main)
58
- AsyncFunction("currentTime") { [weak self] (nativeId: NativeId, mode: String?) -> Double? in
59
- let player = self?.players[nativeId]
57
+ AsyncFunction("currentTime") { (nativeId: NativeId, mode: String?) -> Double? in
58
+ let player = PlayerRegistry.getPlayer(nativeId: nativeId)
60
59
  if let mode {
61
60
  return player?.currentTime(RCTConvert.timeMode(mode))
62
61
  }
63
62
  return player?.currentTime
64
63
  }.runOnQueue(.main)
65
- AsyncFunction("isPlaying") { [weak self] (nativeId: NativeId) -> Bool? in
66
- self?.players[nativeId]?.isPlaying
64
+ AsyncFunction("isPlaying") { (nativeId: NativeId) -> Bool? in
65
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isPlaying
67
66
  }.runOnQueue(.main)
68
- AsyncFunction("isPaused") { [weak self] (nativeId: NativeId) -> Bool? in
69
- self?.players[nativeId]?.isPaused
67
+ AsyncFunction("isPaused") { (nativeId: NativeId) -> Bool? in
68
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isPaused
70
69
  }.runOnQueue(.main)
71
- AsyncFunction("duration") { [weak self] (nativeId: NativeId) -> Double? in
72
- self?.players[nativeId]?.duration
70
+ AsyncFunction("duration") { (nativeId: NativeId) -> Double? in
71
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.duration
73
72
  }.runOnQueue(.main)
74
- AsyncFunction("isMuted") { [weak self] (nativeId: NativeId) -> Bool? in
75
- self?.players[nativeId]?.isMuted
73
+ AsyncFunction("isMuted") { (nativeId: NativeId) -> Bool? in
74
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isMuted
76
75
  }.runOnQueue(.main)
77
- AsyncFunction("getTimeShift") { [weak self] (nativeId: NativeId) -> Double? in
78
- self?.players[nativeId]?.timeShift
76
+ AsyncFunction("getTimeShift") { (nativeId: NativeId) -> Double? in
77
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.timeShift
79
78
  }.runOnQueue(.main)
80
- AsyncFunction("isLive") { [weak self] (nativeId: NativeId) -> Bool? in
81
- self?.players[nativeId]?.isLive
79
+ AsyncFunction("isLive") { (nativeId: NativeId) -> Bool? in
80
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isLive
82
81
  }.runOnQueue(.main)
83
- AsyncFunction("getMaxTimeShift") { [weak self] (nativeId: NativeId) -> Double? in
84
- self?.players[nativeId]?.maxTimeShift
82
+ AsyncFunction("getMaxTimeShift") { (nativeId: NativeId) -> Double? in
83
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.maxTimeShift
85
84
  }.runOnQueue(.main)
86
- AsyncFunction("getPlaybackSpeed") { [weak self] (nativeId: NativeId) -> Float? in
87
- self?.players[nativeId]?.playbackSpeed
85
+ AsyncFunction("getPlaybackSpeed") { (nativeId: NativeId) -> Float? in
86
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.playbackSpeed
88
87
  }.runOnQueue(.main)
89
- AsyncFunction("isAd") { [weak self] (nativeId: NativeId) -> Bool? in
90
- self?.players[nativeId]?.isAd
88
+ AsyncFunction("isAd") { (nativeId: NativeId) -> Bool? in
89
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isAd
91
90
  }.runOnQueue(.main)
92
- AsyncFunction("canPlayAtPlaybackSpeed") { [weak self] (nativeId: NativeId, playbackSpeed: Float) -> Bool? in
93
- self?.players[nativeId]?.canPlay(atPlaybackSpeed: playbackSpeed)
91
+ AsyncFunction("canPlayAtPlaybackSpeed") { (nativeId: NativeId, playbackSpeed: Float) -> Bool? in
92
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.canPlay(atPlaybackSpeed: playbackSpeed)
94
93
  }.runOnQueue(.main)
95
- AsyncFunction("getAudioTrack") { [weak self] (nativeId: NativeId) -> [String: Any]? in
96
- RCTConvert.audioTrackJson(self?.players[nativeId]?.audio)
94
+ AsyncFunction("getAudioTrack") { (nativeId: NativeId) -> [String: Any]? in
95
+ RCTConvert.audioTrackJson(PlayerRegistry.getPlayer(nativeId: nativeId)?.audio)
97
96
  }.runOnQueue(.main)
98
- AsyncFunction("getAvailableAudioTracks") { [weak self] (nativeId: NativeId) -> [[String: Any]] in
99
- self?.players[nativeId]?.availableAudio.compactMap { RCTConvert.audioTrackJson($0) } ?? []
97
+ AsyncFunction("getAvailableAudioTracks") { (nativeId: NativeId) -> [[String: Any]] in
98
+ PlayerRegistry.getPlayer(nativeId: nativeId)?
99
+ .availableAudio.compactMap { RCTConvert.audioTrackJson($0) } ?? []
100
100
  }.runOnQueue(.main)
101
- AsyncFunction("setAudioTrack") { [weak self] (nativeId: NativeId, trackIdentifier: String) in
102
- self?.players[nativeId]?.setAudio(trackIdentifier: trackIdentifier)
101
+ AsyncFunction("setAudioTrack") { (nativeId: NativeId, trackIdentifier: String) in
102
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.setAudio(trackIdentifier: trackIdentifier)
103
103
  }.runOnQueue(.main)
104
- AsyncFunction("getSubtitleTrack") { [weak self] (nativeId: NativeId) -> [String: Any]? in
105
- RCTConvert.subtitleTrackJson(self?.players[nativeId]?.subtitle)
104
+ AsyncFunction("getSubtitleTrack") { (nativeId: NativeId) -> [String: Any]? in
105
+ RCTConvert.subtitleTrackJson(PlayerRegistry.getPlayer(nativeId: nativeId)?.subtitle)
106
106
  }.runOnQueue(.main)
107
- AsyncFunction("getAvailableSubtitles") { [weak self] (nativeId: NativeId) -> [[String: Any]] in
108
- self?.players[nativeId]?.availableSubtitles.compactMap { RCTConvert.subtitleTrackJson($0) } ?? []
107
+ AsyncFunction("getAvailableSubtitles") { (nativeId: NativeId) -> [[String: Any]] in
108
+ PlayerRegistry.getPlayer(nativeId: nativeId)?
109
+ .availableSubtitles.compactMap { RCTConvert.subtitleTrackJson($0) } ?? []
109
110
  }.runOnQueue(.main)
110
- AsyncFunction("setSubtitleTrack") { [weak self] (nativeId: NativeId, trackIdentifier: String?) in
111
- self?.players[nativeId]?.setSubtitle(trackIdentifier: trackIdentifier)
111
+ AsyncFunction("setSubtitleTrack") { (nativeId: NativeId, trackIdentifier: String?) in
112
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.setSubtitle(trackIdentifier: trackIdentifier)
112
113
  }.runOnQueue(.main)
113
114
 
114
- AsyncFunction("getVideoQuality") { [weak self] (nativeId: NativeId) -> [String: Any]? in
115
- RCTConvert.toJson(videoQuality: self?.players[nativeId]?.videoQuality)
115
+ AsyncFunction("getVideoQuality") { (nativeId: NativeId) -> [String: Any]? in
116
+ RCTConvert.toJson(videoQuality: PlayerRegistry.getPlayer(nativeId: nativeId)?.videoQuality)
116
117
  }.runOnQueue(.main)
117
- AsyncFunction("getAvailableVideoQualities") { [weak self] (nativeId: NativeId) -> [[String: Any]] in
118
- self?.players[nativeId]?.availableVideoQualities.compactMap { RCTConvert.toJson(videoQuality: $0) } ?? []
118
+ AsyncFunction("getAvailableVideoQualities") { (nativeId: NativeId) -> [[String: Any]] in
119
+ PlayerRegistry.getPlayer(nativeId: nativeId)?
120
+ .availableVideoQualities.compactMap { RCTConvert.toJson(videoQuality: $0) } ?? []
119
121
  }.runOnQueue(.main)
120
- AsyncFunction("getThumbnail") { [weak self] (nativeId: NativeId, time: Double) -> [String: Any]? in
121
- RCTConvert.toJson(thumbnail: self?.players[nativeId]?.thumbnail(forTime: time))
122
+ AsyncFunction("getThumbnail") { (nativeId: NativeId, time: Double) -> [String: Any]? in
123
+ RCTConvert.toJson(thumbnail: PlayerRegistry.getPlayer(nativeId: nativeId)?.thumbnail(forTime: time))
122
124
  }.runOnQueue(.main)
123
125
  AsyncFunction("loadOfflineContent") { [weak self] (nativeId: NativeId, bridgeId: String, options: [String: Any]?) in // swiftlint:disable:this line_length
124
126
  #if os(iOS)
125
- guard let player = self?.players[nativeId],
127
+ guard let player = PlayerRegistry.getPlayer(nativeId: nativeId),
126
128
  let offlineModule = self?.appContext?.moduleRegistry.get(OfflineModule.self),
127
129
  let offlineContentManagerBridge = offlineModule.retrieve(bridgeId) else { return }
128
130
  let optionsDictionary = options ?? [:]
@@ -134,55 +136,57 @@ public class PlayerModule: Module {
134
136
  player.load(sourceConfig: offlineSourceConfig)
135
137
  #endif
136
138
  }.runOnQueue(.main)
137
- AsyncFunction("scheduleAd") { [weak self] (nativeId: NativeId, adItemJson: [String: Any]) in
139
+ AsyncFunction("scheduleAd") { (nativeId: NativeId, adItemJson: [String: Any]) in
138
140
  guard let adItem = RCTConvert.adItem(adItemJson) else { return }
139
- self?.players[nativeId]?.scheduleAd(adItem: adItem)
141
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.scheduleAd(adItem: adItem)
140
142
  }.runOnQueue(.main)
141
- AsyncFunction("isAirPlayActive") { [weak self] (nativeId: NativeId) -> Bool? in
143
+ AsyncFunction("isAirPlayActive") { (nativeId: NativeId) -> Bool? in
142
144
  #if os(iOS)
143
- return self?.players[nativeId]?.isAirPlayActive
145
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isAirPlayActive
144
146
  #else
145
- return nil
147
+ nil
146
148
  #endif
147
149
  }.runOnQueue(.main)
148
- AsyncFunction("isAirPlayAvailable") { [weak self] (nativeId: NativeId) -> Bool? in
150
+ AsyncFunction("isAirPlayAvailable") { (nativeId: NativeId) -> Bool? in
149
151
  #if os(iOS)
150
- return self?.players[nativeId]?.allowsAirPlay
152
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.allowsAirPlay
151
153
  #else
152
- return nil
154
+ nil
153
155
  #endif
154
156
  }.runOnQueue(.main)
155
- AsyncFunction("isCastAvailable") { [weak self] (nativeId: NativeId) -> Bool? in
156
- self?.players[nativeId]?.isCastAvailable
157
+ AsyncFunction("isCastAvailable") { (nativeId: NativeId) -> Bool? in
158
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isCastAvailable
157
159
  }.runOnQueue(.main)
158
- AsyncFunction("isCasting") { [weak self] (nativeId: NativeId) -> Bool? in
159
- self?.players[nativeId]?.isCasting
160
+ AsyncFunction("isCasting") { (nativeId: NativeId) -> Bool? in
161
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.isCasting
160
162
  }.runOnQueue(.main)
161
- AsyncFunction("castVideo") { [weak self] (nativeId: NativeId) in
162
- self?.players[nativeId]?.castVideo()
163
+ AsyncFunction("castVideo") { (nativeId: NativeId) in
164
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.castVideo()
163
165
  }.runOnQueue(.main)
164
- AsyncFunction("castStop") { [weak self] (nativeId: NativeId) in
165
- self?.players[nativeId]?.castStop()
166
+ AsyncFunction("castStop") { (nativeId: NativeId) in
167
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.castStop()
166
168
  }.runOnQueue(.main)
167
- AsyncFunction("skipAd") { [weak self] (nativeId: NativeId) in
168
- self?.players[nativeId]?.skipAd()
169
+ AsyncFunction("skipAd") { (nativeId: NativeId) in
170
+ PlayerRegistry.getPlayer(nativeId: nativeId)?.skipAd()
169
171
  }.runOnQueue(.main)
170
172
  AsyncFunction(
171
173
  "initializeWithConfig"
172
174
  ) { [weak self] (nativeId: NativeId, config: [String: Any]?, networkNativeId: NativeId?, _: String?) in // swiftlint:disable:this line_length
173
- guard self?.players[nativeId] == nil, let playerConfig = RCTConvert.playerConfig(config) else { return }
175
+ guard !PlayerRegistry.hasPlayer(nativeId: nativeId),
176
+ let playerConfig = RCTConvert.playerConfig(config) else { return }
174
177
  #if os(iOS)
175
178
  self?.setupRemoteControlConfig(playerConfig.remoteControlConfig)
176
179
  #endif
177
180
  if let networkNativeId, let networkConfig = self?.setupNetworkConfig(nativeId: networkNativeId) {
178
181
  playerConfig.networkConfig = networkConfig
179
182
  }
180
- self?.players[nativeId] = PlayerFactory.create(playerConfig: playerConfig)
183
+ let player = PlayerFactory.create(playerConfig: playerConfig)
184
+ PlayerRegistry.register(player: player, nativeId: nativeId)
181
185
  }.runOnQueue(.main)
182
186
  AsyncFunction(
183
187
  "initializeWithAnalyticsConfig"
184
188
  ) { [weak self] (nativeId: NativeId, analyticsConfig: [String: Any]?, config: [String: Any]?, networkNativeId: NativeId?, _: String?) in // swiftlint:disable:this line_length
185
- guard self?.players[nativeId] == nil,
189
+ guard !PlayerRegistry.hasPlayer(nativeId: nativeId),
186
190
  let playerConfig = RCTConvert.playerConfig(config),
187
191
  let analyticsConfig = RCTConvert.analyticsConfig(analyticsConfig) else { return } // swiftlint:disable:this line_length
188
192
  #if os(iOS)
@@ -192,14 +196,15 @@ public class PlayerModule: Module {
192
196
  playerConfig.networkConfig = networkConfig
193
197
  }
194
198
  let defaultMetadata = RCTConvert.analyticsDefaultMetadataFromAnalyticsConfig(analyticsConfig)
195
- self?.players[nativeId] = PlayerFactory.create(
199
+ let player = PlayerFactory.create(
196
200
  playerConfig: playerConfig,
197
201
  analyticsConfig: analyticsConfig,
198
202
  defaultMetadata: defaultMetadata ?? DefaultMetadata()
199
203
  )
204
+ PlayerRegistry.register(player: player, nativeId: nativeId)
200
205
  }.runOnQueue(.main)
201
206
  AsyncFunction("loadSource") { [weak self] (nativeId: NativeId, sourceNativeId: NativeId) in
202
- guard let player = self?.players[nativeId],
207
+ guard let player = PlayerRegistry.getPlayer(nativeId: nativeId),
203
208
  let sourceModule = self?.appContext?.moduleRegistry.get(SourceModule.self), // swiftlint:disable:this line_length
204
209
  let source = sourceModule.retrieve(sourceNativeId) else { return }
205
210
  player.load(source: source)
@@ -209,7 +214,7 @@ public class PlayerModule: Module {
209
214
  /// This needs to stay stable to maintain compatibility for cross-module access..
210
215
  @objc
211
216
  public func retrieve(_ nativeId: NativeId) -> Player? {
212
- players[nativeId]
217
+ PlayerRegistry.getPlayer(nativeId: nativeId)
213
218
  }
214
219
 
215
220
  private func setupRemoteControlConfig(_ remoteControlConfig: RemoteControlConfig) {
@@ -0,0 +1,88 @@
1
+ import BitmovinPlayer
2
+ import ExpoModulesCore
3
+
4
+ /**
5
+ * Global registry for Player instances that allows static access from anywhere in native code
6
+ * without requiring access to the PlayerModule instance or Expo runtime.
7
+ */
8
+ public class PlayerRegistry {
9
+ private static let shared = PlayerRegistry()
10
+ private var players: Registry<Player> = [:]
11
+ private let queue = DispatchQueue(label: "PlayerRegistry", attributes: .concurrent)
12
+
13
+ private init() {}
14
+
15
+ /**
16
+ * Register a player instance with the given native ID.
17
+ */
18
+ public static func register(player: Player, nativeId: NativeId) {
19
+ shared.queue.async(flags: .barrier) {
20
+ shared.players[nativeId] = player
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Unregister a player instance with the given native ID.
26
+ */
27
+ public static func unregister(nativeId: NativeId) {
28
+ shared.queue.async(flags: .barrier) {
29
+ shared.players[nativeId] = nil
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get a player instance by native ID.
35
+ * Returns nil if no player is registered with the given ID.
36
+ */
37
+ public static func getPlayer(nativeId: NativeId) -> Player? {
38
+ shared.queue.sync {
39
+ shared.players[nativeId]
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Get all registered player instances.
45
+ */
46
+ public static func getAllPlayers() -> [Player] {
47
+ shared.queue.sync {
48
+ Array(shared.players.values)
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Get all registered native IDs.
54
+ */
55
+ public static func getAllNativeIds() -> [NativeId] {
56
+ shared.queue.sync {
57
+ Array(shared.players.keys)
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Check if a player is registered with the given native ID.
63
+ */
64
+ public static func hasPlayer(nativeId: NativeId) -> Bool {
65
+ shared.queue.sync {
66
+ shared.players[nativeId] != nil
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Clear all registered players.
72
+ * Note: This does not destroy the players, just removes them from the registry.
73
+ */
74
+ public static func clear() {
75
+ shared.queue.async(flags: .barrier) {
76
+ shared.players.removeAll()
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Get the count of registered players.
82
+ */
83
+ public static func count() -> Int {
84
+ shared.queue.sync {
85
+ shared.players.count
86
+ }
87
+ }
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitmovin-player-react-native",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "Official React Native bindings for Bitmovin's mobile Player SDKs.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const config_plugins_1 = require("expo/config-plugins");
4
+ const isTV = !!process.env.EXPO_TV;
4
5
  const withBitmovinIosConfig = (config, { playerLicenseKey, features }) => {
5
6
  const offlineFeatureConfig = typeof features.offline === 'object'
6
7
  ? features.offline
@@ -25,29 +26,33 @@ const withBitmovinIosConfig = (config, { playerLicenseKey, features }) => {
25
26
  backgroundModes.add('audio');
26
27
  config.modResults['UIBackgroundModes'] = Array.from(backgroundModes);
27
28
  }
28
- if (offlineFeatureConfig?.ios?.isEnabled) {
29
- config.modResults['BitmovinPlayerOfflineSupportEnabled'] = true;
30
- }
31
- if (googleCastIosConfig) {
32
- const appId = googleCastIosConfig.appId || 'FFE417E5';
33
- const localNetworkUsageDescription = googleCastIosConfig.localNetworkUsageDescription ||
34
- '${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network.';
35
- config.modResults['NSBonjourServices'] = [
36
- '_googlecast._tcp',
37
- `_${appId}._googlecast._tcp`,
38
- ];
39
- config.modResults['NSLocalNetworkUsageDescription'] =
40
- localNetworkUsageDescription;
41
- }
42
- return config;
43
- });
44
- config = (0, config_plugins_1.withPodfileProperties)(config, (config) => {
45
- if (googleCastIosConfig) {
46
- config.modResults['BITMOVIN_GOOGLE_CAST_SDK_VERSION'] =
47
- googleCastIosConfig.version;
29
+ if (!isTV) {
30
+ if (offlineFeatureConfig?.ios?.isEnabled) {
31
+ config.modResults['BitmovinPlayerOfflineSupportEnabled'] = true;
32
+ }
33
+ if (googleCastIosConfig) {
34
+ const appId = googleCastIosConfig.appId || 'FFE417E5';
35
+ const localNetworkUsageDescription = googleCastIosConfig.localNetworkUsageDescription ||
36
+ '${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network.';
37
+ config.modResults['NSBonjourServices'] = [
38
+ '_googlecast._tcp',
39
+ `_${appId}._googlecast._tcp`,
40
+ ];
41
+ config.modResults['NSLocalNetworkUsageDescription'] =
42
+ localNetworkUsageDescription;
43
+ }
48
44
  }
49
45
  return config;
50
46
  });
47
+ if (!isTV) {
48
+ config = (0, config_plugins_1.withPodfileProperties)(config, (config) => {
49
+ if (googleCastIosConfig) {
50
+ config.modResults['BITMOVIN_GOOGLE_CAST_SDK_VERSION'] =
51
+ googleCastIosConfig.version;
52
+ }
53
+ return config;
54
+ });
55
+ }
51
56
  return config;
52
57
  };
53
58
  exports.default = withBitmovinIosConfig;
@@ -5,6 +5,8 @@ import {
5
5
  } from 'expo/config-plugins';
6
6
  import FeatureFlags from './FeatureFlags';
7
7
 
8
+ const isTV = !!process.env.EXPO_TV;
9
+
8
10
  const withBitmovinIosConfig: ConfigPlugin<{
9
11
  playerLicenseKey: string;
10
12
  features: FeatureFlags;
@@ -38,32 +40,36 @@ const withBitmovinIosConfig: ConfigPlugin<{
38
40
  backgroundModes.add('audio');
39
41
  config.modResults['UIBackgroundModes'] = Array.from(backgroundModes);
40
42
  }
41
- if (offlineFeatureConfig?.ios?.isEnabled) {
42
- config.modResults['BitmovinPlayerOfflineSupportEnabled'] = true;
43
- }
44
- if (googleCastIosConfig) {
45
- const appId = googleCastIosConfig.appId || 'FFE417E5';
46
- const localNetworkUsageDescription =
47
- googleCastIosConfig.localNetworkUsageDescription ||
48
- '${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network.';
43
+ if (!isTV) {
44
+ if (offlineFeatureConfig?.ios?.isEnabled) {
45
+ config.modResults['BitmovinPlayerOfflineSupportEnabled'] = true;
46
+ }
47
+ if (googleCastIosConfig) {
48
+ const appId = googleCastIosConfig.appId || 'FFE417E5';
49
+ const localNetworkUsageDescription =
50
+ googleCastIosConfig.localNetworkUsageDescription ||
51
+ '${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network.';
49
52
 
50
- config.modResults['NSBonjourServices'] = [
51
- '_googlecast._tcp',
52
- `_${appId}._googlecast._tcp`,
53
- ];
54
- config.modResults['NSLocalNetworkUsageDescription'] =
55
- localNetworkUsageDescription;
53
+ config.modResults['NSBonjourServices'] = [
54
+ '_googlecast._tcp',
55
+ `_${appId}._googlecast._tcp`,
56
+ ];
57
+ config.modResults['NSLocalNetworkUsageDescription'] =
58
+ localNetworkUsageDescription;
59
+ }
56
60
  }
57
61
  return config;
58
62
  });
59
63
 
60
- config = withPodfileProperties(config, (config) => {
61
- if (googleCastIosConfig) {
62
- config.modResults['BITMOVIN_GOOGLE_CAST_SDK_VERSION'] =
63
- googleCastIosConfig.version;
64
- }
65
- return config;
66
- });
64
+ if (!isTV) {
65
+ config = withPodfileProperties(config, (config) => {
66
+ if (googleCastIosConfig) {
67
+ config.modResults['BITMOVIN_GOOGLE_CAST_SDK_VERSION'] =
68
+ googleCastIosConfig.version;
69
+ }
70
+ return config;
71
+ });
72
+ }
67
73
 
68
74
  return config;
69
75
  };
@@ -98,88 +98,90 @@ export function PlayerView({
98
98
  }
99
99
  }, [viewRef, nativeView]);
100
100
 
101
+ if (!isPlayerInitialized) {
102
+ return null;
103
+ }
104
+
101
105
  return (
102
- isPlayerInitialized && (
103
- <NativePlayerView
104
- ref={nativeView}
105
- style={nativeViewStyle}
106
- config={nativePlayerViewConfig}
107
- isFullscreenRequested={isFullscreenRequested}
108
- isPictureInPictureRequested={isPictureInPictureRequested}
109
- scalingMode={scalingMode}
110
- fullscreenBridgeId={fullscreenBridge.current?.nativeId}
111
- onBmpAdBreakFinished={proxy(props.onAdBreakFinished)}
112
- onBmpAdBreakStarted={proxy(props.onAdBreakStarted)}
113
- onBmpAdClicked={proxy(props.onAdClicked)}
114
- onBmpAdError={proxy(props.onAdError)}
115
- onBmpAdFinished={proxy(props.onAdFinished)}
116
- onBmpAdManifestLoad={proxy(props.onAdManifestLoad)}
117
- onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)}
118
- onBmpAdQuartile={proxy(props.onAdQuartile)}
119
- onBmpAdScheduled={proxy(props.onAdScheduled)}
120
- onBmpAdSkipped={proxy(props.onAdSkipped)}
121
- onBmpAdStarted={proxy(props.onAdStarted)}
122
- onBmpCastAvailable={proxy(props.onCastAvailable)}
123
- onBmpCastPaused={proxy(props.onCastPaused)}
124
- onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)}
125
- onBmpCastPlaying={proxy(props.onCastPlaying)}
126
- onBmpCastStarted={proxy(props.onCastStarted)}
127
- onBmpCastStart={proxy(props.onCastStart)}
128
- onBmpCastStopped={proxy(props.onCastStopped)}
129
- onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)}
130
- onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)}
131
- onBmpCueEnter={proxy(props.onCueEnter)}
132
- onBmpCueExit={proxy(props.onCueExit)}
133
- onBmpDestroy={proxy(props.onDestroy)}
134
- onBmpEvent={proxy(props.onEvent)}
135
- onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)}
136
- onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)}
137
- onBmpFullscreenEnter={proxy(props.onFullscreenEnter)}
138
- onBmpFullscreenExit={proxy(props.onFullscreenExit)}
139
- onBmpMuted={proxy(props.onMuted)}
140
- onBmpPaused={proxy(props.onPaused)}
141
- onBmpPictureInPictureAvailabilityChanged={proxy(
142
- props.onPictureInPictureAvailabilityChanged
143
- )}
144
- onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)}
145
- onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)}
146
- onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)}
147
- onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)}
148
- onBmpPlay={proxy(props.onPlay)}
149
- onBmpPlaybackFinished={proxy(props.onPlaybackFinished)}
150
- onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)}
151
- onBmpPlayerActive={proxy(props.onPlayerActive)}
152
- onBmpPlayerError={proxy(props.onPlayerError)}
153
- onBmpPlayerWarning={proxy(props.onPlayerWarning)}
154
- onBmpPlaying={proxy(props.onPlaying)}
155
- onBmpReady={proxy(props.onReady)}
156
- onBmpSeek={proxy(props.onSeek)}
157
- onBmpSeeked={proxy(props.onSeeked)}
158
- onBmpTimeShift={proxy(props.onTimeShift)}
159
- onBmpTimeShifted={proxy(props.onTimeShifted)}
160
- onBmpStallStarted={proxy(props.onStallStarted)}
161
- onBmpStallEnded={proxy(props.onStallEnded)}
162
- onBmpSourceError={proxy(props.onSourceError)}
163
- onBmpSourceLoad={proxy(props.onSourceLoad)}
164
- onBmpSourceLoaded={proxy(props.onSourceLoaded)}
165
- onBmpSourceUnloaded={proxy(props.onSourceUnloaded)}
166
- onBmpSourceWarning={proxy(props.onSourceWarning)}
167
- onBmpAudioAdded={proxy(props.onAudioAdded)}
168
- onBmpAudioChanged={proxy(props.onAudioChanged)}
169
- onBmpAudioRemoved={proxy(props.onAudioRemoved)}
170
- onBmpSubtitleAdded={proxy(props.onSubtitleAdded)}
171
- onBmpSubtitleChanged={proxy(props.onSubtitleChanged)}
172
- onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)}
173
- onBmpTimeChanged={proxy(props.onTimeChanged)}
174
- onBmpUnmuted={proxy(props.onUnmuted)}
175
- onBmpVideoDownloadQualityChanged={proxy(
176
- props.onVideoDownloadQualityChanged
177
- )}
178
- onBmpVideoPlaybackQualityChanged={proxy(
179
- props.onVideoPlaybackQualityChanged
180
- )}
181
- onBmpDownloadFinished={proxy(props.onDownloadFinished)}
182
- />
183
- )
106
+ <NativePlayerView
107
+ ref={nativeView}
108
+ style={nativeViewStyle}
109
+ config={nativePlayerViewConfig}
110
+ isFullscreenRequested={isFullscreenRequested}
111
+ isPictureInPictureRequested={isPictureInPictureRequested}
112
+ scalingMode={scalingMode}
113
+ fullscreenBridgeId={fullscreenBridge.current?.nativeId}
114
+ onBmpAdBreakFinished={proxy(props.onAdBreakFinished)}
115
+ onBmpAdBreakStarted={proxy(props.onAdBreakStarted)}
116
+ onBmpAdClicked={proxy(props.onAdClicked)}
117
+ onBmpAdError={proxy(props.onAdError)}
118
+ onBmpAdFinished={proxy(props.onAdFinished)}
119
+ onBmpAdManifestLoad={proxy(props.onAdManifestLoad)}
120
+ onBmpAdManifestLoaded={proxy(props.onAdManifestLoaded)}
121
+ onBmpAdQuartile={proxy(props.onAdQuartile)}
122
+ onBmpAdScheduled={proxy(props.onAdScheduled)}
123
+ onBmpAdSkipped={proxy(props.onAdSkipped)}
124
+ onBmpAdStarted={proxy(props.onAdStarted)}
125
+ onBmpCastAvailable={proxy(props.onCastAvailable)}
126
+ onBmpCastPaused={proxy(props.onCastPaused)}
127
+ onBmpCastPlaybackFinished={proxy(props.onCastPlaybackFinished)}
128
+ onBmpCastPlaying={proxy(props.onCastPlaying)}
129
+ onBmpCastStarted={proxy(props.onCastStarted)}
130
+ onBmpCastStart={proxy(props.onCastStart)}
131
+ onBmpCastStopped={proxy(props.onCastStopped)}
132
+ onBmpCastTimeUpdated={proxy(props.onCastTimeUpdated)}
133
+ onBmpCastWaitingForDevice={proxy(props.onCastWaitingForDevice)}
134
+ onBmpCueEnter={proxy(props.onCueEnter)}
135
+ onBmpCueExit={proxy(props.onCueExit)}
136
+ onBmpDestroy={proxy(props.onDestroy)}
137
+ onBmpEvent={proxy(props.onEvent)}
138
+ onBmpFullscreenEnabled={proxy(props.onFullscreenEnabled)}
139
+ onBmpFullscreenDisabled={proxy(props.onFullscreenDisabled)}
140
+ onBmpFullscreenEnter={proxy(props.onFullscreenEnter)}
141
+ onBmpFullscreenExit={proxy(props.onFullscreenExit)}
142
+ onBmpMuted={proxy(props.onMuted)}
143
+ onBmpPaused={proxy(props.onPaused)}
144
+ onBmpPictureInPictureAvailabilityChanged={proxy(
145
+ props.onPictureInPictureAvailabilityChanged
146
+ )}
147
+ onBmpPictureInPictureEnter={proxy(props.onPictureInPictureEnter)}
148
+ onBmpPictureInPictureEntered={proxy(props.onPictureInPictureEntered)}
149
+ onBmpPictureInPictureExit={proxy(props.onPictureInPictureExit)}
150
+ onBmpPictureInPictureExited={proxy(props.onPictureInPictureExited)}
151
+ onBmpPlay={proxy(props.onPlay)}
152
+ onBmpPlaybackFinished={proxy(props.onPlaybackFinished)}
153
+ onBmpPlaybackSpeedChanged={proxy(props.onPlaybackSpeedChanged)}
154
+ onBmpPlayerActive={proxy(props.onPlayerActive)}
155
+ onBmpPlayerError={proxy(props.onPlayerError)}
156
+ onBmpPlayerWarning={proxy(props.onPlayerWarning)}
157
+ onBmpPlaying={proxy(props.onPlaying)}
158
+ onBmpReady={proxy(props.onReady)}
159
+ onBmpSeek={proxy(props.onSeek)}
160
+ onBmpSeeked={proxy(props.onSeeked)}
161
+ onBmpTimeShift={proxy(props.onTimeShift)}
162
+ onBmpTimeShifted={proxy(props.onTimeShifted)}
163
+ onBmpStallStarted={proxy(props.onStallStarted)}
164
+ onBmpStallEnded={proxy(props.onStallEnded)}
165
+ onBmpSourceError={proxy(props.onSourceError)}
166
+ onBmpSourceLoad={proxy(props.onSourceLoad)}
167
+ onBmpSourceLoaded={proxy(props.onSourceLoaded)}
168
+ onBmpSourceUnloaded={proxy(props.onSourceUnloaded)}
169
+ onBmpSourceWarning={proxy(props.onSourceWarning)}
170
+ onBmpAudioAdded={proxy(props.onAudioAdded)}
171
+ onBmpAudioChanged={proxy(props.onAudioChanged)}
172
+ onBmpAudioRemoved={proxy(props.onAudioRemoved)}
173
+ onBmpSubtitleAdded={proxy(props.onSubtitleAdded)}
174
+ onBmpSubtitleChanged={proxy(props.onSubtitleChanged)}
175
+ onBmpSubtitleRemoved={proxy(props.onSubtitleRemoved)}
176
+ onBmpTimeChanged={proxy(props.onTimeChanged)}
177
+ onBmpUnmuted={proxy(props.onUnmuted)}
178
+ onBmpVideoDownloadQualityChanged={proxy(
179
+ props.onVideoDownloadQualityChanged
180
+ )}
181
+ onBmpVideoPlaybackQualityChanged={proxy(
182
+ props.onVideoPlaybackQualityChanged
183
+ )}
184
+ onBmpDownloadFinished={proxy(props.onDownloadFinished)}
185
+ />
184
186
  );
185
187
  }