From e7ad851afd661b549c9e1670abbfd9f8042472d4 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Tue, 27 Jan 2026 23:05:57 +0100 Subject: [PATCH 01/17] Add TheoLiveDistribution --- src/api/theolive/TheoLiveDistribution.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/api/theolive/TheoLiveDistribution.ts diff --git a/src/api/theolive/TheoLiveDistribution.ts b/src/api/theolive/TheoLiveDistribution.ts new file mode 100644 index 000000000..07893e533 --- /dev/null +++ b/src/api/theolive/TheoLiveDistribution.ts @@ -0,0 +1,16 @@ +import { TheoLiveEndpoint } from 'react-native-theoplayer'; + +/** + * A THEOlive distribution. + * + * @category THEOlive + * @public + */ +export interface TheoLiveDistribution { + id: string; + name: string; + targetLatency?: number; + maxBitrate?: number; + endpoints: TheoLiveEndpoint[]; + dvrWindowSeconds?: number; +} From 643ff0cc4a8b930ac870f4592c70d3936f019396 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Tue, 27 Jan 2026 23:43:33 +0100 Subject: [PATCH 02/17] Forward DistributionLoadedEvent --- src/api/event/TheoLiveEvent.ts | 20 +++++++++++++++ src/internal/adapter/WebEventForwarder.ts | 5 ++++ src/internal/adapter/event/PlayerEvents.ts | 25 +++++++++++++------ .../event/native/NativeTheoLiveEvent.ts | 11 +++++++- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/api/event/TheoLiveEvent.ts b/src/api/event/TheoLiveEvent.ts index 719adfc7f..5d4ea37f8 100644 --- a/src/api/event/TheoLiveEvent.ts +++ b/src/api/event/TheoLiveEvent.ts @@ -1,4 +1,5 @@ import { Event, PlayerError, PlayerEventType, TheoLiveEndpoint } from 'react-native-theoplayer'; +import { TheoLiveDistribution } from '../theolive/TheoLiveDistribution'; /** * The THEOlive event dispatched by the {@link TheoLiveAPI THEOlive API}. @@ -26,6 +27,18 @@ export interface TheoLiveDistributionEvent extends TheoLiveEvent { distributionId: string; } +/** + * Dispatched when a THEOlive distribution has been successfully loaded. + * + * @public + */ +export interface TheoLiveDistributionLoadedEvent extends TheoLiveEvent { + /** + * The distribution info. + */ + distribution?: TheoLiveDistribution; +} + /** * Dispatched when the loading of a THEOlive endpoint is complete and playback can start. * This event is dispatched on every endpoint load, when an error is encountered and the player recovers by choosing @@ -67,6 +80,13 @@ export enum TheoLiveEventType { */ DISTRIBUTION_LOAD_START = 'distributionloadstart', + /** + * Dispatched when a THEOlive distribution has been successfully loaded. + * + * @public + */ + DISTRIBUTION_LOADED = 'distributionloaded', + /** * Dispatched when loading a THEOlive distribution that cannot be played, for example because the publication is * stopped or is still starting up. diff --git a/src/internal/adapter/WebEventForwarder.ts b/src/internal/adapter/WebEventForwarder.ts index fac067e13..0058e05d9 100644 --- a/src/internal/adapter/WebEventForwarder.ts +++ b/src/internal/adapter/WebEventForwarder.ts @@ -67,6 +67,7 @@ import { DefaultTheoAdsErrorEvent, DefaultTheoAdsEvent, DefaultTheoLiveDistributionEvent, + DefaultTheoLiveDistributionLoadedEvent, DefaultTheoLiveEndpointLoadedEvent, DefaultTheoLiveEvent, DefaultTheoLiveIntentToFallbackEvent, @@ -387,6 +388,9 @@ export class WebEventForwarder { if (event.type === TheoLiveEventType.DISTRIBUTION_LOAD_START || event.type === TheoLiveEventType.DISTRIBUTION_OFFLINE) { const { distributionId } = event; this._facade.dispatchEvent(new DefaultTheoLiveDistributionEvent(event.type as TheoLiveEventType, distributionId)); + } else if (event.type === TheoLiveEventType.DISTRIBUTION_LOADED) { + const { distribution } = event; + this._facade.dispatchEvent(new DefaultTheoLiveDistributionLoadedEvent(event.type as TheoLiveEventType, distribution)); } else if (event.type === TheoLiveEventType.ENDPOINT_LOADED) { const { endpoint } = event; this._facade.dispatchEvent(new DefaultTheoLiveEndpointLoadedEvent(event.type as TheoLiveEventType, endpoint)); @@ -477,6 +481,7 @@ type ForwardedTheoAdsEvent = NativeTheoAdsEventsMap[(typeof FORWARDED_THEOADS_EV const FORWARDED_THEOLIVE_EVENTS = [ TheoLiveEventType.DISTRIBUTION_LOAD_START, + TheoLiveEventType.DISTRIBUTION_LOADED, TheoLiveEventType.DISTRIBUTION_OFFLINE, TheoLiveEventType.ENDPOINT_LOADED, TheoLiveEventType.INTENT_TO_FALLBACK, diff --git a/src/internal/adapter/event/PlayerEvents.ts b/src/internal/adapter/event/PlayerEvents.ts index cbbf36413..510613fe6 100644 --- a/src/internal/adapter/event/PlayerEvents.ts +++ b/src/internal/adapter/event/PlayerEvents.ts @@ -10,6 +10,7 @@ import { ChromecastChangeEvent, ChromecastError, ChromecastErrorEvent, + DimensionChangeEvent, DurationChangeEvent, ErrorEvent, Interstitial, @@ -37,22 +38,23 @@ import { TextTrackEvent, TextTrackEventType, TextTrackListEvent, - TheoAdsEvent, TheoAdsErrorEvent, + TheoAdsEvent, TheoAdsEventType, - TheoLiveEvent, TheoLiveDistributionEvent, + TheoLiveDistributionLoadedEvent, + TheoLiveEndpoint, + TheoLiveEndpointLoadedEvent, + TheoLiveEvent, TheoLiveEventType, + TheoLiveIntentToFallbackEvent, TimeRange, TimeUpdateEvent, TrackListEventType, - VolumeChangeEvent, - TheoLiveEndpoint, - TheoLiveEndpointLoadedEvent, - TheoLiveIntentToFallbackEvent, - DimensionChangeEvent, VideoResizeEvent, + VolumeChangeEvent, } from 'react-native-theoplayer'; +import { TheoLiveDistribution } from '../../../api/theolive/TheoLiveDistribution'; export class DefaultLoadedMetadataEvent extends BaseEvent implements LoadedMetadataEvent { constructor( @@ -264,6 +266,15 @@ export class DefaultTheoLiveDistributionEvent extends BaseEvent implements TheoLiveDistributionLoadedEvent { + constructor( + public subType: TheoLiveEventType, + public distribution?: TheoLiveDistribution, + ) { + super(PlayerEventType.THEOLIVE_EVENT); + } +} + export class DefaultTheoLiveEndpointLoadedEvent extends BaseEvent implements TheoLiveEndpointLoadedEvent { constructor( public subType: TheoLiveEventType, diff --git a/src/internal/adapter/event/native/NativeTheoLiveEvent.ts b/src/internal/adapter/event/native/NativeTheoLiveEvent.ts index 68e90a408..2408f6369 100644 --- a/src/internal/adapter/event/native/NativeTheoLiveEvent.ts +++ b/src/internal/adapter/event/native/NativeTheoLiveEvent.ts @@ -2,10 +2,12 @@ import { PlayerError, TheoLiveEndpoint, TheoLiveEvent, TheoLiveEventType } from import { NativeSyntheticEvent } from 'react-native'; import { DefaultTheoLiveDistributionEvent, + DefaultTheoLiveDistributionLoadedEvent, DefaultTheoLiveEndpointLoadedEvent, - DefaultTheoLiveIntentToFallbackEvent, DefaultTheoLiveEvent, + DefaultTheoLiveIntentToFallbackEvent, } from '../PlayerEvents'; +import { TheoLiveDistribution } from '../../../../api/theolive/TheoLiveDistribution'; export interface NativeTheoLiveEvent { /** @@ -18,6 +20,11 @@ export interface NativeTheoLiveEvent { */ distributionId: string | undefined; + /** + * Description of the THEOlive distribution. + */ + distribution: TheoLiveDistribution | undefined; + /** * Description of the THEOlive endpoint. */ @@ -34,6 +41,8 @@ export function fromNativeTheoLiveEvent(event: NativeSyntheticEvent Date: Wed, 28 Jan 2026 00:01:36 +0100 Subject: [PATCH 03/17] Listen to distributionloaded for android --- .../com/theoplayer/theolive/THEOliveEventAdapter.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt b/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt index c4d6e6796..807ce975b 100644 --- a/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt +++ b/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt @@ -4,6 +4,7 @@ import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap import com.theoplayer.android.api.event.EventListener import com.theoplayer.android.api.event.player.theolive.DistributionLoadStartEvent +import com.theoplayer.android.api.event.player.theolive.DistributionLoadedEvent import com.theoplayer.android.api.event.player.theolive.DistributionOfflineEvent import com.theoplayer.android.api.event.player.theolive.EndpointLoadedEvent import com.theoplayer.android.api.event.player.theolive.IntentToFallbackEvent @@ -13,6 +14,7 @@ import com.theoplayer.util.PayloadBuilder private const val EVENT_PROP_TYPE = "type" private const val EVENT_PROP_DISTRIBUTION_ID = "distributionId" +private const val EVENT_PROP_DISTRIBUTION = "distribution" private const val EVENT_PROP_ENDPOINT = "endpoint" private const val EVENT_PROP_REASON = "reason" @@ -24,6 +26,8 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte private val onDistributionLoadStart = EventListener { onDistributionLoadStart(it) } + private val onDistributionLoaded = + EventListener { onDistributionLoaded(it) } private val onDistributionOffline = EventListener { onDistributionOffline(it) } private val onEndPointLoaded = @@ -33,6 +37,7 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte init { theoLiveApi.addEventListener(TheoLiveEventTypes.DISTRIBUTIONLOADSTART, onDistributionLoadStart) + theoLiveApi.addEventListener(TheoLiveEventTypes.DISTRIBUTIONLOADED, onDistributionLoaded) theoLiveApi.addEventListener(TheoLiveEventTypes.DISTRIBUTIONOFFLINE, onDistributionOffline) theoLiveApi.addEventListener(TheoLiveEventTypes.ENDPOINTLOADED, onEndPointLoaded) theoLiveApi.addEventListener(TheoLiveEventTypes.INTENTTOFALLBACK, onIntentOfFallback) @@ -43,6 +48,7 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte TheoLiveEventTypes.DISTRIBUTIONLOADSTART, onDistributionLoadStart ) + theoLiveApi.removeEventListener(TheoLiveEventTypes.DISTRIBUTIONLOADED, onDistributionLoaded) theoLiveApi.removeEventListener(TheoLiveEventTypes.DISTRIBUTIONOFFLINE, onDistributionOffline) theoLiveApi.removeEventListener(TheoLiveEventTypes.ENDPOINTLOADED, onEndPointLoaded) theoLiveApi.removeEventListener(TheoLiveEventTypes.INTENTTOFALLBACK, onIntentOfFallback) @@ -55,6 +61,13 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte }) } + private fun onDistributionLoaded(event: DistributionLoadedEvent) { + emitter.emit(Arguments.createMap().apply { + putString(EVENT_PROP_TYPE, "distributionloaded") + putString(EVENT_PROP_DISTRIBUTION, event.getDistribution()) + }) + } + private fun onDistributionOffline(event: DistributionOfflineEvent) { emitter.emit(Arguments.createMap().apply { putString(EVENT_PROP_TYPE, "distributionoffline") From 8ba57d982f95086be9cc44b63c4d113d872609c8 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Wed, 28 Jan 2026 00:02:24 +0100 Subject: [PATCH 04/17] Forward distributionLoaded for iOS --- .../THEOplayerRCTTHEOliveEventHandler.swift | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift b/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift index 733b11910..8354b76c5 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift @@ -8,12 +8,14 @@ import THEOplayerTHEOliveIntegration #endif let EVENT_TYPE_DISTRIBUTION_LOAD_START: String = "distributionloadstart" +let EVENT_TYPE_DISTRIBUTION_LOADED: String = "distributionloaded" let EVENT_TYPE_DISTRIBUTION_OFFLINE: String = "distributionoffline" let EVENT_TYPE_ENDPOINT_LOADED: String = "endpointloaded" let EVENT_TYPE_INTENT_TO_FALLBACK: String = "intenttofallback" let THEOLIVE_EVENT_PROP_TYPE: String = "type" let THEOLIVE_EVENT_PROP_DISTRIBUTION_ID: String = "distributionId" +let THEOLIVE_EVENT_PROP_DISTRIBUTION: String = "distribution" let THEOLIVE_EVENT_PROP_ENDPOINT: String = "endpoint" let THEOLIVE_EVENT_PROP_REASON: String = "reason" @@ -26,6 +28,7 @@ class THEOplayerRCTTHEOliveEventHandler { // MARK: THEOlive Listeners private var distributionLoadStartListener: EventListener? + private var distributionLoadedListener: EventListener? private var distributionOfflineListener: EventListener? private var endPointLoadedListener: EventListener? private var intentToFallbackListener: EventListener? @@ -62,8 +65,21 @@ class THEOplayerRCTTHEOliveEventHandler { } } if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionLoadStart listener attached to THEOplayer.theolive") } - - + + + // DISTRIBUTION_LOADED + self.distributionLoadedListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.DISTRIBUTION_LOADED) { [weak self] event in + if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received DistributionLoaded event from THEOlive") } + if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent { + forwardedTHEOliveEvent([ + THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_DISTRIBUTION_LOADED, + THEOLIVE_EVENT_PROP_DISTRIBUTION: event.distribution + ]) + } + } + if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionOffline listener attached to THEOplayer.theolive") } + + // DISTRIBUTION_OFFLINE self.distributionOfflineListener = player.theoLive?.addEventListener(type: THEOliveEventTypes.DISTRIBUTION_OFFLINE) { [weak self] event in if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received DistributionOffline event from THEOlive") } @@ -116,7 +132,16 @@ class THEOplayerRCTTHEOliveEventHandler { ) if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionLoadStart listener detached from THEOplayer.theolive") } } - + + // DISTRIBUTION_LOADED + if let distributionLoadedListener = self.distributionLoadedListener { + player.theoLive?.removeEventListener( + type: THEOliveEventTypes.DISTRIBUTION_LOADED, + listener: distributionLoadedListener + ) + if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DistributionLoaded listener detached from THEOplayer.theolive") } + } + // DISTRIBUTION_OFFLINE if let distributionOfflineListener = self.distributionOfflineListener { player.theoLive?.removeEventListener( From 464e53b82de2c2ac35dd41ea114648ee7977a4b7 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 12:37:05 +0100 Subject: [PATCH 05/17] Add iOS conversion method for distribution objects --- .../THEOplayerRCTTHEOliveEventAdapter.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift index 65428d3e5..46c4f76ff 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift @@ -17,6 +17,12 @@ let PROP_ENDPOINT_PRIORITY: String = "priority" let PROP_ENDPOINT_CONTENT_PROTECTION: String = "contentProtection" let PROP_REASON_ERROR_CODE: String = "errorCode" let PROP_REASON_ERROR_MESSAGE: String = "errorMessage" +let PROP_DISTRIBUTION_ID: String = "id" +let PROP_DISTRIBUTION_NAME: String = "name" +let PROP_DISTRIBUTION_TARGET_LATENCY: String = "targetLatency" +let PROP_DISTRIBUTION_MAX_BITRATE: String = "maxBitrate" +let PROP_DISTRIBUTION_ENDPOINTS: String = "endpoints" +let PROP_DISTRIBUTION_DVR_WINDOW_SECONDS: String = "dvrWindowSeconds" class THEOplayerRCTTHEOliveEventAdapter { @@ -61,6 +67,35 @@ class THEOplayerRCTTHEOliveEventAdapter { PROP_REASON_ERROR_MESSAGE: reason.message ] } + + class func fromDistribution(distribution: (any THEOplayerTHEOliveIntegration.DistributionAPI)?) -> [String:Any] { + guard let distribution = distribution else { + return [:] + } + + var distributionData: [String:Any] = [:] + distributionData[PROP_DISTRIBUTION_ID] = distribution.id + distributionData[PROP_DISTRIBUTION_NAME] = distribution.name + + if let targetLatency = distribution.targetLatency { + distributionData[PROP_DISTRIBUTION_TARGET_LATENCY] = targetLatency + } + if let maxBitrate = distribution.maxBitrate { + distributionData[PROP_DISTRIBUTION_MAX_BITRATE] = maxBitrate + } + if let dvrWindowSeconds = distribution.dvrWindowSeconds { + distributionData[PROP_DISTRIBUTION_DVR_WINDOW_SECONDS] = dvrWindowSeconds + } + var endpointsData: [[String:Any]] = [] + for endpoint in distribution.endpoints { + endpointsData.append(THEOplayerRCTTHEOliveEventAdapter.fromEndpoint(endpoint: endpoint)) + } + distributionData[PROP_DISTRIBUTION_ENDPOINTS] = endpointsData + + return distributionData + } + + #endif } From de5798373f9a444934cb18562b14c86a09869daa Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 12:37:36 +0100 Subject: [PATCH 06/17] Pass converted distribution towards JS from iOS bridge --- ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift b/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift index 8354b76c5..c4b755344 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift @@ -73,7 +73,7 @@ class THEOplayerRCTTHEOliveEventHandler { if let forwardedTHEOliveEvent = self?.onNativeTHEOliveEvent { forwardedTHEOliveEvent([ THEOLIVE_EVENT_PROP_TYPE: EVENT_TYPE_DISTRIBUTION_LOADED, - THEOLIVE_EVENT_PROP_DISTRIBUTION: event.distribution + THEOLIVE_EVENT_PROP_DISTRIBUTION: THEOplayerRCTTHEOliveEventAdapter.fromDistribution(distribution: event.distribution) ]) } } From 51da346b5474048bb0fb4f3e3d925ef230a0e7f7 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 12:40:40 +0100 Subject: [PATCH 07/17] Update annotation --- src/internal/adapter/event/native/NativeTheoLiveEvent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/adapter/event/native/NativeTheoLiveEvent.ts b/src/internal/adapter/event/native/NativeTheoLiveEvent.ts index 2408f6369..04572d7a2 100644 --- a/src/internal/adapter/event/native/NativeTheoLiveEvent.ts +++ b/src/internal/adapter/event/native/NativeTheoLiveEvent.ts @@ -21,7 +21,7 @@ export interface NativeTheoLiveEvent { distributionId: string | undefined; /** - * Description of the THEOlive distribution. + * Description of the THEOlive distribution for DISTRIBUTION_LOADED events. */ distribution: TheoLiveDistribution | undefined; From 506fbb9584546d041dd434eabdced1daab30135e Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 30 Jan 2026 12:46:25 +0100 Subject: [PATCH 08/17] Bump minimal iOS SDK for new DistributionAPI usage --- react-native-theoplayer.podspec | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/react-native-theoplayer.podspec b/react-native-theoplayer.podspec index 2177e3664..aa2d987bd 100644 --- a/react-native-theoplayer.podspec +++ b/react-native-theoplayer.podspec @@ -43,37 +43,37 @@ Pod::Spec.new do |s| # THEOplayer Dependency puts "Adding THEOplayerSDK-core" - s.dependency "THEOplayerSDK-core", "~> 10.7" + s.dependency "THEOplayerSDK-core", "~> 10.10" # THEOlive Dependency puts "Adding THEOplayer-Integration-THEOlive" - s.dependency "THEOplayer-Integration-THEOlive", "~> 10.7" + s.dependency "THEOplayer-Integration-THEOlive", "~> 10.10" # Feature based integration dependencies if theofeatures.include?("GOOGLE_IMA") puts "Adding THEOplayer-Integration-GoogleIMA" - s.dependency "THEOplayer-Integration-GoogleIMA", "~> 10.7" + s.dependency "THEOplayer-Integration-GoogleIMA", "~> 10.10" end if theofeatures.include?("CHROMECAST") puts "Adding THEOplayer-Integration-GoogleCast" - s.ios.dependency "THEOplayer-Integration-GoogleCast", "~> 10.7" + s.ios.dependency "THEOplayer-Integration-GoogleCast", "~> 10.10" end if theofeatures.include?("THEO_ADS") puts "Adding THEOplayer-Integration-THEOads" - s.dependency "THEOplayer-Integration-THEOads", "~> 10.7" + s.dependency "THEOplayer-Integration-THEOads", "~> 10.10" end if theofeatures.include?("MILLICAST") puts "Adding THEOplayer-Integration-Millicast" - s.dependency "THEOplayer-Integration-Millicast", "~> 10.7" + s.dependency "THEOplayer-Integration-Millicast", "~> 10.10" end # Feature based connector dependencies if theofeatures.include?("SIDELOADED_TEXTTRACKS") puts "Adding THEOplayer-Connector-SideloadedSubtitle" - s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 10.7" + s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 10.10" end end From 67cf30e4c27d3b7442cdcadead3f4b5baec07200 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Wed, 4 Feb 2026 14:03:06 +0100 Subject: [PATCH 09/17] Update TheoLiveDistribution --- .../THEOplayerRCTTHEOliveEventAdapter.swift | 21 +------------------ src/api/theolive/TheoLiveDistribution.ts | 6 ------ 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift index 46c4f76ff..a76a3ec82 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift @@ -19,10 +19,6 @@ let PROP_REASON_ERROR_CODE: String = "errorCode" let PROP_REASON_ERROR_MESSAGE: String = "errorMessage" let PROP_DISTRIBUTION_ID: String = "id" let PROP_DISTRIBUTION_NAME: String = "name" -let PROP_DISTRIBUTION_TARGET_LATENCY: String = "targetLatency" -let PROP_DISTRIBUTION_MAX_BITRATE: String = "maxBitrate" -let PROP_DISTRIBUTION_ENDPOINTS: String = "endpoints" -let PROP_DISTRIBUTION_DVR_WINDOW_SECONDS: String = "dvrWindowSeconds" class THEOplayerRCTTHEOliveEventAdapter { @@ -76,22 +72,7 @@ class THEOplayerRCTTHEOliveEventAdapter { var distributionData: [String:Any] = [:] distributionData[PROP_DISTRIBUTION_ID] = distribution.id distributionData[PROP_DISTRIBUTION_NAME] = distribution.name - - if let targetLatency = distribution.targetLatency { - distributionData[PROP_DISTRIBUTION_TARGET_LATENCY] = targetLatency - } - if let maxBitrate = distribution.maxBitrate { - distributionData[PROP_DISTRIBUTION_MAX_BITRATE] = maxBitrate - } - if let dvrWindowSeconds = distribution.dvrWindowSeconds { - distributionData[PROP_DISTRIBUTION_DVR_WINDOW_SECONDS] = dvrWindowSeconds - } - var endpointsData: [[String:Any]] = [] - for endpoint in distribution.endpoints { - endpointsData.append(THEOplayerRCTTHEOliveEventAdapter.fromEndpoint(endpoint: endpoint)) - } - distributionData[PROP_DISTRIBUTION_ENDPOINTS] = endpointsData - + return distributionData } diff --git a/src/api/theolive/TheoLiveDistribution.ts b/src/api/theolive/TheoLiveDistribution.ts index 07893e533..d1480ebea 100644 --- a/src/api/theolive/TheoLiveDistribution.ts +++ b/src/api/theolive/TheoLiveDistribution.ts @@ -1,5 +1,3 @@ -import { TheoLiveEndpoint } from 'react-native-theoplayer'; - /** * A THEOlive distribution. * @@ -9,8 +7,4 @@ import { TheoLiveEndpoint } from 'react-native-theoplayer'; export interface TheoLiveDistribution { id: string; name: string; - targetLatency?: number; - maxBitrate?: number; - endpoints: TheoLiveEndpoint[]; - dvrWindowSeconds?: number; } From 741b40eeabab54c1dfe2fe5f00162ce62d8fcf71 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 13 Feb 2026 12:53:08 +0100 Subject: [PATCH 10/17] Bump dev version --- e2e/package-lock.json | 6 +++--- example/package-lock.json | 8 ++++---- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 571a6ba05..bb9895aa4 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -53,8 +53,8 @@ } }, "..": { - "version": "10.7.1", - "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "version": "10.9.0", + "license": "BSD-3-Clause-Clear", "dependencies": { "@theoplayer/cmcd-connector-web": "^1.4.0", "buffer": "^6.0.3" @@ -74,7 +74,7 @@ "react": "^19.2.0", "react-native": "^0.83.1", "react-native-builder-bob": "^0.39.1", - "theoplayer": "^10", + "theoplayer": "^10.10.0", "typedoc": "^0.25.13", "typedoc-plugin-external-resolver": "^1.0.3", "typedoc-plugin-mdn-links": "^3.3.4", diff --git a/example/package-lock.json b/example/package-lock.json index 5bbf05596..077c82333 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -51,8 +51,8 @@ } }, "..": { - "version": "10.7.1", - "license": "SEE LICENSE AT https://www.theoplayer.com/terms", + "version": "10.9.0", + "license": "BSD-3-Clause-Clear", "dependencies": { "@theoplayer/cmcd-connector-web": "^1.4.0", "buffer": "^6.0.3" @@ -72,7 +72,7 @@ "react": "^19.2.0", "react-native": "^0.83.1", "react-native-builder-bob": "^0.39.1", - "theoplayer": "^10", + "theoplayer": "^10.10.0", "typedoc": "^0.25.13", "typedoc-plugin-external-resolver": "^1.0.3", "typedoc-plugin-mdn-links": "^3.3.4", @@ -13325,7 +13325,7 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package-lock.json b/package-lock.json index 0c825bf5f..ce7205de2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "react": "^19.2.0", "react-native": "^0.83.1", "react-native-builder-bob": "^0.39.1", - "theoplayer": "^10", + "theoplayer": "^10.10.0", "typedoc": "^0.25.13", "typedoc-plugin-external-resolver": "^1.0.3", "typedoc-plugin-mdn-links": "^3.3.4", @@ -10857,9 +10857,9 @@ "dev": true }, "node_modules/theoplayer": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/theoplayer/-/theoplayer-10.6.1.tgz", - "integrity": "sha512-mz3LpcChF0/pUWJwzJtMwKWyuqmv85Ao8eAFVmYFI0K+krjC+yAm28suFa7E6BITZfNTtwlDTY+ZPRDcxd6+ng==", + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/theoplayer/-/theoplayer-10.10.0.tgz", + "integrity": "sha512-24UKdnryzQHl8ch+E3YLJv4swZpydtjNZuh+mA57xBosQsirIxMKuuU0tE6ZjRu21ULgreu2KFwy3Qg9n0hMgg==", "license": "SEE LICENSE AT https://www.theoplayer.com/terms" }, "node_modules/throat": { diff --git a/package.json b/package.json index 3d753da08..946d0eb94 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "react": "^19.2.0", "react-native": "^0.83.1", "react-native-builder-bob": "^0.39.1", - "theoplayer": "^10", + "theoplayer": "^10.10.0", "typedoc": "^0.25.13", "typedoc-plugin-external-resolver": "^1.0.3", "typedoc-plugin-mdn-links": "^3.3.4", From 376c8b23119bfd4dcc56c39ea5673279a04e7ed7 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 13 Feb 2026 14:50:20 +0100 Subject: [PATCH 11/17] Add changelog entry --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 375cbd019..05fdfb7d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed -- Fixed an issue on iOS where the onPlayerStateSync callback was not called from the main thread. +- Fixed an issue on iOS where the `onPlayerStateSync` callback was not called from the main thread. + +### Added + +- Added the `DistributionLoaded` event for THEOlive. ## [10.9.0] - 26-01-29 From 6e3e48fd773238ffb2ca565e8d5cf19fb3a911da Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 13 Feb 2026 15:58:52 +0100 Subject: [PATCH 12/17] Refactor to switch --- src/internal/adapter/WebEventForwarder.ts | 41 ++++++++++++----------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/internal/adapter/WebEventForwarder.ts b/src/internal/adapter/WebEventForwarder.ts index 0058e05d9..a86fc8831 100644 --- a/src/internal/adapter/WebEventForwarder.ts +++ b/src/internal/adapter/WebEventForwarder.ts @@ -385,25 +385,28 @@ export class WebEventForwarder { }; private readonly onTheoLiveEvent = (event: ForwardedTheoLiveEvent) => { - if (event.type === TheoLiveEventType.DISTRIBUTION_LOAD_START || event.type === TheoLiveEventType.DISTRIBUTION_OFFLINE) { - const { distributionId } = event; - this._facade.dispatchEvent(new DefaultTheoLiveDistributionEvent(event.type as TheoLiveEventType, distributionId)); - } else if (event.type === TheoLiveEventType.DISTRIBUTION_LOADED) { - const { distribution } = event; - this._facade.dispatchEvent(new DefaultTheoLiveDistributionLoadedEvent(event.type as TheoLiveEventType, distribution)); - } else if (event.type === TheoLiveEventType.ENDPOINT_LOADED) { - const { endpoint } = event; - this._facade.dispatchEvent(new DefaultTheoLiveEndpointLoadedEvent(event.type as TheoLiveEventType, endpoint)); - } else if (event.type === TheoLiveEventType.INTENT_TO_FALLBACK) { - const { reason } = event; - this._facade.dispatchEvent( - new DefaultTheoLiveIntentToFallbackEvent(event.type as TheoLiveEventType, { - errorCode: reason?.code?.toString() ?? '', - errorMessage: reason?.message ?? '', - }), - ); - } else { - this._facade.dispatchEvent(new DefaultTheoLiveEvent((event as NativeEvent).type as TheoLiveEventType)); + switch (event.type) { + case TheoLiveEventType.DISTRIBUTION_LOAD_START: + case TheoLiveEventType.DISTRIBUTION_OFFLINE: + this._facade.dispatchEvent(new DefaultTheoLiveDistributionEvent(event.type as TheoLiveEventType, event.distributionId)); + break; + case TheoLiveEventType.DISTRIBUTION_LOADED: + this._facade.dispatchEvent(new DefaultTheoLiveDistributionLoadedEvent(event.type as TheoLiveEventType, event.distribution)); + break; + case TheoLiveEventType.ENDPOINT_LOADED: + this._facade.dispatchEvent(new DefaultTheoLiveEndpointLoadedEvent(event.type as TheoLiveEventType, event.endpoint)); + break; + case TheoLiveEventType.INTENT_TO_FALLBACK: + this._facade.dispatchEvent( + new DefaultTheoLiveIntentToFallbackEvent(event.type as TheoLiveEventType, { + errorCode: event.reason?.code?.toString() ?? '', + errorMessage: event.reason?.message ?? '', + }), + ); + break; + default: + this._facade.dispatchEvent(new DefaultTheoLiveEvent(event.type as TheoLiveEventType)); + return; } }; From 023d586c6a260f91439b427733d0f27ee50c0157 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 13 Feb 2026 16:04:30 +0100 Subject: [PATCH 13/17] Export type --- src/api/theolive/barrel.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/theolive/barrel.ts b/src/api/theolive/barrel.ts index 634d31001..e1b30e8fc 100644 --- a/src/api/theolive/barrel.ts +++ b/src/api/theolive/barrel.ts @@ -1,4 +1,5 @@ export * from './TheoLiveAPI'; export * from './TheoLiveConfiguration'; export * from './TheoLiveEndpoint'; +export * from './TheoLiveDistribution'; export * from './TheoLiveSource'; From a608d3418f052e44f68a9d59fbf7275b4dbdb80e Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 13 Feb 2026 16:10:32 +0100 Subject: [PATCH 14/17] Fix distribution serialisation --- .../java/com/theoplayer/theolive/THEOliveEventAdapter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt b/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt index 807ce975b..bd71888cc 100644 --- a/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt +++ b/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt @@ -17,6 +17,8 @@ private const val EVENT_PROP_DISTRIBUTION_ID = "distributionId" private const val EVENT_PROP_DISTRIBUTION = "distribution" private const val EVENT_PROP_ENDPOINT = "endpoint" private const val EVENT_PROP_REASON = "reason" +private const val EVENT_PROP_NAME = "name" +private const val EVENT_PROP_ID = "id" class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitter: Emitter) { @@ -64,7 +66,10 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte private fun onDistributionLoaded(event: DistributionLoadedEvent) { emitter.emit(Arguments.createMap().apply { putString(EVENT_PROP_TYPE, "distributionloaded") - putString(EVENT_PROP_DISTRIBUTION, event.getDistribution()) + putMap(EVENT_PROP_DISTRIBUTION, Arguments.createMap().apply { + putString(EVENT_PROP_ID, event.getDistribution().id) + putString(EVENT_PROP_NAME, event.getDistribution().name) + }) }) } From 46167f1853d333c8b92917905b4f11df68eb3a08 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Fri, 13 Feb 2026 16:27:02 +0100 Subject: [PATCH 15/17] Update minimum supported THEOplayer version --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 7e9839253..986177825 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -124,8 +124,8 @@ repositories { mavenLocal() } -// The minimum supported THEOplayer version is 10.0.1 -def theoVersion = safeExtGet('THEOplayer_sdk', '[10.0.1, 11.0.0)') +// The minimum supported THEOplayer version is 10.10.0 +def theoVersion = safeExtGet('THEOplayer_sdk', '[10.10.0, 11.0.0)') def theoMediaSessionVersion = safeExtGet('THEOplayer_mediasession', '[8.0.0, 11.0.0)') def theoAdsWrapperVersion = "10.0.0" def coroutinesVersion = safeExtGet('coroutinesVersion', '1.10.2') From 34590a1ad7d2b0f2899cd6793411d12a7dd7c551 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Fri, 13 Feb 2026 16:27:14 +0100 Subject: [PATCH 16/17] Update comment gradle.properties --- e2e/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/android/gradle.properties b/e2e/android/gradle.properties index 92e6115dd..124071bbb 100644 --- a/e2e/android/gradle.properties +++ b/e2e/android/gradle.properties @@ -41,7 +41,7 @@ newArchEnabled=true hermesEnabled=true # Version of the THEOplayer SDK, if not specified, the latest available version within bounds is set. -#THEOplayer_sdk=[8.1.0, 11.0.0) +#THEOplayer_sdk=[10.10.0, 11.0.0) # Override Android sdk versions #THEOplayer_compileSdkVersion = 34 From f7ebed5d81a19bd0569dccdcd648af55181b93d7 Mon Sep 17 00:00:00 2001 From: Jeroen Veltmans Date: Fri, 13 Feb 2026 16:28:42 +0100 Subject: [PATCH 17/17] Update example --- example/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 49978b332..acb687946 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -46,7 +46,7 @@ hermesEnabled=true edgeToEdgeEnabled=false # Version of the THEOplayer SDK, if not specified, the latest available version within bounds is set. -#THEOplayer_sdk=[10.0.1, 11.0.0) +#THEOplayer_sdk=[10.10.0, 11.0.0) # Override Android sdk versions #THEOplayer_compileSdkVersion = 36