mirror of
https://github.com/zoriya/react-native-video.git
synced 2026-06-05 03:39:41 +00:00
refactor: don't use nitro dispose (#4802)
This commit is contained in:
@@ -52,7 +52,7 @@
|
|||||||
},
|
},
|
||||||
"example": {
|
"example": {
|
||||||
"name": "react-native-video-example",
|
"name": "react-native-video-example",
|
||||||
"version": "7.0.0-beta.0",
|
"version": "7.0.0-beta.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-native-community/slider": "^4.5.6",
|
"@react-native-community/slider": "^4.5.6",
|
||||||
"@react-native-video/drm": "*",
|
"@react-native-video/drm": "*",
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
},
|
},
|
||||||
"packages/drm-plugin": {
|
"packages/drm-plugin": {
|
||||||
"name": "@react-native-video/drm",
|
"name": "@react-native-video/drm",
|
||||||
"version": "7.0.0-beta.0",
|
"version": "7.0.0-beta.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native/babel-preset": "0.79.2",
|
"@react-native/babel-preset": "0.79.2",
|
||||||
"@release-it/conventional-changelog": "^9.0.2",
|
"@release-it/conventional-changelog": "^9.0.2",
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
},
|
},
|
||||||
"packages/react-native-video": {
|
"packages/react-native-video": {
|
||||||
"name": "react-native-video",
|
"name": "react-native-video",
|
||||||
"version": "7.0.0-beta.0",
|
"version": "7.0.0-beta.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@expo/config-plugins": "^10.0.2",
|
"@expo/config-plugins": "^10.0.2",
|
||||||
"@react-native/eslint-config": "^0.77.0",
|
"@react-native/eslint-config": "^0.77.0",
|
||||||
|
|||||||
@@ -1565,7 +1565,7 @@ PODS:
|
|||||||
- React-logger (= 0.77.3)
|
- React-logger (= 0.77.3)
|
||||||
- React-perflogger (= 0.77.3)
|
- React-perflogger (= 0.77.3)
|
||||||
- React-utils (= 0.77.3)
|
- React-utils (= 0.77.3)
|
||||||
- ReactNativeVideo (7.0.0-beta.0):
|
- ReactNativeVideo (7.0.0-beta.1):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -1587,7 +1587,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- ReactNativeVideoDrm (7.0.0-beta.0):
|
- ReactNativeVideoDrm (7.0.0-beta.1):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -1904,8 +1904,8 @@ SPEC CHECKSUMS:
|
|||||||
ReactAppDependencyProvider: 31015410a4a53b9fd0a908ad4d6e3e2b9a25086a
|
ReactAppDependencyProvider: 31015410a4a53b9fd0a908ad4d6e3e2b9a25086a
|
||||||
ReactCodegen: 53316394e985ded1babc7f143c90c77d2bb1b43c
|
ReactCodegen: 53316394e985ded1babc7f143c90c77d2bb1b43c
|
||||||
ReactCommon: bf4612cba0fa356b529385029f470d5529dddde4
|
ReactCommon: bf4612cba0fa356b529385029f470d5529dddde4
|
||||||
ReactNativeVideo: 5a5e609057e980e9ea2736914377804358c53ae9
|
ReactNativeVideo: 10dd0a47f8228b41565a3efb13df5b323633b590
|
||||||
ReactNativeVideoDrm: 4f266c3b018170319ed16bc511218c0d411358d5
|
ReactNativeVideoDrm: 07b826ab66fd0a00ab3dd3bef2dd2c026e919a9a
|
||||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||||
Yoga: 92f3bb322c40a86b7233b815854730442e01b8c4
|
Yoga: 92f3bb322c40a86b7233b815854730442e01b8c4
|
||||||
|
|
||||||
|
|||||||
+6
@@ -33,6 +33,12 @@ namespace margelo::nitro::videodrm {
|
|||||||
method(_javaPart);
|
method(_javaPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string JHybridPluginManagerSpec::toString() {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<jni::JString()>("toString");
|
||||||
|
auto javaString = method(_javaPart);
|
||||||
|
return javaString->toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
bool JHybridPluginManagerSpec::getIsEnabled() {
|
bool JHybridPluginManagerSpec::getIsEnabled() {
|
||||||
static const auto method = javaClassStatic()->getMethod<jboolean()>("isEnabled");
|
static const auto method = javaClassStatic()->getMethod<jboolean()>("isEnabled");
|
||||||
|
|||||||
+1
@@ -41,6 +41,7 @@ namespace margelo::nitro::videodrm {
|
|||||||
public:
|
public:
|
||||||
size_t getExternalMemorySize() noexcept override;
|
size_t getExternalMemorySize() noexcept override;
|
||||||
void dispose() noexcept override;
|
void dispose() noexcept override;
|
||||||
|
std::string toString() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline const jni::global_ref<JHybridPluginManagerSpec::javaobject>& getJavaPart() const noexcept {
|
inline const jni::global_ref<JHybridPluginManagerSpec::javaobject>& getJavaPart() const noexcept {
|
||||||
|
|||||||
+6
-1
@@ -10,7 +10,7 @@ package com.margelo.nitro.videodrm
|
|||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.facebook.jni.HybridData
|
import com.facebook.jni.HybridData
|
||||||
import com.facebook.proguard.annotations.DoNotStrip
|
import com.facebook.proguard.annotations.DoNotStrip
|
||||||
import com.margelo.nitro.core.*
|
import com.margelo.nitro.core.HybridObject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin class representing the PluginManager HybridObject.
|
* A Kotlin class representing the PluginManager HybridObject.
|
||||||
@@ -36,6 +36,11 @@ abstract class HybridPluginManagerSpec: HybridObject() {
|
|||||||
super.updateNative(hybridData)
|
super.updateNative(hybridData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default implementation of `HybridObject.toString()`
|
||||||
|
override fun toString(): String {
|
||||||
|
return "[HybridObject PluginManager]"
|
||||||
|
}
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
@get:DoNotStrip
|
@get:DoNotStrip
|
||||||
@get:Keep
|
@get:Keep
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@
|
|||||||
// Include C++ implementation defined types
|
// Include C++ implementation defined types
|
||||||
#include "HybridPluginManagerSpecSwift.hpp"
|
#include "HybridPluginManagerSpecSwift.hpp"
|
||||||
#include "ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp"
|
#include "ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp"
|
||||||
|
#include <NitroModules/NitroDefines.hpp>
|
||||||
|
|
||||||
namespace margelo::nitro::videodrm::bridge::swift {
|
namespace margelo::nitro::videodrm::bridge::swift {
|
||||||
|
|
||||||
|
|||||||
+3
@@ -50,6 +50,9 @@ namespace margelo::nitro::videodrm {
|
|||||||
void dispose() noexcept override {
|
void dispose() noexcept override {
|
||||||
_swiftPart.dispose();
|
_swiftPart.dispose();
|
||||||
}
|
}
|
||||||
|
std::string toString() override {
|
||||||
|
return _swiftPart.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Properties
|
// Properties
|
||||||
|
|||||||
+7
@@ -18,6 +18,13 @@ public protocol HybridPluginManagerSpec_protocol: HybridObject {
|
|||||||
func disable() throws -> Void
|
func disable() throws -> Void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extension HybridPluginManagerSpec_protocol {
|
||||||
|
/// Default implementation of ``HybridObject.toString``
|
||||||
|
func toString() -> String {
|
||||||
|
return "[HybridObject PluginManager]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// See ``HybridPluginManagerSpec``
|
/// See ``HybridPluginManagerSpec``
|
||||||
open class HybridPluginManagerSpec_base {
|
open class HybridPluginManagerSpec_base {
|
||||||
private weak var cxxWrapper: HybridPluginManagerSpec_cxx? = nil
|
private weak var cxxWrapper: HybridPluginManagerSpec_cxx? = nil
|
||||||
|
|||||||
+9
-1
@@ -76,7 +76,7 @@ open class HybridPluginManagerSpec_cxx {
|
|||||||
*/
|
*/
|
||||||
public func getCxxPart() -> bridge.std__shared_ptr_HybridPluginManagerSpec_ {
|
public func getCxxPart() -> bridge.std__shared_ptr_HybridPluginManagerSpec_ {
|
||||||
let cachedCxxPart = self.__cxxPart.lock()
|
let cachedCxxPart = self.__cxxPart.lock()
|
||||||
if cachedCxxPart.__convertToBool() {
|
if Bool(fromCxx: cachedCxxPart) {
|
||||||
return cachedCxxPart
|
return cachedCxxPart
|
||||||
} else {
|
} else {
|
||||||
let newCxxPart = bridge.create_std__shared_ptr_HybridPluginManagerSpec_(self.toUnsafe())
|
let newCxxPart = bridge.create_std__shared_ptr_HybridPluginManagerSpec_(self.toUnsafe())
|
||||||
@@ -105,6 +105,14 @@ open class HybridPluginManagerSpec_cxx {
|
|||||||
self.__implementation.dispose()
|
self.__implementation.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call toString() on the Swift class.
|
||||||
|
*/
|
||||||
|
@inline(__always)
|
||||||
|
public func toString() -> String {
|
||||||
|
return self.__implementation.toString()
|
||||||
|
}
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
public final var isEnabled: Bool {
|
public final var isEnabled: Bool {
|
||||||
@inline(__always)
|
@inline(__always)
|
||||||
|
|||||||
+9
-1
@@ -170,9 +170,17 @@ object VideoManager : LifecycleEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun unregisterPlayer(player: HybridVideoPlayer) {
|
fun unregisterPlayer(player: HybridVideoPlayer) {
|
||||||
players.remove(player)
|
|
||||||
audioFocusManager.unregisterPlayer(player)
|
audioFocusManager.unregisterPlayer(player)
|
||||||
PluginsRegistry.shared.notifyPlayerDestroyed(WeakReference(player))
|
PluginsRegistry.shared.notifyPlayerDestroyed(WeakReference(player))
|
||||||
|
|
||||||
|
// Remove player from any views that were using it
|
||||||
|
players[player]?.forEach { nitroId ->
|
||||||
|
views[nitroId]?.get()?.let { view ->
|
||||||
|
view.hybridPlayer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
players.remove(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? {
|
fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? {
|
||||||
|
|||||||
+10
-3
@@ -43,7 +43,7 @@ import kotlin.math.max
|
|||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@DoNotStrip
|
@DoNotStrip
|
||||||
class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
class HybridVideoPlayer() : HybridVideoPlayerSpec(), AutoCloseable {
|
||||||
override lateinit var source: HybridVideoPlayerSourceSpec
|
override lateinit var source: HybridVideoPlayerSourceSpec
|
||||||
override var eventEmitter = HybridVideoPlayerEventEmitter()
|
override var eventEmitter = HybridVideoPlayerEventEmitter()
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -348,7 +348,7 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun release() {
|
override fun release() {
|
||||||
if (playInBackground || showNotificationControls) {
|
if (playInBackground || showNotificationControls) {
|
||||||
VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)
|
VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)
|
||||||
}
|
}
|
||||||
@@ -358,6 +358,8 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
|||||||
stopProgressUpdates()
|
stopProgressUpdates()
|
||||||
loadedWithSource = false
|
loadedWithSource = false
|
||||||
|
|
||||||
|
eventEmitter.clearAllListeners()
|
||||||
|
|
||||||
player.removeListener(playerListener)
|
player.removeListener(playerListener)
|
||||||
player.removeAnalyticsListener(analyticsListener)
|
player.removeAnalyticsListener(analyticsListener)
|
||||||
player.release() // Release player
|
player.release() // Release player
|
||||||
@@ -384,8 +386,13 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
|||||||
release()
|
release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
|
||||||
override val memorySize: Long
|
override val memorySize: Long
|
||||||
get() = allocator?.totalBytesAllocated?.toLong() ?: 0L
|
// 1 MiB by default
|
||||||
|
get() = allocator?.totalBytesAllocated?.toLong() ?: (1024L * 1024L)
|
||||||
|
|
||||||
private fun startProgressUpdates() {
|
private fun startProgressUpdates() {
|
||||||
stopProgressUpdates() // Ensure no multiple runnables
|
stopProgressUpdates() // Ensure no multiple runnables
|
||||||
|
|||||||
+22
-8
@@ -7,31 +7,43 @@ import java.util.UUID
|
|||||||
data class ListenerPair(val id: UUID, val eventName: String, val callback: Any)
|
data class ListenerPair(val id: UUID, val eventName: String, val callback: Any)
|
||||||
|
|
||||||
class HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec() {
|
class HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec() {
|
||||||
|
private val lock = Any()
|
||||||
|
|
||||||
var listeners: MutableList<ListenerPair> = mutableListOf()
|
var listeners: MutableList<ListenerPair> = mutableListOf()
|
||||||
|
|
||||||
// MARK: - Private helpers
|
// MARK: - Private helpers
|
||||||
private fun <T : Any> addListener(eventName: String, listener: T): ListenerSubscription {
|
private fun <T : Any> addListener(eventName: String, listener: T): ListenerSubscription {
|
||||||
val id = UUID.randomUUID()
|
val id = UUID.randomUUID()
|
||||||
listeners.add(ListenerPair(id, eventName, listener))
|
synchronized(lock) {
|
||||||
return ListenerSubscription { listeners.removeAll { it.id == id } }
|
listeners.add(ListenerPair(id, eventName, listener))
|
||||||
|
}
|
||||||
|
return ListenerSubscription {
|
||||||
|
synchronized(lock) {
|
||||||
|
listeners.removeAll { it.id == id }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T> emitEvent(eventName: String, invokeCallback: (T) -> Unit) {
|
private inline fun <reified T> emitEvent(eventName: String, invokeCallback: (T) -> Unit) {
|
||||||
listeners.filter { it.eventName == eventName }.forEach { pair ->
|
val snapshot: List<ListenerPair> = synchronized(lock) {
|
||||||
|
listeners.filter { it.eventName == eventName }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.forEach { pair ->
|
||||||
try {
|
try {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val callback = pair.callback as? T
|
val callback = pair.callback as? T ?: run {
|
||||||
if (callback == null) {
|
|
||||||
Log.d(TAG, "Invalid callback type for $eventName")
|
Log.d(TAG, "Invalid callback type for $eventName")
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
invokeCallback(callback)
|
invokeCallback(callback)
|
||||||
} catch (error: Error) {
|
} catch (t: Throwable) {
|
||||||
Log.d(TAG, "Error calling $eventName listener $error")
|
Log.d(TAG, "Error calling $eventName listener", t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Listener registration methods
|
// MARK: - Listener registration methods
|
||||||
|
|
||||||
override fun addOnAudioBecomingNoisyListener(listener: () -> Unit) =
|
override fun addOnAudioBecomingNoisyListener(listener: () -> Unit) =
|
||||||
@@ -92,7 +104,9 @@ class HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec() {
|
|||||||
addListener("onVolumeChange", listener)
|
addListener("onVolumeChange", listener)
|
||||||
|
|
||||||
override fun clearAllListeners() {
|
override fun clearAllListeners() {
|
||||||
listeners.clear()
|
synchronized(lock) {
|
||||||
|
listeners.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Event emission methods
|
// MARK: - Event emission methods
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ extension HybridVideoPlayer: VideoPlayerObserverDelegate {
|
|||||||
|
|
||||||
func onPlaybackLikelyToKeepUp() {
|
func onPlaybackLikelyToKeepUp() {
|
||||||
isCurrentlyBuffering = false
|
isCurrentlyBuffering = false
|
||||||
if player.timeControlStatus == .playing {
|
if player.timeControlStatus != .waitingToPlayAtSpecifiedRate {
|
||||||
status = .readytoplay
|
status = .readytoplay
|
||||||
}
|
}
|
||||||
updateAndEmitPlaybackState()
|
updateAndEmitPlaybackState()
|
||||||
|
|||||||
@@ -206,6 +206,9 @@ class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {
|
|||||||
func release() {
|
func release() {
|
||||||
sourceLoader.cancelSync()
|
sourceLoader.cancelSync()
|
||||||
NowPlayingInfoCenterManager.shared.removePlayer(player: player)
|
NowPlayingInfoCenterManager.shared.removePlayer(player: player)
|
||||||
|
|
||||||
|
try? _eventEmitter?.clearAllListeners()
|
||||||
|
|
||||||
self.player.replaceCurrentItem(with: nil)
|
self.player.replaceCurrentItem(with: nil)
|
||||||
self.playerItem = nil
|
self.playerItem = nil
|
||||||
|
|
||||||
|
|||||||
+4
@@ -228,6 +228,10 @@ namespace margelo::nitro::video {
|
|||||||
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JVariant_NullType_TextTrack> /* textTrack */)>("selectTextTrack");
|
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JVariant_NullType_TextTrack> /* textTrack */)>("selectTextTrack");
|
||||||
method(_javaPart, textTrack.has_value() ? JVariant_NullType_TextTrack::fromCpp(textTrack.value()) : nullptr);
|
method(_javaPart, textTrack.has_value() ? JVariant_NullType_TextTrack::fromCpp(textTrack.value()) : nullptr);
|
||||||
}
|
}
|
||||||
|
void JHybridVideoPlayerSpec::release() {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<void()>("release");
|
||||||
|
method(_javaPart);
|
||||||
|
}
|
||||||
std::shared_ptr<Promise<void>> JHybridVideoPlayerSpec::initialize() {
|
std::shared_ptr<Promise<void>> JHybridVideoPlayerSpec::initialize() {
|
||||||
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("initialize");
|
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("initialize");
|
||||||
auto __result = method(_javaPart);
|
auto __result = method(_javaPart);
|
||||||
|
|||||||
+1
@@ -82,6 +82,7 @@ namespace margelo::nitro::video {
|
|||||||
std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) override;
|
std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) override;
|
||||||
std::vector<TextTrack> getAvailableTextTracks() override;
|
std::vector<TextTrack> getAvailableTextTracks() override;
|
||||||
void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) override;
|
void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) override;
|
||||||
|
void release() override;
|
||||||
std::shared_ptr<Promise<void>> initialize() override;
|
std::shared_ptr<Promise<void>> initialize() override;
|
||||||
std::shared_ptr<Promise<void>> preload() override;
|
std::shared_ptr<Promise<void>> preload() override;
|
||||||
void play() override;
|
void play() override;
|
||||||
|
|||||||
+4
@@ -141,6 +141,10 @@ abstract class HybridVideoPlayerSpec: HybridObject() {
|
|||||||
@Keep
|
@Keep
|
||||||
abstract fun selectTextTrack(textTrack: Variant_NullType_TextTrack?): Unit
|
abstract fun selectTextTrack(textTrack: Variant_NullType_TextTrack?): Unit
|
||||||
|
|
||||||
|
@DoNotStrip
|
||||||
|
@Keep
|
||||||
|
abstract fun release(): Unit
|
||||||
|
|
||||||
@DoNotStrip
|
@DoNotStrip
|
||||||
@Keep
|
@Keep
|
||||||
abstract fun initialize(): Promise<Unit>
|
abstract fun initialize(): Promise<Unit>
|
||||||
|
|||||||
+6
@@ -188,6 +188,12 @@ namespace margelo::nitro::video {
|
|||||||
std::rethrow_exception(__result.error());
|
std::rethrow_exception(__result.error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline void release() override {
|
||||||
|
auto __result = _swiftPart.release();
|
||||||
|
if (__result.hasError()) [[unlikely]] {
|
||||||
|
std::rethrow_exception(__result.error());
|
||||||
|
}
|
||||||
|
}
|
||||||
inline std::shared_ptr<Promise<void>> initialize() override {
|
inline std::shared_ptr<Promise<void>> initialize() override {
|
||||||
auto __result = _swiftPart.initialize();
|
auto __result = _swiftPart.initialize();
|
||||||
if (__result.hasError()) [[unlikely]] {
|
if (__result.hasError()) [[unlikely]] {
|
||||||
|
|||||||
+1
@@ -32,6 +32,7 @@ public protocol HybridVideoPlayerSpec_protocol: HybridObject {
|
|||||||
func replaceSourceAsync(source: Variant_NullType__any_HybridVideoPlayerSourceSpec_?) throws -> Promise<Void>
|
func replaceSourceAsync(source: Variant_NullType__any_HybridVideoPlayerSourceSpec_?) throws -> Promise<Void>
|
||||||
func getAvailableTextTracks() throws -> [TextTrack]
|
func getAvailableTextTracks() throws -> [TextTrack]
|
||||||
func selectTextTrack(textTrack: Variant_NullType_TextTrack?) throws -> Void
|
func selectTextTrack(textTrack: Variant_NullType_TextTrack?) throws -> Void
|
||||||
|
func release() throws -> Void
|
||||||
func initialize() throws -> Promise<Void>
|
func initialize() throws -> Promise<Void>
|
||||||
func preload() throws -> Promise<Void>
|
func preload() throws -> Promise<Void>
|
||||||
func play() throws -> Void
|
func play() throws -> Void
|
||||||
|
|||||||
+11
@@ -369,6 +369,17 @@ open class HybridVideoPlayerSpec_cxx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@inline(__always)
|
||||||
|
public final func release() -> bridge.Result_void_ {
|
||||||
|
do {
|
||||||
|
try self.__implementation.release()
|
||||||
|
return bridge.create_Result_void_()
|
||||||
|
} catch (let __error) {
|
||||||
|
let __exceptionPtr = __error.toCpp()
|
||||||
|
return bridge.create_Result_void_(__exceptionPtr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@inline(__always)
|
@inline(__always)
|
||||||
public final func initialize() -> bridge.Result_std__shared_ptr_Promise_void___ {
|
public final func initialize() -> bridge.Result_std__shared_ptr_Promise_void___ {
|
||||||
do {
|
do {
|
||||||
|
|||||||
+1
@@ -43,6 +43,7 @@ namespace margelo::nitro::video {
|
|||||||
prototype.registerHybridMethod("replaceSourceAsync", &HybridVideoPlayerSpec::replaceSourceAsync);
|
prototype.registerHybridMethod("replaceSourceAsync", &HybridVideoPlayerSpec::replaceSourceAsync);
|
||||||
prototype.registerHybridMethod("getAvailableTextTracks", &HybridVideoPlayerSpec::getAvailableTextTracks);
|
prototype.registerHybridMethod("getAvailableTextTracks", &HybridVideoPlayerSpec::getAvailableTextTracks);
|
||||||
prototype.registerHybridMethod("selectTextTrack", &HybridVideoPlayerSpec::selectTextTrack);
|
prototype.registerHybridMethod("selectTextTrack", &HybridVideoPlayerSpec::selectTextTrack);
|
||||||
|
prototype.registerHybridMethod("release", &HybridVideoPlayerSpec::release);
|
||||||
prototype.registerHybridMethod("initialize", &HybridVideoPlayerSpec::initialize);
|
prototype.registerHybridMethod("initialize", &HybridVideoPlayerSpec::initialize);
|
||||||
prototype.registerHybridMethod("preload", &HybridVideoPlayerSpec::preload);
|
prototype.registerHybridMethod("preload", &HybridVideoPlayerSpec::preload);
|
||||||
prototype.registerHybridMethod("play", &HybridVideoPlayerSpec::play);
|
prototype.registerHybridMethod("play", &HybridVideoPlayerSpec::play);
|
||||||
|
|||||||
+1
@@ -98,6 +98,7 @@ namespace margelo::nitro::video {
|
|||||||
virtual std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) = 0;
|
virtual std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) = 0;
|
||||||
virtual std::vector<TextTrack> getAvailableTextTracks() = 0;
|
virtual std::vector<TextTrack> getAvailableTextTracks() = 0;
|
||||||
virtual void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) = 0;
|
virtual void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) = 0;
|
||||||
|
virtual void release() = 0;
|
||||||
virtual std::shared_ptr<Promise<void>> initialize() = 0;
|
virtual std::shared_ptr<Promise<void>> initialize() = 0;
|
||||||
virtual std::shared_ptr<Promise<void>> preload() = 0;
|
virtual std::shared_ptr<Promise<void>> preload() = 0;
|
||||||
virtual void play() = 0;
|
virtual void play() = 0;
|
||||||
|
|||||||
@@ -18,7 +18,19 @@ import { createSource } from './utils/sourceFactory';
|
|||||||
import { VideoPlayerEvents } from './VideoPlayerEvents';
|
import { VideoPlayerEvents } from './VideoPlayerEvents';
|
||||||
|
|
||||||
class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||||
protected player: VideoPlayerImpl;
|
private _player: VideoPlayerImpl | undefined;
|
||||||
|
private _releaseTimeout: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
|
protected get player(): VideoPlayerImpl {
|
||||||
|
if (this._player === undefined) {
|
||||||
|
throw new VideoRuntimeError(
|
||||||
|
'player/released',
|
||||||
|
"You can't access player after it's released"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._player;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {
|
constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {
|
||||||
const hybridSource = createSource(source);
|
const hybridSource = createSource(source);
|
||||||
@@ -26,17 +38,39 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
|||||||
|
|
||||||
// Initialize events
|
// Initialize events
|
||||||
super(player.eventEmitter);
|
super(player.eventEmitter);
|
||||||
this.player = player;
|
this._player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up player's native resources and releases native state.
|
* Releases the player's native resources and releases native state.
|
||||||
* After calling this method, the player is no longer usable.
|
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
__destroy() {
|
__destroy() {
|
||||||
|
if (this._player === undefined) return;
|
||||||
|
|
||||||
this.clearAllEvents();
|
this.clearAllEvents();
|
||||||
this.player.dispose();
|
|
||||||
|
try {
|
||||||
|
this.player.release();
|
||||||
|
} catch (error) {
|
||||||
|
// Best effort cleanup: teardown must never crash app unmount.
|
||||||
|
console.error('Failed to cleanup native player resources', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We leave hybrid object to be cleaned up by garbage collector
|
||||||
|
// So we update memory size to ensure that memory is released
|
||||||
|
// when needed
|
||||||
|
this.updateMemorySize();
|
||||||
|
|
||||||
|
// We wait for 5s to let late events that were triggered before release to be processed
|
||||||
|
if (this._releaseTimeout !== undefined) {
|
||||||
|
clearTimeout(this._releaseTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._releaseTimeout = setTimeout(() => {
|
||||||
|
this._player = undefined;
|
||||||
|
this._releaseTimeout = undefined;
|
||||||
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ export interface VideoPlayer
|
|||||||
*/
|
*/
|
||||||
showNotificationControls: boolean;
|
showNotificationControls: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the current source of the player.
|
||||||
|
* @param source - The new source of the video.
|
||||||
|
* @note If you want to clear the source, you can pass null. It has the same effect as {@link release}.
|
||||||
|
* see {@link VideoPlayerSourceBase}
|
||||||
|
*/
|
||||||
replaceSourceAsync(source: VideoPlayerSource | null): Promise<void>;
|
replaceSourceAsync(source: VideoPlayerSource | null): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,6 +42,11 @@ export interface VideoPlayer
|
|||||||
* @param textTrack - Text track to select, or null to unselect current track
|
* @param textTrack - Text track to select, or null to unselect current track
|
||||||
*/
|
*/
|
||||||
selectTextTrack(textTrack: TextTrack | null): void;
|
selectTextTrack(textTrack: TextTrack | null): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the player's native resources and releases native state.
|
||||||
|
*/
|
||||||
|
release(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoPlayerFactory
|
export interface VideoPlayerFactory
|
||||||
|
|||||||
Reference in New Issue
Block a user