Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"

Expand All @@ -24,6 +26,8 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte

private val onDistributionLoadStart =
EventListener<DistributionLoadStartEvent> { onDistributionLoadStart(it) }
private val onDistributionLoaded =
EventListener<DistributionLoadedEvent> { onDistributionLoaded(it) }
private val onDistributionOffline =
EventListener<DistributionOfflineEvent> { onDistributionOffline(it) }
private val onEndPointLoaded =
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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")
Expand Down
35 changes: 35 additions & 0 deletions ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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

}
31 changes: 28 additions & 3 deletions ios/theolive/THEOplayerRCTTHEOliveEventHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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?
Expand Down Expand Up @@ -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: THEOplayerRCTTHEOliveEventAdapter.fromDistribution(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") }
Expand Down Expand Up @@ -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(
Expand Down
14 changes: 7 additions & 7 deletions react-native-theoplayer.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 20 additions & 0 deletions src/api/event/TheoLiveEvent.ts
Original file line number Diff line number Diff line change
@@ -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}.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
16 changes: 16 additions & 0 deletions src/api/theolive/TheoLiveDistribution.ts
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 5 additions & 0 deletions src/internal/adapter/WebEventForwarder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import {
DefaultTheoAdsErrorEvent,
DefaultTheoAdsEvent,
DefaultTheoLiveDistributionEvent,
DefaultTheoLiveDistributionLoadedEvent,
DefaultTheoLiveEndpointLoadedEvent,
DefaultTheoLiveEvent,
DefaultTheoLiveIntentToFallbackEvent,
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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,
Expand Down
25 changes: 18 additions & 7 deletions src/internal/adapter/event/PlayerEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ChromecastChangeEvent,
ChromecastError,
ChromecastErrorEvent,
DimensionChangeEvent,
DurationChangeEvent,
ErrorEvent,
Interstitial,
Expand Down Expand Up @@ -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<PlayerEventType.LOADED_METADATA> implements LoadedMetadataEvent {
constructor(
Expand Down Expand Up @@ -264,6 +266,15 @@ export class DefaultTheoLiveDistributionEvent extends BaseEvent<PlayerEventType.
}
}

export class DefaultTheoLiveDistributionLoadedEvent extends BaseEvent<PlayerEventType.THEOLIVE_EVENT> implements TheoLiveDistributionLoadedEvent {
constructor(
public subType: TheoLiveEventType,
public distribution?: TheoLiveDistribution,
) {
super(PlayerEventType.THEOLIVE_EVENT);
}
}

export class DefaultTheoLiveEndpointLoadedEvent extends BaseEvent<PlayerEventType.THEOLIVE_EVENT> implements TheoLiveEndpointLoadedEvent {
constructor(
public subType: TheoLiveEventType,
Expand Down
11 changes: 10 additions & 1 deletion src/internal/adapter/event/native/NativeTheoLiveEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand All @@ -18,6 +20,11 @@ export interface NativeTheoLiveEvent {
*/
distributionId: string | undefined;

/**
* Description of the THEOlive distribution for DISTRIBUTION_LOADED events.
*/
distribution: TheoLiveDistribution | undefined;

/**
* Description of the THEOlive endpoint.
*/
Expand All @@ -34,6 +41,8 @@ export function fromNativeTheoLiveEvent(event: NativeSyntheticEvent<NativeTheoLi
switch (event.type) {
case TheoLiveEventType.DISTRIBUTION_LOAD_START:
return new DefaultTheoLiveDistributionEvent(TheoLiveEventType.DISTRIBUTION_LOAD_START, nativeEvent.distributionId ?? '');
case TheoLiveEventType.DISTRIBUTION_LOADED:
return new DefaultTheoLiveDistributionLoadedEvent(TheoLiveEventType.DISTRIBUTION_LOADED, nativeEvent.distribution ?? undefined);
case TheoLiveEventType.DISTRIBUTION_OFFLINE:
return new DefaultTheoLiveDistributionEvent(TheoLiveEventType.DISTRIBUTION_OFFLINE, nativeEvent.distributionId ?? '');
case TheoLiveEventType.ENDPOINT_LOADED:
Expand Down
Loading