From 6423ed0bc520120d2b8df8f94e2c51ae6e261908 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 26 Jul 2026 12:51:52 +0200 Subject: [PATCH] feat(android): allow both exoplayer and vlc --- .../main/java/dev/zoriya/omni/OmniPlayer.kt | 34 ++++++-- .../java/dev/zoriya/omni/OmniPlayerFactory.kt | 6 +- .../generated/android/c++/JAndroidBackend.hpp | 58 +++++++++++++ .../c++/JHybridOmniPlayerFactorySpec.cpp | 14 ++- .../c++/JHybridOmniPlayerFactorySpec.hpp | 2 +- .../generated/android/c++/JPlayerBackend.hpp | 59 +++++++++++++ .../com/margelo/nitro/omni/AndroidBackend.kt | 23 +++++ .../nitro/omni/HybridOmniPlayerFactorySpec.kt | 2 +- .../com/margelo/nitro/omni/PlayerBackend.kt | 51 +++++++++++ .../generated/shared/c++/AndroidBackend.hpp | 76 +++++++++++++++++ .../c++/HybridOmniPlayerFactorySpec.hpp | 5 +- .../generated/shared/c++/PlayerBackend.hpp | 85 +++++++++++++++++++ src/index.ts | 2 + src/provider.tsx | 8 +- src/provider.web.tsx | 5 +- src/specs/omni-player.nitro.ts | 3 +- src/types/player.ts | 6 ++ 17 files changed, 418 insertions(+), 21 deletions(-) create mode 100644 nitrogen/generated/android/c++/JAndroidBackend.hpp create mode 100644 nitrogen/generated/android/c++/JPlayerBackend.hpp create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/omni/AndroidBackend.kt create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/omni/PlayerBackend.kt create mode 100644 nitrogen/generated/shared/c++/AndroidBackend.hpp create mode 100644 nitrogen/generated/shared/c++/PlayerBackend.hpp diff --git a/android/src/main/java/dev/zoriya/omni/OmniPlayer.kt b/android/src/main/java/dev/zoriya/omni/OmniPlayer.kt index 871463b..6ecdbca 100644 --- a/android/src/main/java/dev/zoriya/omni/OmniPlayer.kt +++ b/android/src/main/java/dev/zoriya/omni/OmniPlayer.kt @@ -15,7 +15,12 @@ import androidx.media3.common.C import androidx.media3.common.MediaItem import androidx.media3.common.MediaMetadata import androidx.media3.common.Player +import androidx.media3.datasource.DefaultDataSource +import androidx.media3.datasource.DefaultHttpDataSource +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import com.margelo.nitro.NitroModules +import com.margelo.nitro.omni.AndroidBackend import com.margelo.nitro.omni.CastStatus import com.margelo.nitro.omni.HybridOmniPlayerSpec import com.margelo.nitro.omni.MixAudioMode @@ -35,17 +40,26 @@ import dev.zoriya.omni.utils.ThreadHelper.runOnMainThread import dev.zoriya.omni.utils.ThreadHelper.runOnMainThreadSync @SuppressLint("UnsafeOptInUsageError") -class OmniPlayer : HybridOmniPlayerSpec() { +class OmniPlayer(private val backend: AndroidBackend = AndroidBackend.VLC) : HybridOmniPlayerSpec() { private val ctx = NitroModules.applicationContext ?: throw Error("No Context available!") + + // exoplayer only, used to specify request headers. + private var httpDataSourceFactory: DefaultHttpDataSource.Factory? = null + val player: Player = runOnMainThreadSync { - // To use ExoPlayer, build it with an http data source and refresh its - // request headers from the source on each change: - // val http = DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true) - // ExoPlayer.Builder(ctx) - // .setMediaSourceFactory(DefaultMediaSourceFactory(DefaultDataSource.Factory(ctx, http))) - // .build() - // // in the source setter: http.setDefaultRequestProperties(firstSrc.headers) - VlcPlayer(ctx) + when (backend) { + AndroidBackend.EXOPLAYER -> { + val http = DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true) + httpDataSourceFactory = http + ExoPlayer.Builder(ctx) + .setMediaSourceFactory( + DefaultMediaSourceFactory(DefaultDataSource.Factory(ctx, http)) + ) + .build() + } + + AndroidBackend.VLC -> VlcPlayer(ctx) + } } override val eventMap = EventMap(player) @@ -207,6 +221,8 @@ class OmniPlayer : HybridOmniPlayerSpec() { return } + httpDataSourceFactory?.setDefaultRequestProperties(firstSrc.headers) + val currentItem = buildMediaItem(firstSrc, value.metadata, value.subtitles) val mediaItems = mutableListOf() diff --git a/android/src/main/java/dev/zoriya/omni/OmniPlayerFactory.kt b/android/src/main/java/dev/zoriya/omni/OmniPlayerFactory.kt index cb4fd0b..1a8b457 100755 --- a/android/src/main/java/dev/zoriya/omni/OmniPlayerFactory.kt +++ b/android/src/main/java/dev/zoriya/omni/OmniPlayerFactory.kt @@ -2,13 +2,15 @@ package dev.zoriya.omni import android.util.Log import com.facebook.react.uimanager.ThemedReactContext +import com.margelo.nitro.omni.AndroidBackend import com.margelo.nitro.omni.HybridOmniPlayerFactorySpec import com.margelo.nitro.omni.HybridOmniPlayerSpec +import com.margelo.nitro.omni.PlayerBackend import com.margelo.nitro.omni.Source class OmniPlayerFactory(val context: ThemedReactContext) : HybridOmniPlayerFactorySpec() { - override fun createPlayer(props: Source?): HybridOmniPlayerSpec { - return OmniPlayer().apply { + override fun createPlayer(props: Source?, backend: PlayerBackend?): HybridOmniPlayerSpec { + return OmniPlayer(backend?.android ?: AndroidBackend.VLC).apply { source = props } } diff --git a/nitrogen/generated/android/c++/JAndroidBackend.hpp b/nitrogen/generated/android/c++/JAndroidBackend.hpp new file mode 100644 index 0000000..9b57b35 --- /dev/null +++ b/nitrogen/generated/android/c++/JAndroidBackend.hpp @@ -0,0 +1,58 @@ +/// +/// JAndroidBackend.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "AndroidBackend.hpp" + +namespace margelo::nitro::omni { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "AndroidBackend" and the Kotlin enum "AndroidBackend". + */ + struct JAndroidBackend final: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/omni/AndroidBackend;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum AndroidBackend. + */ + [[maybe_unused]] + [[nodiscard]] + AndroidBackend toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldOrdinal = clazz->getField("value"); + int ordinal = this->getFieldValue(fieldOrdinal); + return static_cast(ordinal); + } + + public: + /** + * Create a Java/Kotlin-based enum with the given C++ enum's value. + */ + [[maybe_unused]] + static jni::alias_ref fromCpp(AndroidBackend value) { + static const auto clazz = javaClassStatic(); + switch (value) { + case AndroidBackend::VLC: + static const auto fieldVLC = clazz->getStaticField("VLC"); + return clazz->getStaticFieldValue(fieldVLC); + case AndroidBackend::EXOPLAYER: + static const auto fieldEXOPLAYER = clazz->getStaticField("EXOPLAYER"); + return clazz->getStaticFieldValue(fieldEXOPLAYER); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::omni diff --git a/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.cpp b/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.cpp index 63423c0..1060128 100644 --- a/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.cpp +++ b/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.cpp @@ -19,6 +19,10 @@ namespace margelo::nitro::omni { struct Subtitle; } namespace margelo::nitro::omni { struct Metadata; } // Forward declaration of `MixAudioMode` to properly resolve imports. namespace margelo::nitro::omni { enum class MixAudioMode; } +// Forward declaration of `PlayerBackend` to properly resolve imports. +namespace margelo::nitro::omni { struct PlayerBackend; } +// Forward declaration of `AndroidBackend` to properly resolve imports. +namespace margelo::nitro::omni { enum class AndroidBackend; } #include #include "HybridOmniPlayerSpec.hpp" @@ -37,6 +41,10 @@ namespace margelo::nitro::omni { enum class MixAudioMode; } #include "JMetadata.hpp" #include "MixAudioMode.hpp" #include "JMixAudioMode.hpp" +#include "PlayerBackend.hpp" +#include "JPlayerBackend.hpp" +#include "AndroidBackend.hpp" +#include "JAndroidBackend.hpp" namespace margelo::nitro::omni { @@ -71,9 +79,9 @@ namespace margelo::nitro::omni { // Methods - std::shared_ptr JHybridOmniPlayerFactorySpec::createPlayer(const std::optional& props) { - static const auto method = _javaPart->javaClassStatic()->getMethod(jni::alias_ref /* props */)>("createPlayer"); - auto __result = method(_javaPart, props.has_value() ? JSource::fromCpp(props.value()) : nullptr); + std::shared_ptr JHybridOmniPlayerFactorySpec::createPlayer(const std::optional& props, const std::optional& backend) { + static const auto method = _javaPart->javaClassStatic()->getMethod(jni::alias_ref /* props */, jni::alias_ref /* backend */)>("createPlayer"); + auto __result = method(_javaPart, props.has_value() ? JSource::fromCpp(props.value()) : nullptr, backend.has_value() ? JPlayerBackend::fromCpp(backend.value()) : nullptr); return __result->getJHybridOmniPlayerSpec(); } diff --git a/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.hpp b/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.hpp index 50785a5..79ab9cc 100644 --- a/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.hpp +++ b/nitrogen/generated/android/c++/JHybridOmniPlayerFactorySpec.hpp @@ -54,7 +54,7 @@ namespace margelo::nitro::omni { public: // Methods - std::shared_ptr createPlayer(const std::optional& props) override; + std::shared_ptr createPlayer(const std::optional& props, const std::optional& backend) override; private: jni::global_ref _javaPart; diff --git a/nitrogen/generated/android/c++/JPlayerBackend.hpp b/nitrogen/generated/android/c++/JPlayerBackend.hpp new file mode 100644 index 0000000..1ef5479 --- /dev/null +++ b/nitrogen/generated/android/c++/JPlayerBackend.hpp @@ -0,0 +1,59 @@ +/// +/// JPlayerBackend.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "PlayerBackend.hpp" + +#include "AndroidBackend.hpp" +#include "JAndroidBackend.hpp" +#include + +namespace margelo::nitro::omni { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "PlayerBackend" and the Kotlin data class "PlayerBackend". + */ + struct JPlayerBackend final: public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/omni/PlayerBackend;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct PlayerBackend by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + PlayerBackend toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldAndroid = clazz->getField("android"); + jni::local_ref android = this->getFieldValue(fieldAndroid); + return PlayerBackend( + android != nullptr ? std::make_optional(android->toCpp()) : std::nullopt + ); + } + + public: + /** + * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. + */ + [[maybe_unused]] + static jni::local_ref fromCpp(const PlayerBackend& value) { + using JSignature = JPlayerBackend(jni::alias_ref); + static const auto clazz = javaClassStatic(); + static const auto create = clazz->getStaticMethod("fromCpp"); + return create( + clazz, + value.android.has_value() ? JAndroidBackend::fromCpp(value.android.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::omni diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/AndroidBackend.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/AndroidBackend.kt new file mode 100644 index 0000000..ce546af --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/AndroidBackend.kt @@ -0,0 +1,23 @@ +/// +/// AndroidBackend.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.omni + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "AndroidBackend". + */ +@DoNotStrip +@Keep +enum class AndroidBackend(@DoNotStrip @Keep val value: Int) { + VLC(0), + EXOPLAYER(1); + + companion object +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/HybridOmniPlayerFactorySpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/HybridOmniPlayerFactorySpec.kt index 96b18be..46211a4 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/HybridOmniPlayerFactorySpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/HybridOmniPlayerFactorySpec.kt @@ -30,7 +30,7 @@ abstract class HybridOmniPlayerFactorySpec: HybridObject() { // Methods @DoNotStrip @Keep - abstract fun createPlayer(props: Source?): HybridOmniPlayerSpec + abstract fun createPlayer(props: Source?, backend: PlayerBackend?): HybridOmniPlayerSpec // Default implementation of `HybridObject.toString()` override fun toString(): String { diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/PlayerBackend.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/PlayerBackend.kt new file mode 100644 index 0000000..f8adf01 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/omni/PlayerBackend.kt @@ -0,0 +1,51 @@ +/// +/// PlayerBackend.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.omni + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import java.util.Objects + + +/** + * Represents the JavaScript object/struct "PlayerBackend". + */ +@DoNotStrip +@Keep +data class PlayerBackend( + @DoNotStrip + @Keep + val android: AndroidBackend? +) { + /* primary constructor */ + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is PlayerBackend) return false + return Objects.deepEquals(this.android, other.android) + } + + override fun hashCode(): Int { + return arrayOf( + android + ).contentDeepHashCode() + } + + companion object { + /** + * Constructor called from C++ + */ + @DoNotStrip + @Keep + @Suppress("unused") + @JvmStatic + private fun fromCpp(android: AndroidBackend?): PlayerBackend { + return PlayerBackend(android) + } + } +} diff --git a/nitrogen/generated/shared/c++/AndroidBackend.hpp b/nitrogen/generated/shared/c++/AndroidBackend.hpp new file mode 100644 index 0000000..838218f --- /dev/null +++ b/nitrogen/generated/shared/c++/AndroidBackend.hpp @@ -0,0 +1,76 @@ +/// +/// AndroidBackend.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +namespace margelo::nitro::omni { + + /** + * An enum which can be represented as a JavaScript union (AndroidBackend). + */ + enum class AndroidBackend { + VLC SWIFT_NAME(vlc) = 0, + EXOPLAYER SWIFT_NAME(exoplayer) = 1, + } CLOSED_ENUM; + +} // namespace margelo::nitro::omni + +namespace margelo::nitro { + + // C++ AndroidBackend <> JS AndroidBackend (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::omni::AndroidBackend fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("vlc"): return margelo::nitro::omni::AndroidBackend::VLC; + case hashString("exoplayer"): return margelo::nitro::omni::AndroidBackend::EXOPLAYER; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum AndroidBackend - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::omni::AndroidBackend arg) { + switch (arg) { + case margelo::nitro::omni::AndroidBackend::VLC: return JSIConverter::toJSI(runtime, "vlc"); + case margelo::nitro::omni::AndroidBackend::EXOPLAYER: return JSIConverter::toJSI(runtime, "exoplayer"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert AndroidBackend to JS - invalid value: " + + std::to_string(static_cast(arg)) + "!"); + } + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isString()) { + return false; + } + std::string unionValue = JSIConverter::fromJSI(runtime, value); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("vlc"): + case hashString("exoplayer"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/HybridOmniPlayerFactorySpec.hpp b/nitrogen/generated/shared/c++/HybridOmniPlayerFactorySpec.hpp index 3d9938d..a6d9752 100644 --- a/nitrogen/generated/shared/c++/HybridOmniPlayerFactorySpec.hpp +++ b/nitrogen/generated/shared/c++/HybridOmniPlayerFactorySpec.hpp @@ -17,11 +17,14 @@ namespace margelo::nitro::omni { class HybridOmniPlayerSpec; } // Forward declaration of `Source` to properly resolve imports. namespace margelo::nitro::omni { struct Source; } +// Forward declaration of `PlayerBackend` to properly resolve imports. +namespace margelo::nitro::omni { struct PlayerBackend; } #include #include "HybridOmniPlayerSpec.hpp" #include "Source.hpp" #include +#include "PlayerBackend.hpp" namespace margelo::nitro::omni { @@ -54,7 +57,7 @@ namespace margelo::nitro::omni { public: // Methods - virtual std::shared_ptr createPlayer(const std::optional& props) = 0; + virtual std::shared_ptr createPlayer(const std::optional& props, const std::optional& backend) = 0; protected: // Hybrid Setup diff --git a/nitrogen/generated/shared/c++/PlayerBackend.hpp b/nitrogen/generated/shared/c++/PlayerBackend.hpp new file mode 100644 index 0000000..d5fc99b --- /dev/null +++ b/nitrogen/generated/shared/c++/PlayerBackend.hpp @@ -0,0 +1,85 @@ +/// +/// PlayerBackend.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `AndroidBackend` to properly resolve imports. +namespace margelo::nitro::omni { enum class AndroidBackend; } + +#include "AndroidBackend.hpp" +#include + +namespace margelo::nitro::omni { + + /** + * A struct which can be represented as a JavaScript object (PlayerBackend). + */ + struct PlayerBackend final { + public: + std::optional android SWIFT_PRIVATE; + + public: + PlayerBackend() = default; + explicit PlayerBackend(std::optional android): android(android) {} + + public: + friend bool operator==(const PlayerBackend& lhs, const PlayerBackend& rhs) = default; + }; + +} // namespace margelo::nitro::omni + +namespace margelo::nitro { + + // C++ PlayerBackend <> JS PlayerBackend (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::omni::PlayerBackend fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::omni::PlayerBackend( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "android"))) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::omni::PlayerBackend& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "android"), JSIConverter>::toJSI(runtime, arg.android)); + return obj; + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "android")))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/src/index.ts b/src/index.ts index 47a9deb..b2b0aba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,9 +2,11 @@ export { useEvent, usePlayerState } from "./events"; export { OmniProvider, usePlayer } from "./provider"; export type { OmniEvents } from "./types/events"; export type { + AndroidBackend, CastStatus, OmniPlayer, OmniPlayerState, + PlayerBackend, PlayerStatus, Rendition, Track, diff --git a/src/provider.tsx b/src/provider.tsx index 9d8b69f..986947c 100755 --- a/src/provider.tsx +++ b/src/provider.tsx @@ -1,7 +1,7 @@ import { createContext, type ReactNode, useContext, useEffect } from "react"; import { NitroModules } from "react-native-nitro-modules"; import type { OmniPlayerFactory } from "./specs/omni-player.nitro"; -import type { OmniPlayer } from "./types/player"; +import type { OmniPlayer, PlayerBackend } from "./types/player"; import type { CastOptions, Source } from "./types/source"; import { useLazyRef } from "./utils/lazy-ref"; @@ -13,15 +13,19 @@ const PlayerCtx = createContext(null!); export const OmniProvider = ({ children, source, + backend = { android: "vlc" }, showNotification = false, cast: _, }: { source?: Source; cast?: CastOptions; + backend?: PlayerBackend; children: ReactNode; showNotification?: boolean; }) => { - const player = useLazyRef(() => ProviderFactory.createPlayer(source)); + const player = useLazyRef(() => + ProviderFactory.createPlayer(source, backend), + ); useEffect(() => { player.source = source; diff --git a/src/provider.web.tsx b/src/provider.web.tsx index b257c26..2ed05d1 100644 --- a/src/provider.web.tsx +++ b/src/provider.web.tsx @@ -8,7 +8,7 @@ import { useRef, } from "react"; import { WebOmniPlayer } from "./player.web"; -import type { OmniPlayer } from "./types/player"; +import type { OmniPlayer, PlayerBackend } from "./types/player"; import type { CastOptions, Source } from "./types/source"; import { useLazyRef } from "./utils/lazy-ref"; @@ -20,10 +20,13 @@ export const OmniProvider = ({ children, source, cast, + // Web always uses video.js; accepted for API parity with native. + backend: _backend, showNotification = false, }: { source?: Source; cast?: CastOptions; + backend?: PlayerBackend; children: ReactNode; showNotification?: boolean; }) => { diff --git a/src/specs/omni-player.nitro.ts b/src/specs/omni-player.nitro.ts index 98b896f..2010353 100644 --- a/src/specs/omni-player.nitro.ts +++ b/src/specs/omni-player.nitro.ts @@ -3,6 +3,7 @@ import type { OmniEvents } from "../types/events"; import type { OmniPlayerState, OmniPlayer as OmniPlayerT, + PlayerBackend, PlayerStatus, } from "../types/player"; import type { Source } from "../types/source"; @@ -59,5 +60,5 @@ export interface OmniPlayer } export interface OmniPlayerFactory extends HybridObject<{ android: "kotlin" }> { - createPlayer(props?: Source): OmniPlayer; + createPlayer(props?: Source, backend?: PlayerBackend): OmniPlayer; } diff --git a/src/types/player.ts b/src/types/player.ts index f32f172..d9f8cc3 100644 --- a/src/types/player.ts +++ b/src/types/player.ts @@ -64,3 +64,9 @@ export interface Rendition { readonly bitrate: number; readonly selected: boolean; } + +export type AndroidBackend = "vlc" | "exoplayer"; + +export interface PlayerBackend { + android?: AndroidBackend; +}