react-native-theoplayer 10.5.0 → 10.5.1

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ 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
+ ## [10.5.1] - 25-11-28
9
+
10
+ ### Added
11
+
12
+ - Support for contentProtection query parameters on THEOlive sources.
13
+
8
14
  ## [10.5.0] - 25-11-24
9
15
 
10
16
  ### Fixed
@@ -20,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
20
26
  ### Changed
21
27
 
22
28
  - Updated the active quality info extraction on iOS to use the activeQualityChange event data instead of player API.
29
+ - On iOS, we now also pass all available qualities and the current active quality when bridging video- and audio track data.
23
30
 
24
31
  ## [10.4.0] - 25-11-13
25
32
 
@@ -178,6 +178,9 @@ class SourceAdapter {
178
178
  },
179
179
  latencyConfiguration=jsonTypedSource.optJSONObject(PROP_LATENCY_CONFIGURATION)?.let {
180
180
  parseLatencyConfiguration(it)
181
+ },
182
+ drm=jsonTypedSource.optJSONObject(PROP_CONTENT_PROTECTION)?.let {
183
+ ContentProtectionAdapter.drmConfigurationFromJson(it)
181
184
  }
182
185
  )
183
186
  }
@@ -235,39 +235,12 @@ class THEOplayerRCTMediaTrackEventHandler {
235
235
  let player = self.player,
236
236
  let track = self.activeTrack(tracks: player.videoTracks) {
237
237
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for videoTrack") }
238
- let activeQuality = event.quality
239
- let identifier = String(activeQuality.bandwidth)
240
- let label = self.labelFromBandWidth(activeQuality.bandwidth)
241
-
242
- var width = player.videoWidth
243
- var height = player.videoHeight
244
- if let activeVideoQuality = activeQuality as? VideoQuality {
245
- width = activeVideoQuality.width
246
- height = activeVideoQuality.height
247
- }
248
-
249
- var quality: [String:Any] = [
250
- "bandwidth": activeQuality.bandwidth,
251
- "codecs": "",
252
- "id": identifier,
253
- "uid": identifier,
254
- "name": label,
255
- "label": label,
256
- "available": true,
257
- "width": width,
258
- "height": height,
259
- //"frameRate": 0, // not available on iOS SDK
260
- //"firstFrame": 0 // not available on iOS SDK
261
- ]
262
- if let averageBandwidth = activeQuality.averageBandwidth {
263
- quality["averageBandwidth"] = averageBandwidth
264
- }
265
238
 
266
239
  forwardedMediaTrackEvent([
267
240
  "trackUid" : track.uid,
268
241
  "type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
269
242
  "trackType": MediaTrackType.VIDEO.rawValue,
270
- "qualities": [quality]
243
+ "qualities": THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: event.quality)
271
244
  ])
272
245
  }
273
246
  }
@@ -277,29 +250,12 @@ class THEOplayerRCTMediaTrackEventHandler {
277
250
  let player = self.player,
278
251
  let track = self.activeTrack(tracks: player.audioTracks) {
279
252
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for audioTrack") }
280
- let activeQuality = event.quality
281
- let identifier = String(activeQuality.bandwidth)
282
- let label = self.labelFromBandWidth(activeQuality.bandwidth)
283
-
284
- var quality: [String:Any] = [
285
- "bandwidth": activeQuality.bandwidth,
286
- "codecs": "",
287
- "id": identifier,
288
- "uid": identifier,
289
- "name": label,
290
- "label": label,
291
- "available": true,
292
- //"audioSamplingRate": 0 // not available on iOS SDK
293
- ]
294
- if let averageBandwidth = activeQuality.averageBandwidth {
295
- quality["averageBandwidth"] = averageBandwidth
296
- }
297
253
 
298
254
  forwardedMediaTrackEvent([
299
255
  "trackUid" : track.uid,
300
256
  "type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
301
257
  "trackType": MediaTrackType.AUDIO.rawValue,
302
- "qualities": [quality]
258
+ "qualities": THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: event.quality)
303
259
  ])
304
260
  }
305
261
  }
@@ -318,14 +274,4 @@ class THEOplayerRCTMediaTrackEventHandler {
318
274
  }
319
275
  return nil;
320
276
  }
321
-
322
- private func labelFromBandWidth(_ bandWidth: Int) -> String {
323
- if bandWidth > 1000000 {
324
- return "\(Double(bandWidth / 1000) / 1000) Mbps"
325
- } else if bandWidth > 1000 {
326
- return "\(bandWidth / 1000) kbps"
327
- } else {
328
- return "No Label"
329
- }
330
- }
331
277
  }
@@ -195,7 +195,7 @@ class THEOplayerRCTSourceDescriptionBuilder {
195
195
  let type = typedSourceData[SD_PROP_TYPE] as? String
196
196
 
197
197
  if integration == "theolive" || type == "theolive" {
198
- return THEOplayerRCTSourceDescriptionBuilder.buildTHEOliveDescription(typedSourceData)
198
+ return THEOplayerRCTSourceDescriptionBuilder.buildTHEOliveDescription(typedSourceData, contentPotection: contentProtection)
199
199
  }
200
200
 
201
201
  if type == "millicast" {
@@ -344,7 +344,7 @@ class THEOplayerRCTSourceDescriptionBuilder {
344
344
  - returns: a THEOplayer DRMConfiguration
345
345
  */
346
346
  static func buildContentProtection(_ contentProtectionData: [String:Any]) -> MultiplatformDRMConfiguration? {
347
- guard let customIntegrationId = contentProtectionData[SD_PROP_INTEGRATION] as? String else { return nil }
347
+ let customIntegrationId = contentProtectionData[SD_PROP_INTEGRATION] as? String ?? "internal"
348
348
 
349
349
  // fairplay
350
350
  var fairplayKeySystem: THEOplayerSDK.KeySystemConfiguration? = nil
@@ -179,9 +179,16 @@ class THEOplayerRCTTrackMetadataAggregator {
179
179
  entry[PROP_LABEL] = audioTrack.label
180
180
  entry[PROP_UNLOCALIZED_LABEL] = audioTrack.unlocalizedLabel
181
181
  entry[PROP_ENABLED] = audioTrack.enabled
182
- entry[PROP_QUALITIES] = [] // empty: qualities are not being exposed on iOS
183
- //entry[PROP_ACTIVE_QUALITY] = // undefined: qualities are not being exposed on iOS
184
- //entry[PROP_TARGET_QUALITY] = // undefined: qualities are not being exposed on iOS
182
+
183
+ // add known qualities
184
+ entry[PROP_QUALITIES] = (0..<audioTrack.qualities.count).map { index in
185
+ return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: audioTrack.qualities.get(index))
186
+ }
187
+
188
+ // add active quality
189
+ if let activeQuality = audioTrack.activeQuality {
190
+ entry[PROP_ACTIVE_QUALITY] = THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: activeQuality)
191
+ }
185
192
  return entry
186
193
  }
187
194
 
@@ -221,9 +228,17 @@ class THEOplayerRCTTrackMetadataAggregator {
221
228
  entry[PROP_LABEL] = videoTrack.label
222
229
  entry[PROP_UNLOCALIZED_LABEL] = videoTrack.unlocalizedLabel
223
230
  entry[PROP_ENABLED] = videoTrack.enabled
224
- entry[PROP_QUALITIES] = [] // empty: qualities are not being exposed on iOS
225
- //entry[PROP_ACTIVE_QUALITY] = // undefined: qualities are not being exposed on iOS
226
- //entry[PROP_TARGET_QUALITY] = // undefined: qualities are not being exposed on iOS
231
+
232
+ // add known qualities
233
+ entry[PROP_QUALITIES] = (0..<videoTrack.qualities.count).map { index in
234
+ return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: videoTrack.qualities.get(index))
235
+ }
236
+
237
+ // add active quality
238
+ if let activeQuality = videoTrack.activeQuality {
239
+ entry[PROP_ACTIVE_QUALITY] = THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: activeQuality)
240
+ }
241
+
227
242
  return entry
228
243
  }
229
244
 
@@ -240,6 +255,43 @@ class THEOplayerRCTTrackMetadataAggregator {
240
255
  return 0
241
256
  }
242
257
 
258
+ class func labelFromBandWidth(_ bandWidth: Int) -> String {
259
+ if bandWidth > 1000000 {
260
+ return "\(Double(bandWidth / 1000) / 1000) Mbps"
261
+ } else if bandWidth > 1000 {
262
+ return "\(bandWidth / 1000) kbps"
263
+ } else {
264
+ return "No Label"
265
+ }
266
+ }
267
+
268
+ class func aggregatedQualityInfo(quality: Quality) -> [String:Any] {
269
+ let identifier = String(quality.bandwidth)
270
+ let label = THEOplayerRCTTrackMetadataAggregator.labelFromBandWidth(quality.bandwidth)
271
+
272
+ // common properties
273
+ var entry: [String:Any] = [
274
+ "bandwidth": quality.bandwidth,
275
+ "codecs": "",
276
+ "id": identifier,
277
+ "uid": identifier,
278
+ "name": label,
279
+ "label": label,
280
+ "available": true,
281
+ ]
282
+ if let averageBandwidth = quality.averageBandwidth {
283
+ entry["averageBandwidth"] = averageBandwidth
284
+ }
285
+
286
+ // videoQuality specific properties
287
+ if let videoQuality = quality as? VideoQuality {
288
+ entry["width"] = videoQuality.width
289
+ entry["height"] = videoQuality.height
290
+ }
291
+
292
+ return entry
293
+ }
294
+
243
295
  class func aggregatedMetadataAndChapterTrackInfo(trackDescriptions: [TextTrackDescription], completed: (([[String:Any]]) -> Void)? ) {
244
296
  var trackIndex = 0
245
297
  var tracksInfo: [[String:Any]] = []
@@ -14,10 +14,10 @@ extension THEOplayerRCTSourceDescriptionBuilder {
14
14
  Builds a THEOplayer SourceDescription that can be passed as a source for the THEOplayer.
15
15
  - returns: a THEOlive TypedSource.
16
16
  */
17
- static func buildTHEOliveDescription(_ theoliveData: [String:Any]) -> TypedSource? {
17
+ static func buildTHEOliveDescription(_ theoliveData: [String:Any], contentPotection: MultiplatformDRMConfiguration?) -> TypedSource? {
18
18
  #if canImport(THEOplayerTHEOliveIntegration)
19
19
  if let src = theoliveData[SD_PROP_SRC] as? String {
20
- return TheoLiveSource(channelId: src)
20
+ return TheoLiveSource(channelId: src, drm: contentPotection)
21
21
  }
22
22
  #endif
23
23
  return nil
@@ -1 +1 @@
1
- {"version":"10.5.0","buildDate":"2025-11-24T14:42:03.212Z"}
1
+ {"version":"10.5.1","buildDate":"2025-11-28T15:34:11.051Z"}
@@ -1 +1 @@
1
- {"version":"10.5.0","buildDate":"2025-11-24T14:42:03.212Z"}
1
+ {"version":"10.5.1","buildDate":"2025-11-28T15:34:11.051Z"}
@@ -53,7 +53,7 @@ export interface MediaControlConfiguration {
53
53
  readonly allowLivePlayPause?: boolean;
54
54
  /**
55
55
  * A flag that controls whether to seek to the live edge when resuming a paused live stream.
56
- * Note that {@allowLivePlayPause} needs to be enabled for this property to have effect.
56
+ * Note that {@link allowLivePlayPause} needs to be enabled for this property to have effect.
57
57
  *
58
58
  * @defaultValue `false`
59
59
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-theoplayer",
3
- "version": "10.5.0",
3
+ "version": "10.5.1",
4
4
  "description": "A THEOplayer video component for react-native.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -58,7 +58,7 @@ export interface MediaControlConfiguration {
58
58
 
59
59
  /**
60
60
  * A flag that controls whether to seek to the live edge when resuming a paused live stream.
61
- * Note that {@allowLivePlayPause} needs to be enabled for this property to have effect.
61
+ * Note that {@link allowLivePlayPause} needs to be enabled for this property to have effect.
62
62
  *
63
63
  * @defaultValue `false`
64
64
  *
package/src/manifest.json CHANGED
@@ -1 +1 @@
1
- {"version":"10.5.0","buildDate":"2025-11-24T14:42:03.212Z"}
1
+ {"version":"10.5.1","buildDate":"2025-11-28T15:34:11.051Z"}