react-native-theoplayer
Version:
A THEOplayer video component for react-native.
418 lines (411 loc) • 13.4 kB
JavaScript
"use strict";
import { DefaultEventDispatcher } from './event/DefaultEventDispatcher';
import { addTrack, findMediaTrackByUid, MediaTrackEventType, MediaTrackType, PlayerEventType, PresentationMode, removeTrack, TrackListEventType } from 'react-native-theoplayer';
import { THEOplayerNativeAdsAdapter } from './ads/THEOplayerNativeAdsAdapter';
import { THEOplayerNativeCastAdapter } from './cast/THEOplayerNativeCastAdapter';
import { AbrAdapter } from './abr/AbrAdapter';
import { NativeModules, Platform, StatusBar } from 'react-native';
import { TextTrackStyleAdapter } from './track/TextTrackStyleAdapter';
import { EventBroadcastAdapter } from './broadcast/EventBroadcastAdapter';
import { DefaultNativePlayerState } from './DefaultNativePlayerState';
import { THEOAdsNativeAdapter } from './theoads/THEOAdsNativeAdapter';
import { TheoLiveNativeAdapter } from './theolive/TheoLiveNativeAdapter';
const NativePlayerModule = NativeModules.THEORCTPlayerModule;
export class THEOplayerAdapter extends DefaultEventDispatcher {
_externalEventRouter = undefined;
constructor(view) {
super();
this._view = view;
this._state = new DefaultNativePlayerState(this);
this._adsAdapter = new THEOplayerNativeAdsAdapter(this._view);
this._theoAdsAdapter = new THEOAdsNativeAdapter(this._view);
this._castAdapter = new THEOplayerNativeCastAdapter(this, this._view);
this._abrAdapter = new AbrAdapter(this._view);
this._textTrackStyleAdapter = new TextTrackStyleAdapter(this._view);
this._theoliveAdapter = new TheoLiveNativeAdapter(this._view);
this.addEventListener(PlayerEventType.LOADED_METADATA, this.onLoadedMetadata);
this.addEventListener(PlayerEventType.PAUSE, this.onPause);
this.addEventListener(PlayerEventType.PLAYING, this.onPlaying);
this.addEventListener(PlayerEventType.TIME_UPDATE, this.onTimeupdate);
this.addEventListener(PlayerEventType.DURATION_CHANGE, this.onDurationChange);
this.addEventListener(PlayerEventType.RATE_CHANGE, this.onRateChange);
this.addEventListener(PlayerEventType.SEEKING, this.onSeeking);
this.addEventListener(PlayerEventType.SEEKED, this.onSeeked);
this.addEventListener(PlayerEventType.PROGRESS, this.onProgress);
this.addEventListener(PlayerEventType.MEDIA_TRACK, this.onMediaTrack);
this.addEventListener(PlayerEventType.MEDIA_TRACK_LIST, this.onMediaTrackList);
this.addEventListener(PlayerEventType.PRESENTATIONMODE_CHANGE, this.onPresentationModeChange);
this.addEventListener(PlayerEventType.RESIZE, this.onResize);
}
hasValidSource() {
return this._state.source !== undefined;
}
onPause = () => {
this._state.paused = true;
};
onPlaying = () => {
this._state.paused = false;
};
onPresentationModeChange = event => {
this._state.presentationMode = event.presentationMode;
if (Platform.OS === 'ios') {
StatusBar.setHidden(event.presentationMode === PresentationMode.fullscreen, 'slide');
}
};
onTimeupdate = event => {
this._state.currentTime = event.currentTime;
this._state.currentProgramDateTime = event.currentProgramDateTime;
};
onResize = event => {
this._state.width = event.width;
this._state.height = event.height;
};
onLoadedMetadata = event => {
this._state.duration = event.duration;
this._state.audioTracks = event.audioTracks;
this._state.videoTracks = event.videoTracks;
this._state.selectedAudioTrack = event.selectedAudioTrack;
this._state.selectedVideoTrack = event.selectedVideoTrack;
if (isFinite(this._state.duration)) {
this._state.seekable = [{
start: 0,
end: this._state.duration
}];
}
};
onDurationChange = event => {
this._state.duration = event.duration;
};
onRateChange = event => {
this._state.playbackRate = event.playbackRate;
};
onSeeking = () => {
this._state.seeking = true;
};
onSeeked = () => {
this._state.seeking = false;
};
onProgress = event => {
this._state.seekable = event.seekable?.sort((a, b) => a.end - b.end);
this._state.buffered = event.buffered?.sort((a, b) => a.end - b.end);
};
onMediaTrack = event => {
const {
subType,
trackType,
trackUid
} = event;
const tracks = trackType === MediaTrackType.VIDEO ? this._state.videoTracks : this._state.audioTracks;
const track = findMediaTrackByUid(tracks, trackUid);
switch (subType) {
case MediaTrackEventType.ACTIVE_QUALITY_CHANGED:
// Update local state
if (track) {
Object.assign(track, {
...track,
activeQuality: event.qualities
});
}
break;
}
};
onMediaTrackList = event => {
const {
subType,
trackType,
track
} = event;
const isAudio = trackType === MediaTrackType.AUDIO;
switch (subType) {
case TrackListEventType.ADD_TRACK:
if (isAudio) {
this._state.audioTracks = addTrack(this._state.audioTracks, track);
} else {
this._state.videoTracks = addTrack(this._state.videoTracks, track);
}
break;
case TrackListEventType.REMOVE_TRACK:
if (isAudio) {
this._state.audioTracks = removeTrack(this._state.audioTracks, track);
} else {
this._state.videoTracks = removeTrack(this._state.videoTracks, track);
}
break;
case TrackListEventType.CHANGE_TRACK:
if (isAudio) {
this._state.audioTracks = removeTrack(this._state.audioTracks, track);
this._state.audioTracks = addTrack(this._state.audioTracks, track);
if (track.enabled) {
this._state.selectedAudioTrack = track.uid;
}
} else {
this._state.videoTracks = removeTrack(this._state.videoTracks, track);
this._state.videoTracks = addTrack(this._state.videoTracks, track);
if (track.enabled) {
this._state.selectedVideoTrack = track.uid;
}
}
break;
}
};
get abr() {
return this._abrAdapter;
}
get ads() {
return this._adsAdapter;
}
get theoads() {
return this._theoAdsAdapter;
}
get theolive() {
return this._theoliveAdapter;
}
set autoplay(autoplay) {
this._state.autoplay = autoplay;
NativePlayerModule.setAutoplay(this._view.nativeHandle, autoplay);
}
get autoplay() {
return this._state.autoplay;
}
set preload(type) {
this._state.preload = type;
NativePlayerModule.setPreload(this._view.nativeHandle, type);
}
get preload() {
return this._state.preload;
}
get seekable() {
return this._state.seekable ?? [];
}
seekableEnd() {
const ranges = this.seekable;
return ranges.length === 0 ? 0 : ranges[ranges.length - 1].end;
}
get buffered() {
return this._state.buffered ?? [];
}
get cast() {
return this._castAdapter;
}
get currentTime() {
return this._state.currentTime;
}
set currentTime(currentTime) {
if (!this.hasValidSource()) {
return;
}
if (isNaN(currentTime)) {
return;
}
// Sanitise currentTime
let seekTime = currentTime;
if (currentTime === Infinity) {
seekTime = this.seekableEnd();
}
this._state.currentTime = seekTime;
NativePlayerModule.setCurrentTime(this._view.nativeHandle, seekTime);
}
get currentProgramDateTime() {
return this._state.currentProgramDateTime;
}
get duration() {
return this._state.duration;
}
get pipConfiguration() {
return this._state.pipConfig;
}
set pipConfiguration(pipConfiguration) {
this._state.pipConfig = pipConfiguration;
NativePlayerModule.setPipConfig(this._view.nativeHandle, pipConfiguration);
}
get backgroundAudioConfiguration() {
return this._state.backgroundAudioConfig;
}
set backgroundAudioConfiguration(backgroundAudioConfiguration) {
this._state.backgroundAudioConfig = backgroundAudioConfiguration;
NativePlayerModule.setBackgroundAudioConfig(this._view.nativeHandle, backgroundAudioConfiguration);
}
get presentationMode() {
return this._state.presentationMode;
}
set presentationMode(presentationMode) {
this._state.presentationMode = presentationMode;
NativePlayerModule.setPresentationMode(this._view.nativeHandle, presentationMode);
}
get muted() {
return this._state.muted;
}
set muted(muted) {
this._state.muted = muted;
NativePlayerModule.setMuted(this._view.nativeHandle, muted);
}
get seeking() {
return this._state.seeking;
}
get paused() {
return this._state.paused;
}
get playbackRate() {
return this._state.playbackRate;
}
set playbackRate(playbackRate) {
this._state.playbackRate = playbackRate;
NativePlayerModule.setPlaybackRate(this._view.nativeHandle, playbackRate);
}
get audioTracks() {
return this._state.audioTracks;
}
get selectedAudioTrack() {
return this._state.selectedAudioTrack;
}
set selectedAudioTrack(trackUid) {
if (!this.hasValidSource()) {
return;
}
this._state.selectedAudioTrack = trackUid;
NativePlayerModule.setSelectedAudioTrack(this._view.nativeHandle, trackUid !== undefined ? trackUid : -1);
}
get videoTracks() {
return this._state.videoTracks;
}
get selectedVideoTrack() {
return this._state.selectedVideoTrack;
}
set selectedVideoTrack(trackUid) {
if (!this.hasValidSource()) {
return;
}
this._state.selectedVideoTrack = trackUid;
this._state.targetVideoQuality = undefined;
NativePlayerModule.setSelectedVideoTrack(this._view.nativeHandle, trackUid !== undefined ? trackUid : -1);
}
get textTracks() {
return this._state.textTracks;
}
get selectedTextTrack() {
return this._state.selectedTextTrack;
}
set selectedTextTrack(trackUid) {
this._state.selectedTextTrack = trackUid;
// Apply native selection
NativePlayerModule.setSelectedTextTrack(this._view.nativeHandle, trackUid !== undefined ? trackUid : -1);
}
get textTrackStyle() {
return this._textTrackStyleAdapter;
}
get source() {
return this._state.source;
}
set source(source) {
// This is to correctly reset autoplay during a source change.
this.pause();
this._state.source = source;
NativePlayerModule.setSource(this._view.nativeHandle, source);
// Reset state for play-out of new source
this._state.apply({
playbackRate: 1,
seeking: false,
audioTracks: [],
videoTracks: [],
textTracks: [],
seekable: [],
buffered: [],
selectedTextTrack: undefined,
selectedVideoTrack: undefined,
selectedAudioTrack: undefined,
targetVideoQuality: undefined
});
}
get targetVideoQuality() {
return this._state.targetVideoQuality;
}
set targetVideoQuality(target) {
if (!this.hasValidSource()) {
return;
}
// Always pass an array for targetVideoQuality.
this._state.targetVideoQuality = target === undefined ? [] : Array.isArray(target) ? target : [target];
// Update local state
const track = findMediaTrackByUid(this._state.videoTracks, this.selectedVideoTrack);
if (track) {
Object.assign(track, {
...track,
targetQuality: this._state.targetVideoQuality
});
}
NativePlayerModule.setTargetVideoQuality(this._view.nativeHandle, this._state.targetVideoQuality);
}
get volume() {
return this._state.volume;
}
set volume(volume) {
this._state.volume = volume;
NativePlayerModule.setVolume(this._view.nativeHandle, volume);
}
get aspectRatio() {
return this._state.aspectRatio;
}
set aspectRatio(ratio) {
this._state.aspectRatio = ratio;
NativePlayerModule.setAspectRatio(this._view.nativeHandle, ratio);
}
get renderingTarget() {
return this._state.renderingTarget;
}
set renderingTarget(target) {
if (Platform.OS === 'android') {
this._state.renderingTarget = target;
NativePlayerModule.setRenderingTarget(this._view.nativeHandle, target);
}
}
get keepScreenOn() {
return this._state.keepScreenOn;
}
set keepScreenOn(value) {
this._state.keepScreenOn = value;
NativePlayerModule.setKeepScreenOn(this._view.nativeHandle, value);
}
pause() {
if (this.hasValidSource()) {
this._state.paused = true;
NativePlayerModule.setPaused(this._view.nativeHandle, true);
}
}
play() {
if (this.hasValidSource()) {
this._state.paused = false;
NativePlayerModule.setPaused(this._view.nativeHandle, false);
}
}
get version() {
return this._playerVersion;
}
// @internal
get nativeHandle() {
return this._view.nativeHandle;
}
// @internal
get broadcast() {
return this._externalEventRouter ?? (this._externalEventRouter = new EventBroadcastAdapter(this));
}
/**
* initializeFromNativePlayer is called when the native player is ready and has sent the `onNativePlayerReady` event.
*
* @param version The native player version.
* @param state An optional initial player state.
*/
async initializeFromNativePlayer_(version, state) {
this._playerVersion = version;
if (state) {
this._state.apply(state);
}
await this._castAdapter.init_();
}
get width() {
return this._state.width;
}
get height() {
return this._state.height;
}
}
//# sourceMappingURL=THEOplayerAdapter.js.map