UNPKG

bitmovin-player-react-native

Version:

Official React Native bindings for Bitmovin's mobile Player SDKs.

1,351 lines (1,328 loc) 70.5 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; // src/index.ts var src_exports = {}; __export(src_exports, { AdQuartile: () => AdQuartile, AdSourceType: () => AdSourceType, AnalyticsApi: () => AnalyticsApi, AudioSession: () => AudioSession, BitmovinCastManager: () => BitmovinCastManager, BufferApi: () => BufferApi, BufferType: () => BufferType, CustomMessageHandler: () => CustomMessageHandler, CustomUi: () => CustomUi, DebugConfig: () => DebugConfig, DecoderContextMediaType: () => DecoderContextMediaType, Drm: () => Drm, ForceReuseVideoCodecReason: () => ForceReuseVideoCodecReason, HttpRequestType: () => HttpRequestType, LoadingState: () => LoadingState, MediaType: () => MediaType, Network: () => Network, OfflineContentManager: () => OfflineContentManager, OfflineEventType: () => OfflineEventType, OfflineState: () => OfflineState, Player: () => Player, PlayerView: () => PlayerView, ScalingMode: () => ScalingMode, SmallScreenUi: () => SmallScreenUi, Source: () => Source, SourceType: () => SourceType, SubtitleFormat: () => SubtitleFormat, SurfaceType: () => SurfaceType, TimelineReferencePoint: () => TimelineReferencePoint, TvUi: () => TvUi, UserInterfaceType: () => UserInterfaceType, Variant: () => Variant, usePlayer: () => usePlayer }); module.exports = __toCommonJS(src_exports); // src/advertising.ts var AdQuartile = /* @__PURE__ */ ((AdQuartile2) => { AdQuartile2["FIRST"] = "first"; AdQuartile2["MID_POINT"] = "mid_point"; AdQuartile2["THIRD"] = "third"; return AdQuartile2; })(AdQuartile || {}); var AdSourceType = /* @__PURE__ */ ((AdSourceType2) => { AdSourceType2["IMA"] = "ima"; AdSourceType2["UNKNOWN"] = "unknown"; AdSourceType2["PROGRESSIVE"] = "progressive"; return AdSourceType2; })(AdSourceType || {}); // src/analytics/player.ts var import_react_native = require("react-native"); var PlayerAnalyticsModule = import_react_native.NativeModules.PlayerAnalyticsModule; var AnalyticsApi = class { constructor(playerId) { /** * The native player id that this analytics api is attached to. */ __publicField(this, "playerId"); /** * Sends a sample with the provided custom data. * Does not change the configured custom data of the collector or source. */ __publicField(this, "sendCustomDataEvent", (customData) => { PlayerAnalyticsModule.sendCustomDataEvent(this.playerId, customData); }); /** * Gets the current user id used by the bundled analytics instance. * * @returns The current user id. */ __publicField(this, "getUserId", async () => { return PlayerAnalyticsModule.getUserId(this.playerId); }); this.playerId = playerId; } }; // src/audioSession.ts var import_react_native2 = require("react-native"); var AudioSessionModule = import_react_native2.NativeModules.AudioSessionModule; var AudioSession = { /** * Sets the audio session's category. * * @platform iOS * @see https://developer.apple.com/documentation/avfaudio/avaudiosession/1616583-setcategory */ setCategory: async (category) => { if (AudioSessionModule) { await AudioSessionModule.setCategory(category); } } }; // src/components/PlayerView/index.tsx var import_react2 = __toESM(require("react")); var import_react_native7 = require("react-native"); // src/components/PlayerView/native.ts var import_react_native3 = require("react-native"); var NativePlayerView = (0, import_react_native3.requireNativeComponent)("NativePlayerView"); // src/hooks/useProxy.ts var import_lodash = __toESM(require("lodash.omit")); var import_react = require("react"); var import_react_native4 = require("react-native"); function unwrapNativeEvent(event) { return (0, import_lodash.default)(event.nativeEvent, ["target"]); } function useProxy(viewRef) { return (0, import_react.useCallback)( (callback) => (event) => { const node = event.target._nativeTag; if (node === (0, import_react_native4.findNodeHandle)(viewRef.current)) { callback?.(unwrapNativeEvent(event)); } }, [viewRef] ); } // src/ui/fullscreenhandlerbridge.ts var import_react_native5 = require("react-native"); var import_BatchedBridge = __toESM(require("react-native/Libraries/BatchedBridge/BatchedBridge")); var Uuid = import_react_native5.NativeModules.UuidModule; var FullscreenHandlerModule = import_react_native5.NativeModules.FullscreenHandlerModule; var FullscreenHandlerBridge = class { constructor(nativeId) { __publicField(this, "nativeId"); __publicField(this, "fullscreenHandler"); __publicField(this, "isDestroyed"); this.nativeId = nativeId ?? Uuid.generate(); this.isDestroyed = false; import_BatchedBridge.default.registerCallableModule( `FullscreenBridge-${this.nativeId}`, this ); FullscreenHandlerModule.registerHandler(this.nativeId); } setFullscreenHandler(fullscreenHandler) { if (this.fullscreenHandler === fullscreenHandler) { return; } this.fullscreenHandler = fullscreenHandler; FullscreenHandlerModule.setIsFullscreenActive( this.nativeId, fullscreenHandler?.isFullscreenActive ?? false ); } /** * Destroys the native FullscreenHandler */ destroy() { if (!this.isDestroyed) { FullscreenHandlerModule.destroy(this.nativeId); this.isDestroyed = true; } } // noinspection JSUnusedGlobalSymbols /** * Called by native code, when the UI should enter fullscreen. */ enterFullscreen() { this.fullscreenHandler?.enterFullscreen(); FullscreenHandlerModule.onFullscreenChanged( this.nativeId, this.fullscreenHandler?.isFullscreenActive ?? false ); } // noinspection JSUnusedGlobalSymbols /** * Called by native code, when the UI should exit fullscreen. */ exitFullscreen() { this.fullscreenHandler?.exitFullscreen(); FullscreenHandlerModule.onFullscreenChanged( this.nativeId, this.fullscreenHandler?.isFullscreenActive ?? false ); } }; // src/ui/custommessagehandlerbridge.ts var import_react_native6 = require("react-native"); var import_BatchedBridge2 = __toESM(require("react-native/Libraries/BatchedBridge/BatchedBridge")); var Uuid2 = import_react_native6.NativeModules.UuidModule; var CustomMessageHandlerModule = import_react_native6.NativeModules.CustomMessageHandlerModule; var CustomMessageHandlerBridge = class { constructor(nativeId) { __publicField(this, "nativeId"); __publicField(this, "customMessageHandler"); __publicField(this, "isDestroyed"); this.nativeId = nativeId ?? Uuid2.generate(); this.isDestroyed = false; import_BatchedBridge2.default.registerCallableModule( `CustomMessageBridge-${this.nativeId}`, this ); CustomMessageHandlerModule.registerHandler(this.nativeId); } setCustomMessageHandler(customMessageHandler) { this.customMessageHandler = customMessageHandler; this.customMessageHandler.customMessageSender = this; } /** * Destroys the native CustomMessageHandler */ destroy() { if (!this.isDestroyed) { CustomMessageHandlerModule.destroy(this.nativeId); this.isDestroyed = true; } } // noinspection JSUnusedGlobalSymbols /** * Called by native code, when the UI sends a synchronous message. * @internal */ receivedSynchronousMessage(message, data) { const result = this.customMessageHandler?.receivedSynchronousMessage( message, data ); CustomMessageHandlerModule.onReceivedSynchronousMessageResult( this.nativeId, result ); } // noinspection JSUnusedGlobalSymbols /** * Called by native code, when the UI sends an asynchronous message. * @internal */ receivedAsynchronousMessage(message, data) { this.customMessageHandler?.receivedAsynchronousMessage(message, data); } // noinspection JSUnusedGlobalSymbols /** * Called by CustomMessageHandler, when sending a message to the UI. */ sendMessage(message, data) { CustomMessageHandlerModule.sendMessage(this.nativeId, message, data); } }; // src/components/PlayerView/index.tsx var styles = import_react_native7.StyleSheet.create({ baseStyle: { alignSelf: "stretch" } }); function dispatch(command, node, ...args) { const commandId = import_react_native7.Platform.OS === "android" ? import_react_native7.UIManager.NativePlayerView.Commands[command].toString() : import_react_native7.UIManager.getViewManagerConfig("NativePlayerView").Commands[command]; import_react_native7.UIManager.dispatchViewManagerCommand( node, commandId, import_react_native7.Platform.select({ ios: args, android: [node, ...args] }) ); } function PlayerView({ viewRef, style, player, config, fullscreenHandler, customMessageHandler, isFullscreenRequested = false, scalingMode, isPictureInPictureRequested = false, ...props }) { const workaroundViewManagerCommandNotSent = (0, import_react2.useCallback)(() => { setTimeout(() => player.getDuration(), 100); }, [player]); const nativeView = (0, import_react2.useRef)(viewRef?.current || null); const proxy = useProxy(nativeView); const nativeViewStyle = import_react_native7.StyleSheet.flatten([styles.baseStyle, style]); const fullscreenBridge = (0, import_react2.useRef)(void 0); if (fullscreenHandler && !fullscreenBridge.current) { fullscreenBridge.current = new FullscreenHandlerBridge(); } if (fullscreenBridge.current) { fullscreenBridge.current.setFullscreenHandler(fullscreenHandler); } const customMessageHandlerBridge = (0, import_react2.useRef)(void 0); if (customMessageHandler && !customMessageHandlerBridge.current) { customMessageHandlerBridge.current = new CustomMessageHandlerBridge(); } if (customMessageHandlerBridge.current && customMessageHandler) { customMessageHandlerBridge.current.setCustomMessageHandler( customMessageHandler ); } (0, import_react2.useEffect)(() => { player.initialize(); const node = (0, import_react_native7.findNodeHandle)(nativeView.current); if (node) { if (customMessageHandlerBridge.current) { dispatch( "setCustomMessageHandlerBridgeId", node, customMessageHandlerBridge.current.nativeId ); } dispatch("attachPlayer", node, player.nativeId, player.config); if (fullscreenBridge.current) { dispatch( "attachFullscreenBridge", node, fullscreenBridge.current.nativeId ); } workaroundViewManagerCommandNotSent(); } return () => { fullscreenBridge.current?.destroy(); fullscreenBridge.current = void 0; customMessageHandlerBridge.current?.destroy(); customMessageHandlerBridge.current = void 0; }; }, [player, workaroundViewManagerCommandNotSent]); (0, import_react2.useEffect)(() => { const node = (0, import_react_native7.findNodeHandle)(nativeView.current); if (node) { dispatch("setFullscreen", node, isFullscreenRequested); } }, [isFullscreenRequested, nativeView]); (0, import_react2.useEffect)(() => { const node = (0, import_react_native7.findNodeHandle)(nativeView.current); if (node && scalingMode) { dispatch("setScalingMode", node, scalingMode); } }, [scalingMode, nativeView]); (0, import_react2.useEffect)(() => { const node = (0, import_react_native7.findNodeHandle)(nativeView.current); if (node) { dispatch("setPictureInPicture", node, isPictureInPictureRequested); } }, [isPictureInPictureRequested, nativeView]); (0, import_react2.useEffect)(() => { if (viewRef) { viewRef.current = nativeView.current; } }, [viewRef, nativeView]); return /* @__PURE__ */ import_react2.default.createElement( NativePlayerView, { ref: nativeView, style: nativeViewStyle, fullscreenBridge: fullscreenBridge.current, customMessageHandlerBridge: customMessageHandlerBridge.current, config, 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) } ); } // src/components/PlayerView/playerViewConfig.ts var Variant = class { /** * Specifies the function name that will be used to initialize the `UIManager` * for the Bitmovin Player Web UI. * * The function is called on the `window` object with the `Player` as the first argument and * the `UIConfig` as the second argument. * * Example: * When you added a new function or want to use a different function of our `UIFactory`, * you can specify the full qualifier name including namespaces. * e.g. `bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI` for the SmallScreenUi. * @see UIFactory https://github.com/bitmovin/bitmovin-player-ui/blob/develop/src/ts/uifactory.ts#L60 * * Notes: * - It's not necessary to use our `UIFactory`. Any static function can be specified. */ constructor(uiManagerFactoryFunction) { this.uiManagerFactoryFunction = uiManagerFactoryFunction; } }; var SmallScreenUi = class extends Variant { constructor() { super("bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI"); } }; var TvUi = class extends Variant { constructor() { super("bitmovin.playerui.UIFactory.buildDefaultTvUI"); } }; var CustomUi = class extends Variant { constructor(uiManagerFactoryFunction) { super(uiManagerFactoryFunction); } }; var SurfaceType = /* @__PURE__ */ ((SurfaceType2) => { SurfaceType2["SurfaceView"] = "SurfaceView"; SurfaceType2["TextureView"] = "TextureView"; return SurfaceType2; })(SurfaceType || {}); // src/drm/index.ts var import_react_native9 = require("react-native"); var import_BatchedBridge3 = __toESM(require("react-native/Libraries/BatchedBridge/BatchedBridge")); // src/nativeInstance.ts var import_react_native8 = require("react-native"); var Uuid3 = import_react_native8.NativeModules.UuidModule; var NativeInstance = class { /** * Generate UUID in case the user-defined `nativeId` is empty. */ constructor(config) { /** * Optionally user-defined string `id` for the native instance, or UUIDv4. */ __publicField(this, "nativeId"); /** * The configuration object used to initialize this instance. */ __publicField(this, "config"); this.config = config; this.nativeId = config?.nativeId ?? Uuid3.generate(); } }; // src/drm/index.ts var DrmModule = import_react_native9.NativeModules.DrmModule; var Drm = class extends NativeInstance { constructor() { super(...arguments); /** * Whether this object's native instance has been created. */ __publicField(this, "isInitialized", false); /** * Whether this object's native instance has been disposed. */ __publicField(this, "isDestroyed", false); /** * Allocates the DRM config instance and its resources natively. */ __publicField(this, "initialize", () => { if (!this.isInitialized) { import_BatchedBridge3.default.registerCallableModule(`DRM-${this.nativeId}`, this); DrmModule.initWithConfig(this.nativeId, this.config); this.isInitialized = true; } }); /** * Destroys the native DRM config and releases all of its allocated resources. */ __publicField(this, "destroy", () => { if (!this.isDestroyed) { DrmModule.destroy(this.nativeId); this.isDestroyed = true; } }); /** * iOS only. * * Applies the user-defined `prepareCertificate` function to native's `certificate` data and store * the result back in `DrmModule`. * * Called from native code when `FairplayConfig.prepareCertificate` is dispatched. * * @param certificate - Base64 encoded certificate data. */ __publicField(this, "onPrepareCertificate", (certificate) => { if (this.config?.fairplay?.prepareCertificate) { DrmModule.setPreparedCertificate( this.nativeId, this.config?.fairplay?.prepareCertificate?.(certificate) ); } }); /** * Applies the user-defined `prepareMessage` function to native's `message` data and store * the result back in `DrmModule`. * * Called from native code when `prepareMessage` is dispatched. * * @param message - Base64 encoded message data. * @param assetId - Optional asset ID. Only sent by iOS. */ __publicField(this, "onPrepareMessage", (message, assetId) => { const config = import_react_native9.Platform.OS === "ios" ? this.config?.fairplay : this.config?.widevine; if (config && config.prepareMessage) { DrmModule.setPreparedMessage( this.nativeId, import_react_native9.Platform.OS === "ios" ? config.prepareMessage?.(message, assetId) : config.prepareMessage?.(message) ); } }); /** * iOS only. * * Applies the user-defined `prepareSyncMessage` function to native's `syncMessage` data and * store the result back in `DrmModule`. * * Called from native code when `FairplayConfig.prepareSyncMessage` is dispatched. * * @param syncMessage - Base64 encoded sync SPC message data. */ __publicField(this, "onPrepareSyncMessage", (syncMessage, assetId) => { if (this.config?.fairplay?.prepareSyncMessage) { DrmModule.setPreparedSyncMessage( this.nativeId, this.config?.fairplay?.prepareSyncMessage?.(syncMessage, assetId) ); } }); /** * Applies the user-defined `prepareLicense` function to native's `license` data and store * the result back in `DrmModule`. * * Called from native code when `prepareLicense` is dispatched. * * @param license - Base64 encoded license data. */ __publicField(this, "onPrepareLicense", (license) => { const prepareLicense = import_react_native9.Platform.OS === "ios" ? this.config?.fairplay?.prepareLicense : this.config?.widevine?.prepareLicense; if (prepareLicense) { DrmModule.setPreparedLicense(this.nativeId, prepareLicense(license)); } }); /** * iOS only. * * Applies the user-defined `prepareLicenseServerUrl` function to native's `licenseServerUrl` data * and store the result back in `DrmModule`. * * Called from native code when `FairplayConfig.prepareLicenseServerUrl` is dispatched. * * @param licenseServerUrl - The license server URL string. */ __publicField(this, "onPrepareLicenseServerUrl", (licenseServerUrl) => { if (this.config?.fairplay?.prepareLicenseServerUrl) { DrmModule.setPreparedLicenseServerUrl( this.nativeId, this.config?.fairplay?.prepareLicenseServerUrl?.(licenseServerUrl) ); } }); /** * iOS only. * * Applies the user-defined `prepareContentId` function to native's `contentId` string * and store the result back in `DrmModule`. * * Called from native code when `FairplayConfig.prepareContentId` is dispatched. * * @param contentId - The extracted contentId string. */ __publicField(this, "onPrepareContentId", (contentId) => { if (this.config?.fairplay?.prepareContentId) { DrmModule.setPreparedContentId( this.nativeId, this.config?.fairplay?.prepareContentId?.(contentId) ); } }); } }; // src/hooks/usePlayer.ts var import_react3 = require("react"); // src/player.ts var import_react_native14 = require("react-native"); // src/source.ts var import_react_native10 = require("react-native"); var SourceModule = import_react_native10.NativeModules.SourceModule; var SourceType = /* @__PURE__ */ ((SourceType2) => { SourceType2["NONE"] = "none"; SourceType2["HLS"] = "hls"; SourceType2["DASH"] = "dash"; SourceType2["PROGRESSIVE"] = "progressive"; return SourceType2; })(SourceType || {}); var LoadingState = /* @__PURE__ */ ((LoadingState2) => { LoadingState2[LoadingState2["UNLOADED"] = 0] = "UNLOADED"; LoadingState2[LoadingState2["LOADING"] = 1] = "LOADING"; LoadingState2[LoadingState2["LOADED"] = 2] = "LOADED"; return LoadingState2; })(LoadingState || {}); var TimelineReferencePoint = /* @__PURE__ */ ((TimelineReferencePoint2) => { TimelineReferencePoint2["START"] = "start"; TimelineReferencePoint2["END"] = "end"; return TimelineReferencePoint2; })(TimelineReferencePoint || {}); var Source = class extends NativeInstance { constructor() { super(...arguments); /** * The native DRM config reference of this source. */ __publicField(this, "drm"); /** * The remote control config for this source. * This is only supported on iOS. * * @platform iOS */ __publicField(this, "remoteControl", null); /** * Whether the native {@link Source} object has been created. */ __publicField(this, "isInitialized", false); /** * Whether the native {@link Source} object has been disposed. */ __publicField(this, "isDestroyed", false); /** * Allocates the native {@link Source} instance and its resources natively. */ __publicField(this, "initialize", () => { if (!this.isInitialized) { const sourceMetadata = this.config?.analyticsSourceMetadata; if (this.config?.drmConfig) { this.drm = new Drm(this.config.drmConfig); this.drm.initialize(); } if (sourceMetadata) { SourceModule.initWithAnalyticsConfig( this.nativeId, this.drm?.nativeId, this.config, this.remoteControl, sourceMetadata ); } else { SourceModule.initWithConfig( this.nativeId, this.drm?.nativeId, this.config, this.remoteControl ); } this.isInitialized = true; } }); /** * Destroys the native {@link Source} and releases all of its allocated resources. */ __publicField(this, "destroy", () => { if (!this.isDestroyed) { SourceModule.destroy(this.nativeId); this.drm?.destroy(); this.isDestroyed = true; } }); /** * The duration of the source in seconds if it’s a VoD or `INFINITY` if it’s a live stream. * Default value is `0` if the duration is not available or not known. */ __publicField(this, "duration", async () => { return SourceModule.duration(this.nativeId); }); /** * Whether the source is currently active in a player (i.e. playing back or paused). * Only one source can be active in the same player instance at any time. */ __publicField(this, "isActive", async () => { return SourceModule.isActive(this.nativeId); }); /** * Whether the source is currently attached to a player instance. */ __publicField(this, "isAttachedToPlayer", async () => { return SourceModule.isAttachedToPlayer(this.nativeId); }); /** * Metadata for the currently loaded source. */ __publicField(this, "metadata", async () => { return SourceModule.getMetadata(this.nativeId); }); /** * Set metadata for the currently loaded source. * Setting the metadata to `null` clears the metadata object in native source. * * @param metadata metadata to be set. */ __publicField(this, "setMetadata", (metadata) => { SourceModule.setMetadata(this.nativeId, metadata); }); /** * The current `LoadingState` of the source. */ __publicField(this, "loadingState", async () => { return SourceModule.loadingState(this.nativeId); }); /** * @returns a `Thumbnail` for the specified playback time if available. * Supported thumbnail formats are: * - `WebVtt` configured via {@link SourceConfig.thumbnailTrack}, on all supported platforms * - HLS `Image Media Playlist` in the multivariant playlist, Android-only * - DASH `Image Adaptation Set` as specified in DASH-IF IOP, Android-only * If a `WebVtt` thumbnail track is provided, any potential in-manifest thumbnails are ignored on Android. * * @param time - The time in seconds for which to retrieve the thumbnail. */ __publicField(this, "getThumbnail", async (time) => { return SourceModule.getThumbnail(this.nativeId, time); }); } }; // src/bufferApi.ts var import_react_native11 = require("react-native"); var BufferModule = import_react_native11.NativeModules.BufferModule; var MediaType = /* @__PURE__ */ ((MediaType2) => { MediaType2["AUDIO"] = "audio"; MediaType2["VIDEO"] = "video"; return MediaType2; })(MediaType || {}); var BufferType = /* @__PURE__ */ ((BufferType2) => { BufferType2["FORWARD_DURATION"] = "forwardDuration"; BufferType2["BACKWARD_DURATION"] = "backwardDuration"; return BufferType2; })(BufferType || {}); var BufferApi = class { constructor(playerId) { /** * The native player id that this buffer api is attached to. */ __publicField(this, "nativeId"); /** * Gets the {@link BufferLevel|buffer level} from the Player * @param type The {@link BufferType} to return the level for. * @returns a {@link BufferLevels} that contains {@link BufferLevel} values for audio and video. */ __publicField(this, "getLevel", async (type) => { return BufferModule.getLevel(this.nativeId, type); }); /** * Sets the target buffer level for the chosen buffer {@link BufferType} across all {@link MediaType} options. * * @param type The {@link BufferType} to set the target level for. On iOS and tvOS, only {@link BufferType.FORWARD_DURATION} is supported. * @param value The value to set. On iOS and tvOS when passing `0`, the player will choose an appropriate forward buffer duration suitable for most use-cases. On Android setting to `0` will have no effect. */ __publicField(this, "setTargetLevel", async (type, value) => { return BufferModule.setTargetLevel(this.nativeId, type, value); }); this.nativeId = playerId; } }; // src/network/index.ts var import_react_native12 = require("react-native"); var import_BatchedBridge4 = __toESM(require("react-native/Libraries/BatchedBridge/BatchedBridge")); // src/network/networkConfig.ts var HttpRequestType = /* @__PURE__ */ ((HttpRequestType2) => { HttpRequestType2["ManifestDash"] = "manifest/dash"; HttpRequestType2["ManifestHlsMaster"] = "manifest/hls/master"; HttpRequestType2["ManifestHlsVariant"] = "manifest/hls/variant"; HttpRequestType2["ManifestSmooth"] = "manifest/smooth"; HttpRequestType2["MediaProgressive"] = "media/progressive"; HttpRequestType2["MediaAudio"] = "media/audio"; HttpRequestType2["MediaVideo"] = "media/video"; HttpRequestType2["MediaSubtitles"] = "media/subtitles"; HttpRequestType2["MediaThumbnails"] = "media/thumbnails"; HttpRequestType2["DrmLicenseFairplay"] = "drm/license/fairplay"; HttpRequestType2["DrmCertificateFairplay"] = "drm/certificate/fairplay"; HttpRequestType2["DrmLicenseWidevine"] = "drm/license/widevine"; HttpRequestType2["KeyHlsAes"] = "key/hls/aes"; HttpRequestType2["Unknown"] = "unknown"; return HttpRequestType2; })(HttpRequestType || {}); // src/network/index.ts var NetworkModule = import_react_native12.NativeModules.NetworkModule; var Network = class extends NativeInstance { constructor() { super(...arguments); /** * Whether this object's native instance has been created. */ __publicField(this, "isInitialized", false); /** * Whether this object's native instance has been disposed. */ __publicField(this, "isDestroyed", false); /** * Allocates the Network config instance and its resources natively. */ __publicField(this, "initialize", () => { if (!this.isInitialized) { import_BatchedBridge4.default.registerCallableModule(`Network-${this.nativeId}`, this); NetworkModule.initWithConfig(this.nativeId, this.config); this.isInitialized = true; } }); /** * Destroys the native Network config and releases all of its allocated resources. */ __publicField(this, "destroy", () => { if (!this.isDestroyed) { NetworkModule.destroy(this.nativeId); this.isDestroyed = true; } }); /** * Applies the user-defined `preprocessHttpRequest` function to native's `type` and `request` data and store * the result back in `NetworkModule`. * * Called from native code when `NetworkConfig.preprocessHttpRequest` is dispatched. * * @param requestId Passed through to identify the completion handler of the request on native. * @param type Type of the request to be made. * @param request The HTTP request to process. */ __publicField(this, "onPreprocessHttpRequest", (requestId, type, request) => { this.config?.preprocessHttpRequest?.(type, request).then((resultRequest) => { NetworkModule.setPreprocessedHttpRequest(requestId, resultRequest); }).catch(() => { NetworkModule.setPreprocessedHttpRequest(requestId, request); }); }); /** * Applies the user-defined `preprocessHttpResponse` function to native's `type` and `response` data and store * the result back in `NetworkModule`. * * Called from native code when `NetworkConfig.preprocessHttpResponse` is dispatched. * * @param responseId Passed through to identify the completion handler of the response on native. * @param type Type of the request to be made. * @param response The HTTP response to process. */ __publicField(this, "onPreprocessHttpResponse", (responseId, type, response) => { this.config?.preprocessHttpResponse?.(type, response).then((resultResponse) => { NetworkModule.setPreprocessedHttpResponse(responseId, resultResponse); }).catch(() => { NetworkModule.setPreprocessedHttpResponse(responseId, response); }); }); } }; // src/decoder/index.ts var import_react_native13 = require("react-native"); var import_BatchedBridge5 = __toESM(require("react-native/Libraries/BatchedBridge/BatchedBridge")); var DecoderConfigModule = import_react_native13.NativeModules.DecoderConfigModule; var DecoderConfigBridge = class extends NativeInstance { constructor(decoderConfig) { super(decoderConfig); /** * Whether this object's native instance has been created. */ __publicField(this, "isInitialized", false); /** * Whether this object's native instance has been disposed. */ __publicField(this, "isDestroyed", false); } initialize() { if (!this.isInitialized) { import_BatchedBridge5.default.registerCallableModule( `DecoderConfigBridge-${this.nativeId}`, this ); DecoderConfigModule.initWithConfig(this.nativeId, this.config); this.isInitialized = true; } } /** * Destroys the native `DecoderConfig` */ destroy() { if (!this.isDestroyed) { DecoderConfigModule.destroy(this.nativeId); this.isDestroyed = true; } } // noinspection JSUnusedGlobalSymbols /** * Called by native code, when the decoder priority should be evaluated. */ overrideDecodersPriority(context, preferredDecoders) { const orderedPriority = this.config?.decoderPriorityProvider?.overrideDecodersPriority( context, preferredDecoders ) ?? preferredDecoders; DecoderConfigModule.overrideDecoderPriorityProviderComplete( this.nativeId, orderedPriority ); } }; // src/player.ts var PlayerModule = import_react_native14.NativeModules.PlayerModule; var Player = class extends NativeInstance { constructor() { super(...arguments); /** * Whether the native `Player` object has been created. */ __publicField(this, "isInitialized", false); /** * Whether the native `Player` object has been disposed. */ __publicField(this, "isDestroyed", false); /** * Currently active source, or `null` if none is active. */ __publicField(this, "source"); /** * The `AnalyticsApi` for interactions regarding the `Player`'s analytics. * * `undefined` if the player was created without analytics support. */ __publicField(this, "analytics"); /** * The {@link BufferApi} for interactions regarding the buffer. */ __publicField(this, "buffer", new BufferApi(this.nativeId)); __publicField(this, "network"); __publicField(this, "decoderConfig"); /** * Allocates the native `Player` instance and its resources natively. */ __publicField(this, "initialize", () => { if (!this.isInitialized) { if (this.config?.networkConfig) { this.network = new Network(this.config.networkConfig); this.network.initialize(); } this.maybeInitDecoderConfig(); const analyticsConfig = this.config?.analyticsConfig; if (analyticsConfig) { PlayerModule.initWithAnalyticsConfig( this.nativeId, this.config, this.network?.nativeId, this.decoderConfig?.nativeId, analyticsConfig ); this.analytics = new AnalyticsApi(this.nativeId); } else { PlayerModule.initWithConfig( this.nativeId, this.config, this.network?.nativeId, this.decoderConfig?.nativeId ); } this.isInitialized = true; } }); /** * Destroys the native `Player` and releases all of its allocated resources. */ __publicField(this, "destroy", () => { if (!this.isDestroyed) { PlayerModule.destroy(this.nativeId); this.source?.destroy(); this.network?.destroy(); this.decoderConfig?.destroy(); this.isDestroyed = true; } }); /** * Loads a new {@link Source} from `sourceConfig` into the player. */ __publicField(this, "load", (sourceConfig) => { this.loadSource(new Source(sourceConfig)); }); /** * Loads the downloaded content from {@link OfflineContentManager} into the player. */ __publicField(this, "loadOfflineContent", (offlineContentManager, options) => { PlayerModule.loadOfflineContent( this.nativeId, offlineContentManager.nativeId, options ); }); /** * Loads the given {@link Source} into the player. */ __publicField(this, "loadSource", (source) => { source.initialize(); this.source = source; PlayerModule.loadSource(this.nativeId, source.nativeId); }); /** * Unloads all {@link Source}s from the player. */ __publicField(this, "unload", () => { PlayerModule.unload(this.nativeId); }); /** * Starts or resumes playback after being paused. Has no effect if the player is already playing. */ __publicField(this, "play", () => { PlayerModule.play(this.nativeId); }); /** * Pauses the video if it is playing. Has no effect if the player is already paused. */ __publicField(this, "pause", () => { PlayerModule.pause(this.nativeId); }); /** * Seeks to the given playback time specified by the parameter `time` in seconds. Must not be * greater than the total duration of the video. Has no effect when watching a live stream since * seeking is not possible. * * @param time - The time to seek to in seconds. */ __publicField(this, "seek", (time) => { PlayerModule.seek(this.nativeId, time); }); /** * Shifts the time to the given `offset` in seconds from the live edge. The resulting offset has to be within the * timeShift window as specified by `maxTimeShift` (which is a negative value) and 0. When the provided `offset` is * positive, it will be interpreted as a UNIX timestamp in seconds and converted to fit into the timeShift window. * When the provided `offset` is negative, but lower than `maxTimeShift`, then it will be clamped to `maxTimeShift`. * Has no effect for VoD. * * Has no effect if no sources are loaded. * * @param offset - Target offset from the live edge in seconds. */ __publicField(this, "timeShift", (offset) => { PlayerModule.timeShift(this.nativeId, offset); }); /** * Mutes the player if an audio track is available. Has no effect if the player is already muted. */ __publicField(this, "mute", () => { PlayerModule.mute(this.nativeId); }); /** * Unmutes the player if it is muted. Has no effect if the player is already unmuted. */ __publicField(this, "unmute", () => { PlayerModule.unmute(this.nativeId); }); /** * Sets the player's volume between 0 (silent) and 100 (max volume). * * @param volume - The volume level to set. */ __publicField(this, "setVolume", (volume) => { PlayerModule.setVolume(this.nativeId, volume); }); /** * @returns The player's current volume level. */ __publicField(this, "getVolume", async () => { return PlayerModule.getVolume(this.nativeId); }); /** * @returns The current playback time in seconds. * * For VoD streams the returned time ranges between 0 and the duration of the asset. * * For live streams it can be specified if an absolute UNIX timestamp or a value * relative to the playback start should be returned. * * @param mode - The time mode to specify: an absolute UNIX timestamp ('absolute') or relative time ('relative'). */ __publicField(this, "getCurrentTime", async (mode = "absolute") => { return PlayerModule.currentTime(this.nativeId, mode); }); /** * @returns The total duration in seconds of the current video or INFINITY if it’s a live stream. */ __publicField(this, "getDuration", async () => { return PlayerModule.duration(this.nativeId); }); /** * @returns `true` if the player is muted. */ __publicField(this, "isMuted", async () => { return PlayerModule.isMuted(this.nativeId); }); /** * @returns `true` if the player is currently playing, i.e. has started and is not paused. */ __publicField(this, "isPlaying", async () => { return PlayerModule.isPlaying(this.nativeId); }); /** * @returns `true` if the player has started playback but it's currently paused. */ __publicField(this, "isPaused", async () => { return PlayerModule.isPaused(this.nativeId); }); /** * @returns `true` if the displayed video is a live stream. */ __publicField(this, "isLive", async () => { return PlayerModule.isLive(this.nativeId); }); /** * @remarks Only available for iOS devices. * @returns `true` when media is played externally using AirPlay. */ __publicField(this, "isAirPlayActive", async () => { if (import_react_native14.Platform.OS === "android") { console.warn( `[Player ${this.nativeId}] Method isAirPlayActive is not available for Android. Only iOS devices.` ); return false; } return PlayerModule.isAirPlayActive(this.nativeId); }); /** * @remarks Only available for iOS devices. * @returns `true` when AirPlay is available. */ __publicField(this, "isAirPlayAvailable", async () => { if (import_react_native14.Platform.OS === "android") { console.warn( `[Player ${this.nativeId}] Method isAirPlayAvailable is not available for Android. Only iOS devices.` ); return false; } return PlayerModule.isAirPlayAvailable(this.nativeId); }); /** * @returns The currently selected audio track or `null`. */ __publicField(this, "getAudioTrack", async () => { return PlayerModule.getAudioTrack(this.nativeId); }); /** * @returns An array containing {@link AudioTrack} objects for all available audio tracks. */ __publicField(this, "getAvailableAudioTracks", async () => { return PlayerModule.getAvailableAudioTracks(this.nativeId); }); /** * Sets the audio track to the ID specified by trackIdentifier. A list can be retrieved by calling getAvailableAudioTracks. * * @param trackIdentifier - The {@link AudioTrack.identifier} to be set. */ __publicField(this, "setAudioTrack", async (trackIdentifier) => { return PlayerModule.setAudioTrack(this.nativeId, trackIdentifier); }); /** * @returns The currently selected {@link SubtitleTrack} or `null`. */ __publicField(this, "getSubtitleTrack", async () => { return PlayerModule.getSubtitleTrack(this.nativeId); }); /** * @returns An array containing SubtitleTrack objects for all available subtitle tracks. */ __publicField(this, "getAvailableSubtitles", async () => { return PlayerModule.getAvailableSubtitles(this.nativeId); }); /** * Sets the subtitle track to the ID specified by trackIdentifier. A list can be retrieved by calling getAvailableSubtitles. * * @param trackIdentifier - The {@link SubtitleTrack.identifier} to be set. */ __publicField(this, "setSubtitleTrack", async (trackIdentifier) => { return PlayerModule.setSubtitleTrack(this.nativeId, trackIdentifier); }); /** * Dynamically schedules the {@link AdItem} for playback. * Has no effect if there is no active playback session. * * @param adItem - Ad to be scheduled for playback. * * @platform iOS, Android */ __publicField(this, "scheduleAd", (adItem) => { PlayerModule.scheduleAd(this.nativeId, adItem); }); /** * Skips the current ad. * Has no effect if the current ad is not skippable or if no ad is being played back. * * @platform iOS, Android */ __publicField(this, "skipAd", () => { PlayerModule.skipAd(this.nativeId); }); /** * @returns `true` while an ad is being played back or when main content playback has been paused for ad playback. * @platform iOS, Android */ __publicField(this, "isAd", async () => { return PlayerModule.isAd(this.nativeId); }); /** * The current time shift of the live stream in seconds. This value is always 0 if the active {@link Source} is not a * live stream or no sources are loaded. */ __publicField(this, "getTimeShift", async () => { return PlayerModule.getTimeShift(this.nativeId); }); /** * The limit in seconds for time shifting. This value is either negative or 0 and it is always 0 if the active * {@link Source} is not a live stream or no sources are loaded. */ __publicField(this, "getMaxTimeShift", async () => { return PlayerModule.getMaxTimeShift(this.nativeId); }); /** * Sets the upper bitrate boundary for video qualities. All qualities with a bitrate * that is higher than this threshold will not be eligible for automatic quality selection. * * Can be set to `null` for no limitation. */ __publicField(this, "setMaxSelectableBitrate", (bitrate) => { PlayerModule.setMaxSelectableBitrate(this.nativeId, bitrate || -1); }); /** * @returns a {@link Thumbnail} for the specified playback time for the currently active source if available. * Supported thumbnail formats are: * - `WebVtt` configured via {@link SourceConfig.thumbnailTrack}, on all supported platforms * - HLS `Image Media Playlist` in the multivariant playlist, Android-only * - DASH `Image Adaptation Set` as specified in DASH-IF IOP, Android-only * If a `WebVtt` thumbnail track is provided, any potential in-manifest thumbnails are ignored on Android. * * @param time - The time in seconds for which to retrieve the thumbnail. */ __publicField(this, "getThumbnail", async (time) => { return PlayerModule.getThumbnail(this.nativeId, time); }); /** * Whether casting to a cast-compatible remote device is available. {@link CastAvailableEvent} signals when * casting becomes available. * * @platform iOS, Android */ __publicField(this, "isCastAvailable", async () => { return PlayerModule.isCastAvailable(this.nativeId); }); /** * Whether video is currently being casted to a remote device and not played locally. * * @platform iOS, Android */ __pu