commit a545dd2dd589bcb5f2a602315e2c47dac786b7b8 Author: Zoe Roux Date: Sun Oct 12 17:21:22 2025 +0200 . diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..56aa5e85 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + root: true, + extends: ["../../config/.eslintrc.js"], + parserOptions: { + tsconfigRootDir: __dirname, + project: true, + }, +}; diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/ReactNativeVideo.podspec b/ReactNativeVideo.podspec new file mode 100644 index 00000000..26122a61 --- /dev/null +++ b/ReactNativeVideo.podspec @@ -0,0 +1,59 @@ +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + +fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1' + +Pod::Spec.new do |s| + s.name = "ReactNativeVideo" + s.version = package["version"] + s.summary = package["description"] + s.homepage = package["homepage"] + s.license = package["license"] + s.authors = package["author"] + + s.platforms = { :ios => min_ios_version_supported } + s.source = { :git => "https://github.com/KrzysztofMoch/react-native-video.git", :tag => "#{s.version}" } + + s.source_files = [ + "ios/*.{h,m,mm,swift}", + "ios/Core/**/*.{h,m,mm,swift}", # Core library files + "ios/Hybrids/**/*.{h,m,mm,swift}", # Nitro Hybrid files + "ios/View/**/*.{h,m,mm,swift}" # Video View files + ] + + if fabric_enabled + s.exclude_files = ["ios/view/paper/**/*.{h,m,mm,swift}"] + else + s.exclude_files = ["ios/view/fabric/**/*.{h,m,mm,swift}"] + end + + # Cxx to Swift bridging helpers + s.public_header_files = ["ios/Video-Bridging-Header.h"] + + s.pod_target_xcconfig = { + "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES FOLLY_MOBILE" + } + + # Try to manually add the dependencies + # because they are not automatically added by expo + # when USE_FRAMEWORKS is true + if ENV["USE_FRAMEWORKS"] + s.dependency "React-Core" + + puts "[ReactNativeVideo] Detected USE_FRAMEWORKS, adding required dependencies..." + + add_dependency(s, "React-jsinspector", :framework_name => "jsinspector_modern") + add_dependency(s, "React-rendererconsistency", :framework_name => "React_rendererconsistency") + + # @KrzysztofMoch Note: We need to add this as well for newer versions of React Native, but it's not available in older versions + # add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing') + end + + # Add all files generated by Nitrogen + load 'nitrogen/generated/ios/ReactNativeVideo+autolinking.rb' + add_nitrogen_files(s) + + install_modules_dependencies(s) +end diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt new file mode 100644 index 00000000..19a835a9 --- /dev/null +++ b/android/CMakeLists.txt @@ -0,0 +1,29 @@ + +project(ReactNativeVideo) +cmake_minimum_required(VERSION 3.9.0) + +set (PACKAGE_NAME ReactNativeVideo) +set (CMAKE_VERBOSE_MAKEFILE ON) +set (CMAKE_CXX_STANDARD 20) + +# Define C++ library and add all sources +add_library(${PACKAGE_NAME} SHARED + src/main/cpp/cpp-adapter.cpp +) + +# Add Nitrogen specs :) +include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideo+autolinking.cmake) + +# Set up local includes +include_directories( + "src/main/cpp" +) + +find_library(LOG_LIB log) + +# Link all libraries together +target_link_libraries( + ${PACKAGE_NAME} + ${LOG_LIB} + android # <-- Android core +) \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 00000000..ab032a12 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,250 @@ +buildscript { + // Buildscript is evaluated before everything else so we can't use getExtOrDefault + def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["RNVideo_kotlinVersion"] + def minKotlin_version = project.properties["RNVideo_minKotlinVersion"] + + def androidx_version = rootProject.ext.has('androidxActivityVersion') ? rootProject.ext.get('androidxActivityVersion') : project.properties['RNVideo_androidxActivityVersion'] + def minAndroidx_version = project.properties["RNVideo_androidxActivityVersion"] + + def isVersionAtLeast = { version, minVersion -> + def (major, minor, patch) = version.tokenize('.') + def (minMajor, minMinor, minPatch) = minVersion.tokenize('.') + + // major version is greater + if (major.toInteger() > minMajor.toInteger()) return true + + // major version is equal, minor version is greater + if (major.toInteger() == minMajor.toInteger() && minor.toInteger() > minMinor.toInteger()) return true + + // major version is equal, minor version is equal, patch version is greater + if (major.toInteger() == minMajor.toInteger() && minor.toInteger() == minMinor.toInteger() && patch.toInteger() >= minPatch.toInteger()) return true + + return false + } + + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "com.android.tools.build:gradle:7.2.1" + // noinspection DifferentKotlinGradleVersion + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } + + ext { + if (!isVersionAtLeast(kotlin_version, minKotlin_version)) { + throw new GradleException("Kotlin version must be at least $minKotlin_version (current: $kotlin_version)") + } + + if (!isVersionAtLeast(androidx_version, minAndroidx_version)) { + throw new GradleException("AndroidX version must be at least $minAndroidx_version (current: $androidx_version)") + } + } +} + +def reactNativeArchitectures() { + def value = rootProject.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} + +def isNewArchitectureEnabled() { + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" +} + +apply plugin: "com.android.library" +apply plugin: "kotlin-android" +apply from: '../nitrogen/generated/android/ReactNativeVideo+autolinking.gradle' +apply from: './fix-prefab.gradle' + +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} + +def getExtOrDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["RNVideo_" + name] +} + +def getExtOrIntegerDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["RNVideo_" + name]).toInteger() +} + +def supportsNamespace() { + def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') + def major = parsed[0].toInteger() + def minor = parsed[1].toInteger() + + // Namespace support was added in 7.3.0 + return (major == 7 && minor >= 3) || major >= 8 +} + +def ExoplayerDependenciesList = [ + "useExoplayerDash", + "useExoplayerHls", +] + +def ExoplayerDependencies = ExoplayerDependenciesList.collectEntries { property -> + [(property): getExtOrDefault(property)?.toBoolean() ?: false] +} + +// Print Configuration +println "[ReactNativeVideo] Exoplayer Dependencies Configuration:" +ExoplayerDependenciesList.each { propertyName -> + def propertyValue = ExoplayerDependencies[propertyName] + println "$propertyName: $propertyValue" +} + +android { + if (supportsNamespace()) { + namespace "com.twg.video" + + sourceSets { + main { + manifest.srcFile "src/main/AndroidManifestNew.xml" + } + } + } + + ndkVersion getExtOrDefault("ndkVersion") + compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") + + defaultConfig { + minSdkVersion getExtOrIntegerDefault("minSdkVersion") + targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") + + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + buildConfigField "boolean", "USE_EXOPLAYER_DASH", ExoplayerDependencies.useExoplayerDash.toString() + buildConfigField "boolean", "USE_EXOPLAYER_HLS", ExoplayerDependencies.useExoplayerHls.toString() + + externalNativeBuild { + cmake { + cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" + arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + abiFilters (*reactNativeArchitectures()) + } + } + } + + externalNativeBuild { + cmake { + path "CMakeLists.txt" + } + } + + packagingOptions { + excludes = [ + "META-INF", + "META-INF/**", + "**/libc++_shared.so", + "**/libfbjni.so", + "**/libjsi.so", + "**/libfolly_json.so", + "**/libfolly_runtime.so", + "**/libglog.so", + "**/libhermes.so", + "**/libhermes-executor-debug.so", + "**/libhermes_executor.so", + "**/libreactnativejni.so", + "**/libturbomodulejsijni.so", + "**/libreact_nativemodule_core.so", + "**/libjscexecutor.so", + "**/libreactnative.so" + ] + } + + buildFeatures { + buildConfig true + prefab true + } + + buildTypes { + release { + minifyEnabled false + } + } + + lintOptions { + disable "GradleCompatible" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + sourceSets { + main { + if (!isNewArchitectureEnabled()) { + java.srcDirs += ["src/paper/java"] + } + + if (!ExoplayerDependencies.useExoplayerDash) { + java.srcDirs += ["src/stubs/dash"] + } + + if (!ExoplayerDependencies.useExoplayerHls) { + java.srcDirs += ["src/stubs/hls"] + } + } + } +} + +repositories { + mavenCentral() + google() +} + +def kotlin_version = getExtOrDefault("kotlinVersion") +def media3_version = getExtOrDefault("media3Version") +def androidxCore_version = getExtOrDefault("androidxCoreVersion") +def androidxActivity_version = getExtOrDefault("androidxActivityVersion") + +dependencies { + // For < 0.71, this will be from the local maven repo + // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin + //noinspection GradleDynamicVersion + implementation "com.facebook.react:react-native:+" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + + // Add a dependency on NitroModules + implementation project(":react-native-nitro-modules") + + implementation "androidx.core:core-ktx:$androidxCore_version" + implementation "androidx.activity:activity-ktx:$androidxActivity_version" + + // For media playback using ExoPlayer + implementation "androidx.media3:media3-exoplayer:$media3_version" + + // Common functionality used across multiple media libraries + implementation "androidx.media3:media3-common:$media3_version" + + // For building media playback UIs + implementation "androidx.media3:media3-ui:$media3_version" + + // Common functionality for loading data + implementation "androidx.media3:media3-datasource:$media3_version" + + // For loading data using the OkHttp network stack + implementation "androidx.media3:media3-datasource-okhttp:$media3_version" + + // For Media Session + implementation "androidx.media3:media3-session:$media3_version" + + if (ExoplayerDependencies.useExoplayerDash) { + implementation "androidx.media3:media3-exoplayer-dash:$media3_version" + } + + if (ExoplayerDependencies.useExoplayerHls) { + implementation "androidx.media3:media3-exoplayer-hls:$media3_version" + } +} + +if (isNewArchitectureEnabled()) { + react { + jsRootDir = file("../src/spec/fabric") + libraryName = "RNCVideoView" + codegenJavaPackageName = "com.twg.video" + } +} + diff --git a/android/fix-prefab.gradle b/android/fix-prefab.gradle new file mode 100644 index 00000000..dfa5480f --- /dev/null +++ b/android/fix-prefab.gradle @@ -0,0 +1,51 @@ +tasks.configureEach { task -> + // Make sure that we generate our prefab publication file only after having built the native library + // so that not a header publication file, but a full configuration publication will be generated, which + // will include the .so file + + def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/ + def matcher = task.name =~ prefabConfigurePattern + if (matcher.matches()) { + def variantName = matcher[0][1] + task.outputs.upToDateWhen { false } + task.dependsOn("externalNativeBuild${variantName}") + } +} + +afterEvaluate { + def abis = reactNativeArchitectures() + rootProject.allprojects.each { proj -> + if (proj === rootProject) return + + def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config -> + config.dependencies.any { dep -> + dep.group == project.group && dep.name == project.name + } + } + if (!dependsOnThisLib && proj != project) return + + if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) { + return + } + + def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants + // Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to + // generate a libnameConfig.cmake file that will contain our native library (.so). + // See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue + variants.all { variant -> + def variantName = variant.name + abis.each { abi -> + def searchDir = new File(proj.projectDir, ".cxx/${variantName}") + if (!searchDir.exists()) return + def matches = [] + searchDir.eachDir { randomDir -> + def prefabFile = new File(randomDir, "${abi}/prefab_config.json") + if (prefabFile.exists()) matches << prefabFile + } + matches.each { prefabConfig -> + prefabConfig.setLastModified(System.currentTimeMillis()) + } + } + } + } +} \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..ee17bacd --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,13 @@ +RNVideo_kotlinVersion=1.9.24 +RNVideo_minKotlinVersion=1.8.0 +RNVideo_minSdkVersion=24 +RNVideo_targetSdkVersion=35 +RNVideo_compileSdkVersion=35 +RNVideo_ndkversion=27.1.12297006 + +RNVideo_useExoplayerDash=true +RNVideo_useExoplayerHls=true + +RNVideo_media3Version=1.4.1 +RNVideo_androidxCoreVersion=1.13.1 +RNVideo_androidxActivityVersion=1.9.3 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..f79cac1a --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + diff --git a/android/src/main/AndroidManifestNew.xml b/android/src/main/AndroidManifestNew.xml new file mode 100644 index 00000000..f79cac1a --- /dev/null +++ b/android/src/main/AndroidManifestNew.xml @@ -0,0 +1,3 @@ + + + diff --git a/android/src/main/cpp/cpp-adapter.cpp b/android/src/main/cpp/cpp-adapter.cpp new file mode 100644 index 00000000..6a2102df --- /dev/null +++ b/android/src/main/cpp/cpp-adapter.cpp @@ -0,0 +1,6 @@ +#include +#include "ReactNativeVideoOnLoad.hpp" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { + return margelo::nitro::video::initialize(vm); +} \ No newline at end of file diff --git a/android/src/main/java/com/twg/video/core/AudioFocusManager.kt b/android/src/main/java/com/twg/video/core/AudioFocusManager.kt new file mode 100644 index 00000000..6126080f --- /dev/null +++ b/android/src/main/java/com/twg/video/core/AudioFocusManager.kt @@ -0,0 +1,233 @@ +package com.twg.video.core + +import android.content.Context +import android.media.AudioAttributes +import android.media.AudioManager +import android.media.AudioFocusRequest +import android.os.Build +import androidx.annotation.OptIn +import androidx.annotation.RequiresApi +import androidx.media3.common.util.UnstableApi +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import com.margelo.nitro.video.MixAudioMode +import kotlin.getValue +import com.twg.video.core.utils.Threading + +@OptIn(UnstableApi::class) +class AudioFocusManager() { + private val players = mutableListOf() + private var currentMixAudioMode: MixAudioMode? = null + private var audioFocusRequest: AudioFocusRequest? = null + + val appContext by lazy { + NitroModules.applicationContext ?: throw UnknownError() + } + + private val audioManager by lazy { + appContext.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: throw UnknownError() + } + + private val audioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> + when (focusChange) { + AudioManager.AUDIOFOCUS_GAIN -> { + unDuckActivePlayers() + } + AudioManager.AUDIOFOCUS_LOSS -> { + pauseActivePlayers() + currentMixAudioMode = null + audioFocusRequest = null + } + AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { + val mixAudioMode = determineRequiredMixMode() + if (mixAudioMode != MixAudioMode.MIXWITHOTHERS) { + pauseActivePlayers() + currentMixAudioMode = null + audioFocusRequest = null + } + } + AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { + val mixAudioMode = determineRequiredMixMode() + when (mixAudioMode) { + MixAudioMode.DONOTMIX -> pauseActivePlayers() + else -> duckActivePlayers() + } + } + } + } + + fun registerPlayer(player: HybridVideoPlayer) { + if (!players.contains(player)) { + players.add(player) + } + } + + fun unregisterPlayer(player: HybridVideoPlayer) { + players.remove(player) + if (players.isEmpty()) { + abandonAudioFocus() + } else { + requestAudioFocusUpdate() + } + } + + fun requestAudioFocusUpdate() { + Threading.runOnMainThread { + val requiredMixMode = determineRequiredMixMode() + + if (requiredMixMode == null) { + abandonAudioFocus() + return@runOnMainThread + } + + if (currentMixAudioMode != requiredMixMode) { + requestAudioFocus(requiredMixMode) + } + } + } + + private fun determineRequiredMixMode(): MixAudioMode? { + val activePlayers = players.filter { player -> + player.player?.isPlaying == true && player.player?.volume != 0f + } + + if (activePlayers.isEmpty()) { + return null + } + + val anyPlayerNeedsMixWithOthers = activePlayers.any { player -> + player.mixAudioMode == MixAudioMode.MIXWITHOTHERS + } + + if (anyPlayerNeedsMixWithOthers) { + abandonAudioFocus() + return MixAudioMode.MIXWITHOTHERS + } + + val anyPlayerNeedsExclusiveFocus = activePlayers.any { player -> + player.mixAudioMode == MixAudioMode.DONOTMIX + } + + val anyPlayerNeedsDucking = activePlayers.any { player -> + player.mixAudioMode == MixAudioMode.DUCKOTHERS + } + + return when { + anyPlayerNeedsExclusiveFocus -> MixAudioMode.DONOTMIX + anyPlayerNeedsDucking -> MixAudioMode.DUCKOTHERS + else -> MixAudioMode.AUTO + } + } + + private fun requestAudioFocus(mixMode: MixAudioMode) { + val focusType = when (mixMode) { + MixAudioMode.DONOTMIX -> AudioManager.AUDIOFOCUS_GAIN + MixAudioMode.DUCKOTHERS -> AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK + MixAudioMode.AUTO -> AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK + MixAudioMode.MIXWITHOTHERS -> return // No focus needed for mix with others + } + + val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + requestAudioFocusNew(focusType) + } else { + requestAudioFocusLegacy(focusType) + } + + if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + currentMixAudioMode = mixMode + } else { + currentMixAudioMode = null + // Pause players since audio focus couldn't be obtained + pauseActivePlayers() + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun requestAudioFocusNew(focusType: Int): Int { + + audioFocusRequest = AudioFocusRequest.Builder(focusType) + .setAudioAttributes( + AudioAttributes.Builder().run { + setUsage(AudioAttributes.USAGE_MEDIA) + setContentType(AudioAttributes.CONTENT_TYPE_MOVIE) + build() + } + ) + .setOnAudioFocusChangeListener(audioFocusChangeListener) + .build() + + return audioManager.requestAudioFocus(audioFocusRequest!!) + } + + @Suppress("DEPRECATION") + private fun requestAudioFocusLegacy(focusType: Int): Int { + return audioManager.requestAudioFocus( + audioFocusChangeListener, + AudioManager.STREAM_MUSIC, + focusType + ) + } + + private fun abandonAudioFocus() { + if (currentMixAudioMode != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + abandonAudioFocusNew() + } else { + abandonAudioFocusLegacy() + } + currentMixAudioMode = null + audioFocusRequest = null + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun abandonAudioFocusNew() { + audioFocusRequest?.let { request -> + audioManager.abandonAudioFocusRequest(request) + } + } + + @Suppress("DEPRECATION") + private fun abandonAudioFocusLegacy() { + audioManager.abandonAudioFocus(audioFocusChangeListener) + } + + private fun pauseActivePlayers() { + Threading.runOnMainThread { + players.forEach { player -> + player.player?.let { mediaPlayer -> + if (mediaPlayer.volume != 0f && mediaPlayer.isPlaying) { + mediaPlayer.pause() + } + } + } + } + } + + private fun duckActivePlayers() { + Threading.runOnMainThread { + players.forEach { player -> + player.player?.let { mediaPlayer -> + // We need to duck the volume to 50%. After the audio focus is regained, + // we will restore the volume to the user's volume. + mediaPlayer.volume = mediaPlayer.volume * 0.5f + } + } + } + } + + private fun unDuckActivePlayers() { + Threading.runOnMainThread { + // Resume players that were paused due to audio focus loss + players.forEach { player -> + player.player?.let { mediaPlayer -> + // Restore full volume if it was ducked + if (mediaPlayer.volume != 0f && mediaPlayer.volume.toDouble() != player.userVolume) { + mediaPlayer.volume = player.userVolume.toFloat() + } + } + } + } + } +} + diff --git a/android/src/main/java/com/twg/video/core/VideoError.kt b/android/src/main/java/com/twg/video/core/VideoError.kt new file mode 100644 index 00000000..789b9d0a --- /dev/null +++ b/android/src/main/java/com/twg/video/core/VideoError.kt @@ -0,0 +1,95 @@ +package com.twg.video.core + +// Base class for all video errors +abstract class VideoError( + open val code: String, + message: String +) : Error("{%@$code::$message@%}") + +// Library related errors +sealed class LibraryError(code: String, message: String) : VideoError(code, message) { + object Deallocated : LibraryError( + "library/deallocated", + "Object has been deallocated" + ) + + object ApplicationContextNotFound : LibraryError( + "library/application-context-not-found", + "Application context not found" + ) + + class MethodNotSupported(val methodName: String) : LibraryError( + "library/method-not-supported", + "Method $methodName() is not supported on Android" + ) + + object DRMPluginNotFound : LibraryError( + "library/drm-plugin-not-found", + "No DRM plugin have been found, please add one to the project", + ) +} + +// Player related errors +sealed class PlayerError(code: String, message: String) : VideoError(code, message) { + object NotInitialized : PlayerError( + "player/not-initialized", + "Player has not been initialized (Or has been set to null)" + ) + + object AssetNotInitialized : PlayerError( + "player/asset-not-initialized", + "Asset has not been initialized (Or has been set to null)" + ) + + object InvalidSource : PlayerError( + "player/invalid-source", + "Invalid source passed to player" + ) +} + +// Source related errors +sealed class SourceError(code: String, message: String) : VideoError(code, message) { + class InvalidUri(val uri: String) : SourceError( + "source/invalid-uri", + "Invalid source file uri: $uri" + ) + + class MissingReadFilePermission(val uri: String) : SourceError( + "source/missing-read-file-permission", + "Missing read file permission for source file at $uri" + ) + + class FileDoesNotExist(val uri: String) : SourceError( + "source/file-does-not-exist", + "File does not exist at URI: $uri" + ) + + object FailedToInitializeAsset : SourceError( + "source/failed-to-initialize-asset", + "Failed to initialize asset" + ) + + class UnsupportedContentType(val uri: String) : SourceError( + "source/unsupported-content-type", + "type of content (${uri}) is not supported" + ) +} + +// View related errors +sealed class VideoViewError(code: String, message: String) : VideoError(code, message) { + class ViewNotFound(val viewId: Int) : VideoViewError( + "view/not-found", + "View with viewId $viewId not found" + ) + object ViewIsDeallocated : VideoViewError( + "view/deallocated", + "Attempt to access a view, but it has been deallocated (or not initialized)" + ) + object PictureInPictureNotSupported : VideoViewError( + "view/picture-in-picture-not-supported", + "Picture in picture is not supported on this device" + ) +} + +// Unknown error +class UnknownError : VideoError("unknown/unknown", "Unknown error") diff --git a/android/src/main/java/com/twg/video/core/VideoManager.kt b/android/src/main/java/com/twg/video/core/VideoManager.kt new file mode 100644 index 00000000..cbb9a54d --- /dev/null +++ b/android/src/main/java/com/twg/video/core/VideoManager.kt @@ -0,0 +1,284 @@ +package com.twg.video.core + +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.facebook.react.bridge.LifecycleEventListener +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import com.margelo.nitro.video.MixAudioMode +import com.twg.video.core.plugins.PluginsRegistry +import com.twg.video.view.VideoView +import java.lang.ref.WeakReference + +@OptIn(UnstableApi::class) +object VideoManager : LifecycleEventListener { + private const val TAG = "VideoManager" + + // nitroId -> weak VideoView + private val views = mutableMapOf>() + // player -> list of nitroIds of views that are using this player + private val players = mutableMapOf>() + + // Keep track of players that were paused due to PiP so that they can be resumed later + private val playersPausedForPip = mutableSetOf() + + private var currentPipVideoView: WeakReference? = null + + var audioFocusManager = AudioFocusManager() + + private var lastPlayedNitroId: Int? = null + + init { + NitroModules.applicationContext?.apply { + addLifecycleEventListener(this@VideoManager) + } + } + + fun requestPictureInPicture(videoView: VideoView): Boolean { + Log.d(TAG, "PiP requested for video nitroId: ${videoView.nitroId}") + + if (videoView.isInPictureInPicture) { + Log.d(TAG, "Video nitroId: ${videoView.nitroId} is already in PiP") + return true + } + + // Exit PiP from current video if there is one + currentPipVideoView?.get()?.let { currentPipVideo -> + if (currentPipVideo != videoView && currentPipVideo.isInPictureInPicture) { + Log.d(TAG, "Forcing exit PiP for video nitroId: ${currentPipVideo.nitroId} to make room for nitroId: ${videoView.nitroId}") + currentPipVideo.forceExitPictureInPicture() + } + } + + // Ensure the player that belongs to this view is attached back to this view + videoView.hybridPlayer?.movePlayerToVideoView(videoView) + + // Pause every other player that might be playing in the background so that only the PiP video plays + pauseOtherPlayers(videoView) + + // Set this video as the designated PiP video BEFORE entering PiP mode + // This ensures the PictureInPictureHelperFragment callbacks know which video should respond + currentPipVideoView = WeakReference(videoView) + Log.d(TAG, "Designated video nitroId: ${videoView.nitroId} as the PiP video") + + val success = videoView.internalEnterPictureInPicture() + Log.d(TAG, "PiP enter result for video nitroId: ${videoView.nitroId} = $success") + + if (!success) { + // If we failed to enter PiP, resume any players we just paused + resumePlayersPausedForPip() + currentPipVideoView = null + Log.w(TAG, "Failed to enter PiP, clearing designated PiP video") + } + + return success + } + + fun notifyPictureInPictureExited(videoView: VideoView) { + Log.d(TAG, "PiP exit notification for video nitroId: ${videoView.nitroId}") + currentPipVideoView?.get()?.let { currentPipVideo -> + if (currentPipVideo == videoView) { + Log.d(TAG, "Clearing PiP reference for video nitroId: ${videoView.nitroId}") + currentPipVideoView = null + // Resume any players that were paused when PiP was entered + resumePlayersPausedForPip() + } + } + } + + fun getCurrentPictureInPictureVideo(): VideoView? { + return currentPipVideoView?.get() + } + + fun setCurrentPictureInPictureVideo(videoView: VideoView) { + Log.d(TAG, "Setting current PiP video to nitroId: ${videoView.nitroId}") + currentPipVideoView = WeakReference(videoView) + } + + fun isAnyVideoInPictureInPicture(): Boolean { + return currentPipVideoView?.get()?.isInPictureInPicture == true + } + + fun forceExitAllPictureInPicture() { + currentPipVideoView?.get()?.let { currentPipVideo -> + if (currentPipVideo.isInPictureInPicture) { + currentPipVideo.forceExitPictureInPicture() + } + } + currentPipVideoView = null + } + + fun maybePassPlayerToView(player: HybridVideoPlayer) { + val views = players[player]?.mapNotNull { getVideoViewWeakReferenceByNitroId(it)?.get() } ?: return + val latestView = views.lastOrNull() ?: return + + player.movePlayerToVideoView(latestView) + } + + fun registerView(view: VideoView) { + views[view.nitroId] = WeakReference(view) + PluginsRegistry.shared.notifyVideoViewCreated(WeakReference(view)) + } + + fun unregisterView(view: VideoView) { + view.hybridPlayer?.let { + removeViewFromPlayer(view, it) + } + + // Clean up PiP reference if this view was in PiP + currentPipVideoView?.get()?.let { currentPipVideo -> + if (currentPipVideo == view) { + currentPipVideoView = null + } + } + + views.remove(view.nitroId) + PluginsRegistry.shared.notifyVideoViewDestroyed(WeakReference(view)) + } + + fun addViewToPlayer(view: VideoView, player: HybridVideoPlayer) { + // Add player to list if it doesn't exist (should not happen) + if(!players.containsKey(player)) players[player] = mutableListOf() + + // Check if view is already added to player + if(players[player]?.contains(view.nitroId) == true) return + + // Add view to player + players[player]?.add(view.nitroId) + } + + fun removeViewFromPlayer(view: VideoView, player: HybridVideoPlayer) { + players[player]?.remove(view.nitroId) + + // If this was the last view using this player, clean up + if (players[player]?.isEmpty() == true) { + players.remove(player) + } else { + // If there are other views using this player, move to the latest one + maybePassPlayerToView(player) + } + } + + fun registerPlayer(player: HybridVideoPlayer) { + if (!players.containsKey(player)) { + players[player] = mutableListOf() + } + + audioFocusManager.registerPlayer(player) + PluginsRegistry.shared.notifyPlayerCreated(WeakReference(player)) + } + + fun unregisterPlayer(player: HybridVideoPlayer) { + players.remove(player) + audioFocusManager.unregisterPlayer(player) + PluginsRegistry.shared.notifyPlayerDestroyed(WeakReference(player)) + } + + fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? { + return players.keys.find { player -> + players[player]?.contains(nitroId) == true + } + } + + fun updateVideoViewNitroId(oldNitroId: Int, newNitroId: Int, view: VideoView) { + // Remove old mapping + if (oldNitroId != -1) { + views.remove(oldNitroId) + + // Update player mappings + players.keys.forEach { player -> + players[player]?.let { nitroIds -> + if (nitroIds.remove(oldNitroId)) { + nitroIds.add(newNitroId) + } + } + } + } + + // Add new mapping + views[newNitroId] = WeakReference(view) + } + + fun getVideoViewWeakReferenceByNitroId(nitroId: Int): WeakReference? { + return views[nitroId] + } + + // ------------ Lifecycle Handler ------------ + private fun onAppEnterForeground() { + players.keys.forEach { player -> + if (player.wasAutoPaused) { + player.play() + } + } + } + + private fun onAppEnterBackground() { + players.keys.forEach { player -> + if (!player.playInBackground && player.isPlaying) { + player.wasAutoPaused = player.isPlaying + player.pause() + } + } + } + + override fun onHostResume() { + onAppEnterForeground() + } + + override fun onHostPause() { + onAppEnterBackground() + } + + override fun onHostDestroy() { + forceExitAllPictureInPicture() + } + + fun pauseOtherPlayers(pipVideoView: VideoView) { + val pipPlayer = pipVideoView.hybridPlayer + playersPausedForPip.clear() + + players.keys.forEach { player -> + // Skip the player that is used for the PiP view + if (player == pipPlayer) return@forEach + + // Pause only if it is currently playing + if (player.isPlaying && player.mixAudioMode != MixAudioMode.MIXWITHOTHERS) { + player.pause() + playersPausedForPip.add(player) + Log.v(TAG, "Paused player for PiP (nitroIds: ${players[player]})") + } + } + } + + private fun resumePlayersPausedForPip() { + playersPausedForPip.forEach { player -> + // Ensure the player is attached to the latest visible VideoView before resuming + maybePassPlayerToView(player) + + if (!player.isPlaying) { + player.play() + Log.v(TAG, "Resumed player after PiP exit (nitroIds: ${players[player]})") + } + } + playersPausedForPip.clear() + } + + fun getAnyPlayingVideoView(): VideoView? { + return views.values.firstOrNull { ref -> + ref.get()?.hybridPlayer?.isPlaying == true + }?.get() + } + + fun setLastPlayedPlayer(player: HybridVideoPlayer) { + // Resolve to the latest view using this player (usually the last one in the list) + val nitroIds = players[player] ?: return + if (nitroIds.isNotEmpty()) { + lastPlayedNitroId = nitroIds.last() + } + } + + fun getLastPlayedVideoView(): VideoView? { + return lastPlayedNitroId?.let { views[it]?.get() } + } +} diff --git a/android/src/main/java/com/twg/video/core/extensions/ResizeMode+AspectRatioFrameLayout.kt b/android/src/main/java/com/twg/video/core/extensions/ResizeMode+AspectRatioFrameLayout.kt new file mode 100644 index 00000000..7fedeb5c --- /dev/null +++ b/android/src/main/java/com/twg/video/core/extensions/ResizeMode+AspectRatioFrameLayout.kt @@ -0,0 +1,20 @@ +package com.twg.video.core.extensions + +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import androidx.media3.ui.AspectRatioFrameLayout +import com.margelo.nitro.video.ResizeMode + +@OptIn(UnstableApi::class) +/** + * Converts a [ResizeMode] to a [AspectRatioFrameLayout] resize mode. + * @return The corresponding [AspectRatioFrameLayout] resize mode. + */ +fun ResizeMode.toAspectRatioFrameLayout(): Int { + return when (this) { + ResizeMode.CONTAIN -> AspectRatioFrameLayout.RESIZE_MODE_FIT + ResizeMode.COVER -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM + ResizeMode.STRETCH -> AspectRatioFrameLayout.RESIZE_MODE_FILL + ResizeMode.NONE -> AspectRatioFrameLayout.RESIZE_MODE_FIT + } +} diff --git a/android/src/main/java/com/twg/video/core/extensions/SubtitleType+toString.kt b/android/src/main/java/com/twg/video/core/extensions/SubtitleType+toString.kt new file mode 100644 index 00000000..abc52ce0 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/extensions/SubtitleType+toString.kt @@ -0,0 +1,14 @@ +package com.twg.video.core.extensions + +import com.margelo.nitro.video.SubtitleType + +fun SubtitleType.toStringExtension(): String { + return when { + this == SubtitleType.AUTO -> "auto" + this == SubtitleType.VTT -> "vtt" + this == SubtitleType.SRT -> "srt" + this == SubtitleType.SSA -> "ssa" + this == SubtitleType.ASS -> "ass" + else -> throw IllegalArgumentException("Unknown SubtitleType: $this") + } +} diff --git a/android/src/main/java/com/twg/video/core/extensions/VideoPlaybackService+ServiceManagment.kt b/android/src/main/java/com/twg/video/core/extensions/VideoPlaybackService+ServiceManagment.kt new file mode 100644 index 00000000..52e29ac7 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/extensions/VideoPlaybackService+ServiceManagment.kt @@ -0,0 +1,52 @@ +package com.twg.video.core.extensions + +import android.content.Context +import android.content.Context.BIND_AUTO_CREATE +import android.content.Context.BIND_INCLUDE_CAPABILITIES +import android.content.Intent +import android.os.Build +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import com.twg.video.core.services.playback.VideoPlaybackService +import com.twg.video.core.services.playback.VideoPlaybackServiceConnection + +fun VideoPlaybackService.Companion.startService( + context: Context, + serviceConnection: VideoPlaybackServiceConnection +) { + val reactContext = NitroModules.applicationContext ?: return + + val intent = Intent(context, VideoPlaybackService::class.java) + intent.action = VIDEO_PLAYBACK_SERVICE_INTERFACE + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + reactContext.startForegroundService(intent); + } else { + reactContext.startService(intent); + } + + val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + BIND_AUTO_CREATE or BIND_INCLUDE_CAPABILITIES + } else { + BIND_AUTO_CREATE + } + + context.bindService(intent, serviceConnection, flags) +} + +@OptIn(UnstableApi::class) +fun VideoPlaybackService.Companion.stopService( + player: HybridVideoPlayer, + serviceConnection: VideoPlaybackServiceConnection +) { + try { + // Unregister the player first; this might stop the service if no players remain + serviceConnection.unregisterPlayer(player) + // Ask service (if still connected) to stop when idle + try { serviceConnection.serviceBinder?.service?.stopIfNoPlayers() } catch (_: Exception) {} + // Then unbind + NitroModules.applicationContext?.currentActivity?.unbindService(serviceConnection) + } catch (_: Exception) {} +} diff --git a/android/src/main/java/com/twg/video/core/fragments/FullscreenVideoFragment.kt b/android/src/main/java/com/twg/video/core/fragments/FullscreenVideoFragment.kt new file mode 100644 index 00000000..868e2540 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/fragments/FullscreenVideoFragment.kt @@ -0,0 +1,249 @@ +package com.twg.video.core.fragments + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.Configuration +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowInsets +import android.view.WindowInsetsController +import android.view.WindowManager +import android.widget.FrameLayout +import android.widget.ImageButton +import androidx.activity.OnBackPressedCallback +import androidx.annotation.OptIn +import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import androidx.media3.common.util.UnstableApi +import com.twg.video.core.utils.PictureInPictureUtils.createPictureInPictureParams +import com.twg.video.core.utils.SmallVideoPlayerOptimizer +import com.twg.video.view.VideoView +import java.util.UUID + +@OptIn(UnstableApi::class) +class FullscreenVideoFragment(private val videoView: VideoView) : Fragment() { + val id: String = UUID.randomUUID().toString() + + private var container: FrameLayout? = null + private var originalPlayerParent: ViewGroup? = null + private var originalPlayerLayoutParams: ViewGroup.LayoutParams? = null + private var rootContentViews: List = listOf() + + // Back press callback to handle back navigation + private val backPressCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + videoView.exitFullscreen() + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Create a fullscreen container + this.container = FrameLayout(requireContext()).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + setBackgroundColor(android.graphics.Color.BLACK) + keepScreenOn = true + } + return this.container + } + + override fun onResume() { + super.onResume() + + // System UI is re-enabled when user have exited app and go back + // We need to hide it again + hideSystemUI() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + // Register back press callback + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressCallback) + + enterFullscreenMode() + setupPlayerView() + hideSystemUI() + + // Update PiP params if supported + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + val params = createPictureInPictureParams(videoView) + requireActivity().setPictureInPictureParams(params) + } catch (_: Exception) {} + } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + + // Handle PiP mode changes + val isInPictureInPictureMode = + requireActivity().isInPictureInPictureMode + + if (isInPictureInPictureMode) { + videoView.playerView.useController = false + } else { + videoView.playerView.useController = videoView.useController + } + } + + private fun enterFullscreenMode() { + // Store original parent and layout params + originalPlayerParent = videoView.playerView.parent as? ViewGroup + originalPlayerLayoutParams = videoView.playerView.layoutParams + + // Remove player from original parent + originalPlayerParent?.removeView(videoView.playerView) + + // Hide all root content views + val currentActivity = requireActivity() + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + rootContentViews = (0 until rootContent.childCount) + .map { rootContent.getChildAt(it) } + .filter { it.isVisible } + + rootContentViews.forEach { view -> + view.visibility = View.GONE + } + + // Add our fullscreen container to root + rootContent.addView(container, + ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + ) + } + + private fun setupPlayerView() { + // Add PlayerView to our container + container?.addView(videoView.playerView, + FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ) + ) + + videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK) + videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK) + + // We need show controls in fullscreen + videoView.playerView.useController = true + + setupFullscreenButton() + videoView.playerView.setShowSubtitleButton(true) + + // Apply optimizations based on video player size in fullscreen mode + SmallVideoPlayerOptimizer.applyOptimizations(videoView.playerView, requireContext(), isFullscreen = true) + } + + @SuppressLint("PrivateResource") + private fun setupFullscreenButton() { + videoView.playerView.setFullscreenButtonClickListener { _ -> + videoView.exitFullscreen() + } + + // Change icon to exit fullscreen + val button = videoView.playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) + button?.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit) + } + + @Suppress("DEPRECATION") + private fun hideSystemUI() { + val currentActivity = requireActivity() + container?.let { container -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + container.fitsSystemWindows = false + container.windowInsetsController?.let { controller -> + controller.hide(WindowInsets.Type.systemBars()) + controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + } else { + currentActivity.window.decorView.systemUiVisibility = ( + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_FULLSCREEN + ) + } + } + } + + @Suppress("DEPRECATION") + private fun restoreSystemUI() { + val currentActivity = requireActivity() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + container?.windowInsetsController?.show(WindowInsets.Type.systemBars()) + } else { + currentActivity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE + } + } + + fun exitFullscreen() { + // Remove back press callback since we're exiting + backPressCallback.remove() + + restoreSystemUI() + + if (videoView.useController == false) { + videoView.playerView.useController = false + } + + // Ensure PlayerView keeps black background when returning to normal mode + videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK) + videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK) + + // Remove PlayerView from our container + container?.removeView(videoView.playerView) + + // Remove our container from root + val currentActivity = requireActivity() + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + rootContent.removeView(container) + + // Restore root content views + rootContentViews.forEach { it.visibility = View.VISIBLE } + rootContentViews = listOf() + + // Safely restore PlayerView to original parent + // First, ensure PlayerView is removed from any current parent + val currentParent = videoView.playerView.parent as? ViewGroup + currentParent?.removeView(videoView.playerView) + + // Now add it back to the original parent if it's not already the parent + if (videoView.playerView.parent != originalPlayerParent) { + originalPlayerParent?.addView(videoView.playerView, originalPlayerLayoutParams) + } + + // Remove this fragment + parentFragmentManager.beginTransaction() + .remove(this) + .commitAllowingStateLoss() + + // Notify VideoView that we've exited fullscreen + videoView.isInFullscreen = false + } + + + + override fun onDestroy() { + super.onDestroy() + + // Ensure we clean up properly if fragment is destroyed + if (videoView.isInFullscreen) { + exitFullscreen() + } + } +} diff --git a/android/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.kt b/android/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.kt new file mode 100644 index 00000000..b3a21c23 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.kt @@ -0,0 +1,72 @@ +package com.twg.video.core.fragments + +import android.content.res.Configuration +import android.os.Bundle +import android.util.Log +import androidx.annotation.OptIn +import androidx.fragment.app.Fragment +import androidx.media3.common.util.UnstableApi +import com.twg.video.core.VideoManager +import com.twg.video.view.VideoView +import java.util.UUID + +@OptIn(UnstableApi::class) +class PictureInPictureHelperFragment(private val videoView: VideoView) : Fragment() { + val id: String = UUID.randomUUID().toString() + + override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) { + super.onPictureInPictureModeChanged(isInPictureInPictureMode) + + if (isInPictureInPictureMode) { + var currentPipVideo = VideoManager.getCurrentPictureInPictureVideo() + + if (currentPipVideo == null) { + synchronized(VideoManager) { + currentPipVideo = VideoManager.getCurrentPictureInPictureVideo() + if (currentPipVideo == null) { + if (videoView.hybridPlayer?.isPlaying == true) { + val lastPlayed = VideoManager.getLastPlayedVideoView() + val shouldDesignate = lastPlayed == null || lastPlayed.nitroId == videoView.nitroId + + if (shouldDesignate) { + VideoManager.setCurrentPictureInPictureVideo(videoView) + videoView.hybridPlayer?.movePlayerToVideoView(videoView) + VideoManager.pauseOtherPlayers(videoView) + currentPipVideo = videoView + } + } else { + if (!VideoManager.isAnyVideoInPictureInPicture()) { + val lastPlayed = VideoManager.getLastPlayedVideoView() + val targetView = lastPlayed ?: videoView + + VideoManager.setCurrentPictureInPictureVideo(targetView) + targetView.hybridPlayer?.movePlayerToVideoView(targetView) + VideoManager.pauseOtherPlayers(targetView) + currentPipVideo = targetView + } + } + } + } + } + + if (currentPipVideo == videoView) { + // If we're currently in fullscreen, exit it first to prevent parent conflicts + if (videoView.isInFullscreen) { + try { + videoView.exitFullscreen() + } catch (e: Exception) { + Log.w("ReactNativeVideo", "Failed to exit fullscreen before entering PiP for nitroId: ${videoView.nitroId}", e) + } + } + + // Now move the PlayerView to the root for PiP and hide content + videoView.hideRootContentViews() + videoView.isInPictureInPicture = true + } + } else { + if (videoView.isInPictureInPicture) { + videoView.exitPictureInPicture() + } + } + } +} diff --git a/android/src/main/java/com/twg/video/core/player/DRMManagerSpec.kt b/android/src/main/java/com/twg/video/core/player/DRMManagerSpec.kt new file mode 100644 index 00000000..d64e8174 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/player/DRMManagerSpec.kt @@ -0,0 +1,23 @@ +package com.twg.video.core.player + +import androidx.annotation.OptIn +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.common.util.Util +import androidx.media3.exoplayer.drm.DrmSessionManager +import com.margelo.nitro.video.NativeDrmParams +import java.util.UUID + +@OptIn(UnstableApi::class) +interface DRMManagerSpec { + fun buildDrmSessionManager(drmParams: NativeDrmParams): DrmSessionManager { + val drmScheme = drmParams.type ?: "widevine" + val drmUuid = Util.getDrmUuid(drmScheme) + + return buildDrmSessionManager(drmParams, drmUuid) + } + + fun buildDrmSessionManager(drmParams: NativeDrmParams, drmUuid: UUID?, retryCount: Int = 0): DrmSessionManager + + fun getDRMConfiguration(drmParams: NativeDrmParams): MediaItem.DrmConfiguration +} \ No newline at end of file diff --git a/android/src/main/java/com/twg/video/core/player/DataSourceFactoryUtils.kt b/android/src/main/java/com/twg/video/core/player/DataSourceFactoryUtils.kt new file mode 100644 index 00000000..02b03aa6 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/player/DataSourceFactoryUtils.kt @@ -0,0 +1,51 @@ +package com.twg.video.core.player + +import android.content.Context +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import androidx.media3.common.util.Util +import androidx.media3.datasource.DefaultDataSource +import androidx.media3.datasource.okhttp.OkHttpDataSource +import com.facebook.react.bridge.ReactContext +import com.facebook.react.modules.network.CookieJarContainer +import com.facebook.react.modules.network.ForwardingCookieHandler +import com.facebook.react.modules.network.OkHttpClientProvider +import com.margelo.nitro.video.HybridVideoPlayerSourceSpec +import okhttp3.JavaNetCookieJar + +fun buildBaseDataSourceFactory(context: Context, source: HybridVideoPlayerSourceSpec): DefaultDataSource.Factory { + return if (source.uri.startsWith("http")) { + DefaultDataSource.Factory(context, buildHttpDataSourceFactory(context, source)) + } else { + DefaultDataSource.Factory(context) + } +} + +@OptIn(UnstableApi::class) +fun buildHttpDataSourceFactory(context: Context, source: HybridVideoPlayerSourceSpec): OkHttpDataSource.Factory { + val client = OkHttpClientProvider.getOkHttpClient() + + if (context is ReactContext) { + val handler = ForwardingCookieHandler(context) + (client.cookieJar as CookieJarContainer).setCookieJar(JavaNetCookieJar(handler)) + } + + val factory = OkHttpDataSource.Factory(client) + + val headers: Map? = source.config.headers + + if (headers != null) { + factory.setDefaultRequestProperties(headers) + } + + if (headers == null || !headers.containsKey("User-Agent")) { + factory.setUserAgent(getUserAgent(context)) + } + + return factory +} + +@OptIn(UnstableApi::class) +fun getUserAgent(context: Context): String { + return Util.getUserAgent(context, context.packageName) +} diff --git a/android/src/main/java/com/twg/video/core/player/MediaItemUtils.kt b/android/src/main/java/com/twg/video/core/player/MediaItemUtils.kt new file mode 100644 index 00000000..329ada25 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/player/MediaItemUtils.kt @@ -0,0 +1,141 @@ +package com.twg.video.core.player + +import android.util.Log +import android.webkit.MimeTypeMap +import androidx.annotation.OptIn +import androidx.core.net.toUri +import androidx.media3.common.MediaItem +import androidx.media3.common.C +import androidx.media3.common.MediaMetadata +import androidx.media3.common.MimeTypes +import androidx.media3.common.util.UnstableApi +import com.margelo.nitro.video.BufferConfig +import com.margelo.nitro.video.CustomVideoMetadata +import com.margelo.nitro.video.HybridVideoPlayerSource +import com.margelo.nitro.video.LivePlaybackParams +import com.margelo.nitro.video.NativeDrmParams +import com.margelo.nitro.video.NativeVideoConfig +import com.margelo.nitro.video.SubtitleType +import com.twg.video.core.LibraryError +import com.twg.video.core.SourceError +import com.twg.video.core.extensions.toStringExtension +import com.twg.video.core.plugins.PluginsRegistry + +private const val TAG = "MediaItemUtils" + +@OptIn(UnstableApi::class) +fun createMediaItemFromVideoConfig( + source: HybridVideoPlayerSource +): MediaItem { + val mediaItemBuilder = MediaItem.Builder() + + mediaItemBuilder.setUri(source.config.uri) + + source.config.drm?.let { drmParams -> + val drmManager = source.drmManager ?: throw LibraryError.DRMPluginNotFound + val drmConfiguration = drmManager.getDRMConfiguration(drmParams) + mediaItemBuilder.setDrmConfiguration(drmConfiguration) + } + + source.config.bufferConfig?.livePlayback?.let { livePlaybackParams -> + mediaItemBuilder.setLiveConfiguration(getLiveConfiguration(livePlaybackParams)) + } + + source.config.metadata?.let { metadata -> + mediaItemBuilder.setMediaMetadata(getCustomMetadata(metadata)) + } + + return PluginsRegistry.shared.overrideMediaItemBuilder( + source, + mediaItemBuilder + ).build() +} + +fun getSubtitlesConfiguration( + config: NativeVideoConfig, +): List { + val subtitlesConfiguration: MutableList = mutableListOf() + + if (config.externalSubtitles != null) { + for (subtitle in config.externalSubtitles) { + val ext = if (subtitle.type == SubtitleType.AUTO) { + MimeTypeMap.getFileExtensionFromUrl(subtitle.uri) + } else { + subtitle.type.toStringExtension() + } + + val mimeType = when (ext?.lowercase()) { + "srt" -> MimeTypes.APPLICATION_SUBRIP + "vtt" -> MimeTypes.TEXT_VTT + "ssa", "ass" -> MimeTypes.TEXT_SSA + else -> { + Log.e(TAG, "Unsupported subtitle extension '$ext' for URI: ${subtitle.uri}. Skipping this subtitle.") + continue + } + } + + try { + val subtitleConfig = MediaItem.SubtitleConfiguration.Builder(subtitle.uri.toUri()) + .setId("external-subtitle-${subtitle.uri}") + .setMimeType(mimeType) + .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) + .setRoleFlags(C.ROLE_FLAG_SUBTITLE) + .setLabel(subtitle.label) + .build() + subtitlesConfiguration.add(subtitleConfig) + } catch (e: Exception) { + Log.e(TAG, "Error creating SubtitleConfiguration for URI ${subtitle.uri}: ${e.message}", e) + } + } + } + return subtitlesConfiguration +} + +fun getLiveConfiguration( + livePlaybackParams: LivePlaybackParams +): MediaItem.LiveConfiguration { + val liveConfiguration = MediaItem.LiveConfiguration.Builder() + + livePlaybackParams.maxOffsetMs?.let { + if (it >= 0) { + liveConfiguration.setMaxOffsetMs(it.toLong()) + } + } + + livePlaybackParams.minOffsetMs?.let { + if (it >= 0) { + liveConfiguration.setMinOffsetMs(it.toLong()) + } + } + + livePlaybackParams.targetOffsetMs?.let { + if (it >= 0) { + liveConfiguration.setTargetOffsetMs(it.toLong()) + } + } + + livePlaybackParams.maxPlaybackSpeed?.let { + if (it >= 0) { + liveConfiguration.setMaxPlaybackSpeed(it.toFloat()) + } + } + + livePlaybackParams.minPlaybackSpeed?.let { + if (it >= 0) { + liveConfiguration.setMinPlaybackSpeed(it.toFloat()) + } + } + + return liveConfiguration.build() +} + +fun getCustomMetadata(metadata: CustomVideoMetadata): MediaMetadata { + return MediaMetadata.Builder() + .setDisplayTitle(metadata.title) + .setTitle(metadata.title) + .setSubtitle(metadata.subtitle) + .setDescription(metadata.description) + .setArtist(metadata.artist) + .setArtworkUri(metadata.imageUri?.toUri()) + .build() +} diff --git a/android/src/main/java/com/twg/video/core/player/MediaSourceUtils.kt b/android/src/main/java/com/twg/video/core/player/MediaSourceUtils.kt new file mode 100644 index 00000000..0d422099 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/player/MediaSourceUtils.kt @@ -0,0 +1,112 @@ +package com.twg.video.core.player + +import android.content.Context +import android.net.Uri +import androidx.annotation.OptIn +import androidx.media3.common.util.Util +import androidx.media3.exoplayer.source.MediaSource +import com.margelo.nitro.video.HybridVideoPlayerSourceSpec +import androidx.core.net.toUri +import androidx.media3.common.C +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.dash.DashMediaSource +import androidx.media3.exoplayer.drm.DrmSessionManager +import androidx.media3.exoplayer.hls.HlsMediaSource +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MergingMediaSource +import com.margelo.nitro.video.HybridVideoPlayerSource +import com.twg.video.core.LibraryError +import com.twg.video.core.SourceError +import com.twg.video.core.plugins.PluginsRegistry + +@OptIn(UnstableApi::class) +@Throws(SourceError::class) +fun buildMediaSource(context: Context, source: HybridVideoPlayerSource, mediaItem: MediaItem): MediaSource { + val uri = source.uri.toUri() + + // Explanation: + // 1. Remove query params from uri to avoid getting false extension + // 2. Get extension from uri + val type = Util.inferContentType(uri) + val dataSourceFactory = PluginsRegistry.shared.overrideMediaDataSourceFactory( + source, + buildBaseDataSourceFactory(context, source) + ) + + if (!source.config.externalSubtitles.isNullOrEmpty()) { + return buildExternalSubtitlesMediaSource(context, source) + } + + val mediaSourceFactory: MediaSource.Factory = when (type) { + C.CONTENT_TYPE_DASH -> { + DashMediaSource.Factory(dataSourceFactory) + } + C.CONTENT_TYPE_HLS -> { + HlsMediaSource.Factory(dataSourceFactory) + } + C.CONTENT_TYPE_OTHER -> { + DefaultMediaSourceFactory(context) + .setDataSourceFactory(dataSourceFactory) + } + else -> { + throw SourceError.UnsupportedContentType(source.uri) + } + } + + source.config.drm?.let { + val drmSessionManager = source.drmSessionManager ?: throw LibraryError.DRMPluginNotFound + mediaSourceFactory.setDrmSessionManagerProvider { drmSessionManager } + } + + return PluginsRegistry.shared.overrideMediaSourceFactory( + source, + mediaSourceFactory, + dataSourceFactory + ).createMediaSource(mediaItem) +} + +@OptIn(UnstableApi::class) +fun buildExternalSubtitlesMediaSource(context: Context, source: HybridVideoPlayerSource): MediaSource { + val dataSourceFactory = PluginsRegistry.shared.overrideMediaDataSourceFactory( + source, + buildBaseDataSourceFactory(context, source) + ) + + val mediaItemBuilderWithSubtitles = MediaItem.Builder() + .setUri(source.uri.toUri()) + .setSubtitleConfigurations(getSubtitlesConfiguration(source.config)) + + source.config.metadata?.let { metadata -> + mediaItemBuilderWithSubtitles.setMediaMetadata(getCustomMetadata(metadata)) + } + + val mediaItemBuilder = PluginsRegistry.shared.overrideMediaItemBuilder( + source, + mediaItemBuilderWithSubtitles + ) + + val mediaSourceFactory = DefaultMediaSourceFactory(context) + .setDataSourceFactory(dataSourceFactory) + + if (source.config.drm != null) { + if (source.drmManager == null) { + throw LibraryError.DRMPluginNotFound + } + + mediaSourceFactory.setDrmSessionManagerProvider { + source.drmManager as DrmSessionManager + } + + val drmConfiguration = source.drmManager!!.getDRMConfiguration(source.config.drm!!) + mediaItemBuilder.setDrmConfiguration(drmConfiguration) + } + + return PluginsRegistry.shared.overrideMediaSourceFactory( + source, + mediaSourceFactory, + dataSourceFactory + ).createMediaSource(mediaItemBuilder.build()) +} + + diff --git a/android/src/main/java/com/twg/video/core/player/OnAudioFocusChangedListener.kt b/android/src/main/java/com/twg/video/core/player/OnAudioFocusChangedListener.kt new file mode 100644 index 00000000..5b933b50 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/player/OnAudioFocusChangedListener.kt @@ -0,0 +1,27 @@ +package com.twg.video.core.player + +import android.content.IntentFilter +import android.media.AudioManager +import androidx.core.content.ContextCompat +import com.margelo.nitro.video.HybridVideoPlayerEventEmitterSpec + +// TODO: We should make VideoFocusManager that will track focus globally for now lets just do simple listener +class OnAudioFocusChangedListener : AudioManager.OnAudioFocusChangeListener { + private var eventEmitter: HybridVideoPlayerEventEmitterSpec? = null + + override fun onAudioFocusChange(focusChange: Int) { + when (focusChange) { + AudioManager.AUDIOFOCUS_GAIN -> eventEmitter?.onAudioFocusChange?.invoke(true) + AudioManager.AUDIOFOCUS_LOSS -> eventEmitter?.onAudioFocusChange?.invoke(false) + AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> eventEmitter?.onAudioFocusChange?.invoke(false) + } + } + + fun setEventEmitter(eventEmitter: HybridVideoPlayerEventEmitterSpec) { + this.eventEmitter = eventEmitter + } + + fun removeEventEmitter() { + this.eventEmitter = null + } +} diff --git a/android/src/main/java/com/twg/video/core/plugins/PluginsRegistry.kt b/android/src/main/java/com/twg/video/core/plugins/PluginsRegistry.kt new file mode 100644 index 00000000..eabdbcb6 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/plugins/PluginsRegistry.kt @@ -0,0 +1,223 @@ +package com.twg.video.core.plugins + +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.datasource.DataSource +import androidx.media3.exoplayer.source.MediaSource +import com.margelo.nitro.video.HybridVideoPlayer +import com.margelo.nitro.video.HybridVideoPlayerSource +import com.twg.video.BuildConfig +import com.twg.video.core.LibraryError +import com.twg.video.core.player.DRMManagerSpec +import com.twg.video.view.VideoView +import java.lang.ref.WeakReference + +// Keep these types for platform compatibility +// On iOS we cannot just export HybridVideoPlayer so we need to keep this typealias +typealias NativeVideoPlayer = HybridVideoPlayer +typealias NativeVideoPlayerSource = HybridVideoPlayerSource + +class PluginsRegistry { + // Plugin ID -> ReactNativeVideoPluginSpec + private val plugins: MutableMap = mutableMapOf() + + companion object { + val shared = PluginsRegistry() + private const val TAG = "ReactNativeVideoPluginsRegistry" + } + + // Public methods + fun register(plugin: ReactNativeVideoPluginSpec) { + if(hasPlugin(plugin)) { + plugins.replace(plugin.id, plugin) + + if (BuildConfig.DEBUG) { + Log.d(TAG, "Replaced plugin ${plugin.name} (ID: ${plugin.id})") + } + + return + } + + plugins.put(plugin.id, plugin) + + if (BuildConfig.DEBUG) { + Log.d(TAG, "Registered plugin ${plugin.name} (ID: ${plugin.id})") + } + } + + @Suppress("unused") + fun unregister(plugin: ReactNativeVideoPluginSpec) { + if (!hasPlugin(plugin)) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "Tried to unregister plugin ${plugin.name} (ID: ${plugin.id}), but it was not registered") + } + + return + } + + plugins.remove(plugin.id) + + if (BuildConfig.DEBUG) { + Log.d(TAG, "Unregistered plugin ${plugin.name} (ID: ${plugin.id})") + } + } + + // Notifications + @OptIn(UnstableApi::class) + internal fun notifyPlayerCreated(player: WeakReference) { + plugins.values.forEach { it.onPlayerCreated(player) } + } + + @OptIn(UnstableApi::class) + internal fun notifyPlayerDestroyed(player: WeakReference) { + plugins.values.forEach { it.onPlayerDestroyed(player) } + } + + @OptIn(UnstableApi::class) + internal fun notifyVideoViewCreated(view: WeakReference) { + plugins.values.forEach { it.onVideoViewCreated(view) } + } + + @OptIn(UnstableApi::class) + internal fun notifyVideoViewDestroyed(view: WeakReference) { + plugins.values.forEach { it.onVideoViewDestroyed(view) } + } + + // Internal methods + + /** + * Maybe override the source with the plugins. + * + * This method is used to override the source with the plugins. + * It is called when a source is created and is used to override the source with the plugins. + * + * It is not guaranteed that the source will be overridden with the plugins. + * If no plugin overrides the source, the original source is returned. + * + * @param source The source instance. + * @return The maybe overridden source instance. + */ + internal fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource { + var overriddenSource = source + + for (plugin in plugins.values) { + overriddenSource = plugin.overrideSource(overriddenSource) + } + + return overriddenSource + } + + /** + * Returns the DRM manager instance from the plugins. + * + * @throws LibraryError.DRMPluginNotFound If no DRM manager is found. + * @return Any + */ + internal fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec { + for (plugin in plugins.values) { + val manager = plugin.getDRMManager(source) + + if (manager != null) return manager + } + + throw LibraryError.DRMPluginNotFound + } + + /** + * Maybe override the media data source factory with the plugins. + * + * If no plugin overrides the media data source factory, the original factory is returned. + * + * @param source The source instance. + * @param mediaDataSourceFactory The media data source factory instance. + * @return The maybe overridden media data source factory instance. + */ + internal fun overrideMediaDataSourceFactory( + source: NativeVideoPlayerSource, + mediaDataSourceFactory: DataSource.Factory + ): DataSource.Factory { + for (plugin in plugins.values) { + val factory = plugin.getMediaDataSourceFactory(source, mediaDataSourceFactory) + + if (factory != null) return factory + } + + return mediaDataSourceFactory + } + + /** + * Maybe override the media source factory with the plugins. + * + * If no plugin overrides the media source factory, the original factory is returned. + * + * @param source The source instance. + * @param mediaSourceFactory The media source factory instance. + * @param mediaDataSourceFactory The media data source factory instance. + * @return The maybe overridden media source factory instance. + */ + internal fun overrideMediaSourceFactory( + source: NativeVideoPlayerSource, + mediaSourceFactory: MediaSource.Factory, + mediaDataSourceFactory: DataSource.Factory + ): MediaSource.Factory { + for (plugin in plugins.values) { + val factory = plugin.getMediaSourceFactory(source, mediaSourceFactory, mediaDataSourceFactory) + + if (factory != null) return factory + } + + return mediaSourceFactory + } + + /** + * Maybe override the media item builder with the plugins. + * + * If no plugin overrides the media item builder, the original builder is returned. + * + * @param source The source instance. + * @param mediaItemBuilder The media item builder instance. + * @return The maybe overridden media item builder instance. + */ + internal fun overrideMediaItemBuilder( + source: NativeVideoPlayerSource, + mediaItemBuilder: MediaItem.Builder + ): MediaItem.Builder { + for (plugin in plugins.values) { + val builder = plugin.getMediaItemBuilder(source, mediaItemBuilder) + + if (builder != null) return builder + } + + return mediaItemBuilder + } + + /** + * Maybe disable the cache with the plugins. + * + * If no plugin disables the cache, the original cache is not disabled. + * + * @param source The source instance. + * @return The maybe disabled cache. + */ + internal fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean { + for (plugin in plugins.values) { + val shouldDisable = plugin.shouldDisableCache(source) + + if (shouldDisable) return true + } + + return false + } + + /** + * Checks if a plugin is registered. + * + * @param plugin The plugin instance. + * @return True if the plugin is registered, false otherwise. + */ + internal fun hasPlugin(plugin: ReactNativeVideoPluginSpec): Boolean { + return plugins.any { it.key == plugin.id } + } +} \ No newline at end of file diff --git a/android/src/main/java/com/twg/video/core/plugins/ReactNativeVideoPlugin.kt b/android/src/main/java/com/twg/video/core/plugins/ReactNativeVideoPlugin.kt new file mode 100644 index 00000000..007b68fe --- /dev/null +++ b/android/src/main/java/com/twg/video/core/plugins/ReactNativeVideoPlugin.kt @@ -0,0 +1,173 @@ +package com.twg.video.core.plugins + +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.datasource.DataSource +import androidx.media3.exoplayer.source.MediaSource +import com.twg.video.core.player.DRMManagerSpec +import com.twg.video.view.VideoView +import java.lang.ref.WeakReference + +interface ReactNativeVideoPluginSpec { + /** + * The ID of the plugin. + */ + val id: String + + /** + * The name of the plugin. + */ + val name: String + + /** + * Called when a player is created. + * + * @param player The weak reference to the player instance. + */ + @UnstableApi + fun onPlayerCreated(player: WeakReference) + + /** + * Called when a player is destroyed. + * + * @param player The weak reference to the player instance. + */ + @UnstableApi + fun onPlayerDestroyed(player: WeakReference) + + /** + * Called when a video view is created. + * + * @param view The weak reference to the video view instance. + */ + @UnstableApi + fun onVideoViewCreated(view: WeakReference) + + /** + * Called when a video view is destroyed. + * + * @param view The weak reference to the video view instance. + */ + @UnstableApi + fun onVideoViewDestroyed(view: WeakReference) + + /** + * Called when a source is being used to create mediaItem or MediaSource. + * You can use it to modify the source before it is used. + * + * @param source The source instance. + * @return The overridden source instance. + */ + fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource + + /** + * Called when a DRM manager is requested. + * + * @return The DRM manager instance. + */ + fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec? + + + /** + * Called when a media data source factory is requested. + * + * @param source The source instance. + * @param mediaDataSourceFactory The media data source factory. + * @return The media data source factory. If null is returned, the default factory will be used. + */ + fun getMediaDataSourceFactory( + source: NativeVideoPlayerSource, + mediaDataSourceFactory: DataSource.Factory + ): DataSource.Factory? + + /** + * Called when a media source factory is requested. + * + * @param source The source instance. + * @param mediaSourceFactory The media source factory. + * @param mediaDataSourceFactory The media data source factory. + * @return The media source factory. If null is returned, the default factory will be used. + */ + fun getMediaSourceFactory( + source: NativeVideoPlayerSource, + mediaSourceFactory: MediaSource.Factory, + mediaDataSourceFactory: DataSource.Factory + ): MediaSource.Factory? + + /** + * Called when a media item builder is requested. + * + * @param source The source instance. + * @param mediaItemBuilder The media item builder. + * @return The media item builder. If null is returned, the default builder will be used. + */ + fun getMediaItemBuilder( + source: NativeVideoPlayerSource, + mediaItemBuilder: MediaItem.Builder + ): MediaItem.Builder? + + /** + * Called when a cache should be disabled. + * + * @param source The source instance. + * @return True if cache should be disabled, false otherwise. + */ + fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean +} + +@Suppress("Unused") +/** + * A helper base implementation of the ReactNativeVideoPluginSpec interface. + */ +open class ReactNativeVideoPlugin(override val name: String) : ReactNativeVideoPluginSpec { + override val id = "RNV_Plugin_${name}" + + init { + // Automatically register the plugin when it is created + PluginsRegistry.shared.register(this) + } + + @UnstableApi + override fun onPlayerCreated(player: WeakReference) { /* NOOP */} + + @UnstableApi + override fun onPlayerDestroyed(player: WeakReference) { /* NOOP */} + + @UnstableApi + override fun onVideoViewCreated(view: WeakReference) { /* NOOP */} + + @UnstableApi + override fun onVideoViewDestroyed(view: WeakReference) { /* NOOP */} + + override fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource { + return source + } + + override fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec? { return null } + + override fun getMediaDataSourceFactory( + source: NativeVideoPlayerSource, + mediaDataSourceFactory: DataSource.Factory + ): DataSource.Factory? { + return null + } + + override fun getMediaSourceFactory( + source: NativeVideoPlayerSource, + mediaSourceFactory: MediaSource.Factory, + mediaDataSourceFactory: DataSource.Factory + ): MediaSource.Factory? { + return null + } + + override fun getMediaItemBuilder( + source: NativeVideoPlayerSource, + mediaItemBuilder: MediaItem.Builder + ): MediaItem.Builder? { + return null + } + + override fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean { + return false + } +} \ No newline at end of file diff --git a/android/src/main/java/com/twg/video/core/recivers/AudioBecomingNoisyReceiver.kt b/android/src/main/java/com/twg/video/core/recivers/AudioBecomingNoisyReceiver.kt new file mode 100644 index 00000000..b613ee72 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/recivers/AudioBecomingNoisyReceiver.kt @@ -0,0 +1,38 @@ +package com.twg.video.core.recivers + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.media.AudioManager +import androidx.core.content.ContextCompat +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayerEventEmitterSpec +import com.twg.video.core.LibraryError + +class AudioBecomingNoisyReceiver() : BroadcastReceiver() { + private var eventEmitter: HybridVideoPlayerEventEmitterSpec? = null + + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) { + eventEmitter?.onAudioBecomingNoisy?.invoke() + } + } + + fun setEventEmitter(eventEmitter: HybridVideoPlayerEventEmitterSpec) { + val context = NitroModules.applicationContext ?: throw LibraryError.ApplicationContextNotFound + + this.eventEmitter = eventEmitter + val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY) + ContextCompat.registerReceiver( + context.applicationContext, + this, + intentFilter, + ContextCompat.RECEIVER_NOT_EXPORTED + ) + } + + fun removeEventEmitter() { + this.eventEmitter = null + } +} diff --git a/android/src/main/java/com/twg/video/core/services/playback/CustomMediaNotificationProvider.kt b/android/src/main/java/com/twg/video/core/services/playback/CustomMediaNotificationProvider.kt new file mode 100644 index 00000000..294fc2c6 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/services/playback/CustomMediaNotificationProvider.kt @@ -0,0 +1,147 @@ +package com.twg.video.core.services.playback + +import android.content.Context +import android.app.PendingIntent +import android.content.Intent +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.MediaMetadata +import androidx.media3.common.Player +import androidx.media3.common.util.UnstableApi +import androidx.media3.session.CommandButton +import androidx.media3.session.DefaultMediaNotificationProvider +import androidx.media3.session.MediaSession +import com.google.common.collect.ImmutableList +import androidx.core.os.bundleOf +import android.os.Bundle +import com.margelo.nitro.NitroModules +import com.twg.video.core.LibraryError + +@OptIn(UnstableApi::class) +class CustomMediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) { + + init { + setSmallIcon(androidx.media3.session.R.drawable.media3_notification_small_icon) + } + + fun getContext(): Context { + return NitroModules.applicationContext ?: run { + throw LibraryError.ApplicationContextNotFound + } + } + + override fun getNotificationContentTitle(metadata: MediaMetadata): CharSequence? { + return metadata.title + ?: metadata.displayTitle + ?: metadata.subtitle + ?: metadata.description + ?: "${getAppName()} is playing" + } + + override fun getNotificationContentText(metadata: MediaMetadata): CharSequence? { + return metadata.artist + ?: metadata.subtitle + ?: metadata.description + } + + companion object { + private const val SEEK_INTERVAL_MS = 10000L + private const val TAG = "CustomMediaNotificationProvider" + + enum class COMMAND(val stringValue: String) { + NONE("NONE"), + SEEK_FORWARD("COMMAND_SEEK_FORWARD"), + SEEK_BACKWARD("COMMAND_SEEK_BACKWARD"), + TOGGLE_PLAY("COMMAND_TOGGLE_PLAY"), + PLAY("COMMAND_PLAY"), + PAUSE("COMMAND_PAUSE") + } + + fun commandFromString(value: String): COMMAND = + when (value) { + COMMAND.SEEK_FORWARD.stringValue -> COMMAND.SEEK_FORWARD + COMMAND.SEEK_BACKWARD.stringValue -> COMMAND.SEEK_BACKWARD + COMMAND.TOGGLE_PLAY.stringValue -> COMMAND.TOGGLE_PLAY + COMMAND.PLAY.stringValue -> COMMAND.PLAY + COMMAND.PAUSE.stringValue -> COMMAND.PAUSE + else -> COMMAND.NONE + } + + fun handleCommand(command: COMMAND, session: MediaSession) { + // TODO: get somehow ControlsConfig here - for now hardcoded 10000ms + + when (command) { + COMMAND.SEEK_BACKWARD -> session.player.seekTo(session.player.contentPosition - SEEK_INTERVAL_MS) + COMMAND.SEEK_FORWARD -> session.player.seekTo(session.player.contentPosition + SEEK_INTERVAL_MS) + COMMAND.TOGGLE_PLAY -> handleCommand(if (session.player.isPlaying) COMMAND.PAUSE else COMMAND.PLAY, session) + COMMAND.PLAY -> session.player.play() + COMMAND.PAUSE -> session.player.pause() + else -> Log.w(TAG, "Received COMMAND.NONE - was there an error?") + } + } + } + + private fun getAppName(): String { + return try { + val context = getContext() + val pm = context.packageManager + val label = pm.getApplicationLabel(context.applicationInfo) + label.toString() + } catch (e: Exception) { + return "Unknown" + } + } + + override fun getMediaButtons( + session: MediaSession, + playerCommands: Player.Commands, + mediaButtonPreferences: ImmutableList, + showPauseButton: Boolean + ): ImmutableList { + val rewind = CommandButton.Builder() + .setDisplayName("Rewind") + .setSessionCommand(androidx.media3.session.SessionCommand( + COMMAND.SEEK_BACKWARD.stringValue, + Bundle.EMPTY + )) + .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_back_10) + .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 0)) + .build() + + val toggle = CommandButton.Builder() + .setDisplayName(if (showPauseButton) "Pause" else "Play") + .setSessionCommand(androidx.media3.session.SessionCommand( + COMMAND.TOGGLE_PLAY.stringValue, + Bundle.EMPTY + )) + .setIconResId( + if (showPauseButton) androidx.media3.session.R.drawable.media3_icon_pause + else androidx.media3.session.R.drawable.media3_icon_play + ) + .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 1)) + .build() + + val forward = CommandButton.Builder() + .setDisplayName("Forward") + .setSessionCommand(androidx.media3.session.SessionCommand( + COMMAND.SEEK_FORWARD.stringValue, + Bundle.EMPTY + )) + .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_forward_10) + .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 2)) + .build() + + return ImmutableList.of(rewind, toggle, forward) + } + + override fun addNotificationActions( + mediaSession: MediaSession, + mediaButtons: ImmutableList, + builder: androidx.core.app.NotificationCompat.Builder, + actionFactory: androidx.media3.session.MediaNotification.ActionFactory + ): IntArray { + // Use default behavior to add actions from our custom buttons and return compact indices + val compact = super.addNotificationActions(mediaSession, mediaButtons, builder, actionFactory) + return if (compact.isEmpty()) intArrayOf(0, 1, 2) else compact + } +} diff --git a/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackCallback.kt b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackCallback.kt new file mode 100644 index 00000000..25349a5d --- /dev/null +++ b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackCallback.kt @@ -0,0 +1,96 @@ +package com.twg.video.core.services.playback + +import android.os.Bundle +import androidx.annotation.OptIn +import androidx.media3.common.Player +import androidx.media3.common.util.UnstableApi +import androidx.media3.session.CommandButton +import androidx.media3.session.MediaSession +import androidx.media3.session.SessionCommand +import androidx.media3.session.SessionResult +import com.google.common.util.concurrent.ListenableFuture +import com.google.common.collect.ImmutableList + +@OptIn(UnstableApi::class) +class VideoPlaybackCallback : MediaSession.Callback { + // For Android 13+ + private fun buildCustomButtons(): ImmutableList { + val rewind = CommandButton.Builder() + .setDisplayName("Rewind") + .setSessionCommand( + SessionCommand( + CustomMediaNotificationProvider.Companion.COMMAND.SEEK_BACKWARD.stringValue, + Bundle.EMPTY + ) + ) + .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_back_10) + .build() + + val forward = CommandButton.Builder() + .setDisplayName("Forward") + .setSessionCommand( + SessionCommand( + CustomMediaNotificationProvider.Companion.COMMAND.SEEK_FORWARD.stringValue, + Bundle.EMPTY + ) + ) + .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_forward_10) + .build() + + return ImmutableList.of(rewind, forward) + } + + override fun onConnect(session: MediaSession, controller: MediaSession.ControllerInfo): MediaSession.ConnectionResult { + try { + return MediaSession.ConnectionResult.AcceptedResultBuilder(session) + .setAvailablePlayerCommands( + MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon() + .add(Player.COMMAND_SEEK_FORWARD) + .add(Player.COMMAND_SEEK_BACK) + .build() + ).setAvailableSessionCommands( + MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() + .add( + SessionCommand( + CustomMediaNotificationProvider.Companion.COMMAND.SEEK_FORWARD.stringValue, + Bundle.EMPTY + ) + ) + .add( + SessionCommand( + CustomMediaNotificationProvider.Companion.COMMAND.SEEK_BACKWARD.stringValue, + Bundle.EMPTY + ) + ) + .add( + SessionCommand( + CustomMediaNotificationProvider.Companion.COMMAND.TOGGLE_PLAY.stringValue, + Bundle.EMPTY + ) + ).build() + ).build() + } catch (e: Exception) { + return MediaSession.ConnectionResult.reject() + } + } + + override fun onPostConnect(session: MediaSession, controller: MediaSession.ControllerInfo) { + session.setCustomLayout(buildCustomButtons()) + super.onPostConnect(session, controller) + } + + override fun onCustomCommand( + session: MediaSession, + controller: MediaSession.ControllerInfo, + customCommand: SessionCommand, + args: Bundle + ): ListenableFuture { + CustomMediaNotificationProvider.Companion.handleCommand( + CustomMediaNotificationProvider.Companion.commandFromString( + customCommand.customAction + ), session + ) + + return super.onCustomCommand(session, controller, customCommand, args) + } +} diff --git a/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackService.kt b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackService.kt new file mode 100644 index 00000000..bd10a6f2 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackService.kt @@ -0,0 +1,138 @@ +package com.twg.video.core.services.playback + +import android.app.Activity +import android.app.PendingIntent +import android.content.Intent +import android.os.Binder +import android.os.IBinder +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.util.BitmapLoader +import androidx.media3.common.util.UnstableApi +import androidx.media3.session.DefaultMediaNotificationProvider +import androidx.media3.session.SimpleBitmapLoader +import androidx.media3.session.MediaSession +import androidx.media3.session.MediaSessionService +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +class VideoPlaybackServiceBinder(val service: VideoPlaybackService): Binder() + +@OptIn(UnstableApi::class) +class VideoPlaybackService : MediaSessionService() { + private var mediaSessionsList = mutableMapOf() + private var binder = VideoPlaybackServiceBinder(this) + private var sourceActivity: Class? = null // retained for future deep-links; currently unused + + override fun onCreate() { + super.onCreate() + setMediaNotificationProvider(CustomMediaNotificationProvider(this)) + } + + // Player Registry + fun registerPlayer(player: HybridVideoPlayer, from: Class) { + if (mediaSessionsList.containsKey(player)) { + return + } + sourceActivity = from + + val builder = MediaSession.Builder(this, player.player) + .setId("RNVideoPlaybackService_" + player.hashCode()) + .setCallback(VideoPlaybackCallback()) + + // Ensure tapping the notification opens the app via sessionActivity + try { + val launchIntent = packageManager.getLaunchIntentForPackage(packageName) + if (launchIntent != null) { + launchIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) + val contentIntent = PendingIntent.getActivity( + this, + 0, + launchIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + builder.setSessionActivity(contentIntent) + } + } catch (_: Exception) {} + + + val mediaSession = builder.build() + + mediaSessionsList[player] = mediaSession + addSession(mediaSession) + } + + fun unregisterPlayer(player: HybridVideoPlayer) { + val session = mediaSessionsList.remove(player) + session?.release() + stopIfNoPlayers() + } + + fun updatePlayerPreferences(player: HybridVideoPlayer) { + val session = mediaSessionsList[player] + if (session == null) { + // If not registered but now needs it, register + if (player.playInBackground || player.showNotificationControls) { + val activity = try { NitroModules.applicationContext?.currentActivity } catch (_: Exception) { null } + if (activity != null) registerPlayer(player, activity.javaClass) + } + return + } + + // If no longer needs registration, unregister and possibly stop service + if (!player.playInBackground && !player.showNotificationControls) { + unregisterPlayer(player) + stopIfNoPlayers() + return + } + } + + // Callbacks + + override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? = null + + override fun onBind(intent: Intent?): IBinder { + super.onBind(intent) + return binder + } + + override fun onTaskRemoved(rootIntent: Intent?) { + stopForegroundSafely() + cleanup() + stopSelf() + } + + override fun onDestroy() { + stopForegroundSafely() + cleanup() + super.onDestroy() + } + + private fun stopForegroundSafely() { + try { + stopForeground(STOP_FOREGROUND_REMOVE) + } catch (_: Exception) {} + } + + private fun cleanup() { + stopForegroundSafely() + stopSelf() + mediaSessionsList.forEach { (_, session) -> + session.release() + } + mediaSessionsList.clear() + } + + // Stop the service if there are no active media sessions (no players need it) + fun stopIfNoPlayers() { + if (mediaSessionsList.isEmpty()) { + cleanup() + } + } + + companion object { + const val VIDEO_PLAYBACK_SERVICE_INTERFACE = SERVICE_INTERFACE + } +} diff --git a/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackServiceConnection.kt b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackServiceConnection.kt new file mode 100644 index 00000000..ecc621f0 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackServiceConnection.kt @@ -0,0 +1,59 @@ +package com.twg.video.core.services.playback + +import android.content.ComponentName +import android.content.ServiceConnection +import android.os.IBinder +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import java.lang.ref.WeakReference + +@OptIn(UnstableApi::class) +class VideoPlaybackServiceConnection (private val player: WeakReference) : + ServiceConnection { + var serviceBinder: VideoPlaybackServiceBinder? = null + + override fun onServiceConnected(componentName: ComponentName?, binder: IBinder?) { + val player = player.get() ?: return + + try { + val activity = NitroModules.Companion.applicationContext?.currentActivity ?: run { + Log.e("VideoPlaybackServiceConnection", "Activity is null") + return + } + + serviceBinder = binder as? VideoPlaybackServiceBinder + // Only register when the player actually needs background service/notification + if (player.playInBackground || player.showNotificationControls) { + serviceBinder?.service?.registerPlayer(player, activity.javaClass) + } + } catch (err: Exception) { + Log.e("VideoPlaybackServiceConnection", "Could not bind to playback service", err) + } + } + + override fun onServiceDisconnected(componentName: ComponentName?) { + player.get()?.let { + unregisterPlayer(it) + } + serviceBinder = null + } + + override fun onNullBinding(componentName: ComponentName?) { + Log.e( + "VideoPlaybackServiceConnection", + "Could not bind to playback service - there can be issues with background playback" + + "and notification controls" + ) + } + + fun unregisterPlayer(player: HybridVideoPlayer) { + try { + if (serviceBinder?.service != null) { + serviceBinder?.service?.unregisterPlayer(player) + } + } catch (_: Exception) {} + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/PictureInPictureUtils.kt b/android/src/main/java/com/twg/video/core/utils/PictureInPictureUtils.kt new file mode 100644 index 00000000..b9596afa --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/PictureInPictureUtils.kt @@ -0,0 +1,129 @@ +package com.twg.video.core.utils + +import android.app.PictureInPictureParams +import android.content.pm.PackageManager +import android.graphics.Rect +import android.os.Build +import android.util.Log +import android.util.Rational +import android.view.View +import androidx.annotation.OptIn +import androidx.annotation.RequiresApi +import androidx.media3.common.util.UnstableApi +import com.margelo.nitro.NitroModules +import com.twg.video.view.VideoView + +@OptIn(UnstableApi::class) +object PictureInPictureUtils { + private const val TAG = "PictureInPictureUtils" + + fun canEnterPictureInPicture(): Boolean { + val applicationContent = NitroModules.applicationContext + val currentActivity = applicationContent?.currentActivity + return currentActivity?.packageManager?.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) == true + } + + @RequiresApi(Build.VERSION_CODES.O) + fun createPictureInPictureParams(videoView: VideoView): PictureInPictureParams { + val builder = PictureInPictureParams.Builder() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && videoView.autoEnterPictureInPicture) { + builder.setAutoEnterEnabled(videoView.autoEnterPictureInPicture) + } + + return builder + .setAspectRatio(calculateAspectRatio(videoView.playerView)) + .setSourceRectHint(calculateSourceRectHint(videoView.playerView)) + .build() + } + + @RequiresApi(Build.VERSION_CODES.O) + fun createDisabledPictureInPictureParams(videoView: VideoView): PictureInPictureParams { + val defaultParams = PictureInPictureParams.Builder() + .setAspectRatio(null) // Clear aspect ratio + .setSourceRectHint(null) // Clear source rect hint + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + defaultParams.setAutoEnterEnabled(false) + } + + return defaultParams.build() + } + + fun calculateAspectRatio(view: View): Rational { + // AspectRatio for PIP must be between 2.39:1 and 1:2.39 + // see: https://developer.android.com/reference/android/app/PictureInPictureParams.Builder#setAspectRatio(android.util.Rational) + + val maximumAspectRatio = Rational(239, 100) + val minimumAspectRatio = Rational(100, 239) + + val currentAspectRatio = Rational(view.width, view.height) + + return when { + currentAspectRatio > maximumAspectRatio -> maximumAspectRatio + currentAspectRatio < minimumAspectRatio -> minimumAspectRatio + else -> currentAspectRatio + } + } + + fun calculateSourceRectHint(view: View): Rect { + // Get the visible rectangle of view in screen coordinates + val visibleRect = Rect() + view.getGlobalVisibleRect(visibleRect) + + // Get the Y position of view on the screen + val locationOnScreen = IntArray(2) + view.getLocationOnScreen(locationOnScreen) + val yOnScreen = locationOnScreen[1] + + // Preserve the original height + val height = visibleRect.height() + + // Set the new top and bottom based on the view's screen position + visibleRect.top = yOnScreen + visibleRect.bottom = yOnScreen + height + + return visibleRect + } + + fun safeSetPictureInPictureParams(params: PictureInPictureParams) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + val currentActivity = NitroModules.applicationContext?.currentActivity + currentActivity?.setPictureInPictureParams(params) + Log.d(TAG, "Successfully set PiP params") + } catch (e: Exception) { + Log.w(TAG, "Failed to set PiP params - PiP may not be enabled in manifest", e) + // Ignore: We cannot check if user has added support for PIP in manifest + // so we need to catch error if he did not add it. + } + } + } + + @RequiresApi(Build.VERSION_CODES.O) + fun safeEnterPictureInPictureMode(params: PictureInPictureParams): Boolean { + return try { + val currentActivity = NitroModules.applicationContext?.currentActivity + val result = currentActivity?.enterPictureInPictureMode(params) ?: false + Log.d(TAG, "PiP enter result: $result") + result + } catch (e: Exception) { + Log.e(TAG, "Failed to enter PiP mode", e) + false + } + } + + fun isCurrentlyInPictureInPictureMode(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + val currentActivity = NitroModules.applicationContext?.currentActivity + currentActivity?.isInPictureInPictureMode == true + } catch (e: Exception) { + Log.w(TAG, "Failed to check PiP mode status", e) + false + } + } else { + false + } + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/SmallVideoPlayerOptimizer.kt b/android/src/main/java/com/twg/video/core/utils/SmallVideoPlayerOptimizer.kt new file mode 100644 index 00000000..dfcba4ed --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/SmallVideoPlayerOptimizer.kt @@ -0,0 +1,157 @@ +package com.twg.video.core.utils + +import android.content.Context +import android.util.Log +import android.view.View +import android.view.ViewGroup +import android.widget.ImageButton +import androidx.media3.ui.PlayerView + +object SmallVideoPlayerOptimizer { + + fun isSmallVideoPlayer(playerView: PlayerView): Boolean { + // Check if the PlayerView dimensions are small enough to warrant optimizations + val width = playerView.width + val height = playerView.height + + // If view hasn't been measured yet, use layout params or return false + if (width <= 0 || height <= 0) { + val layoutParams = playerView.layoutParams + if (layoutParams != null) { + // Convert any specific dimensions to pixels if needed + val widthPx = if (layoutParams.width > 0) layoutParams.width else playerView.measuredWidth + val heightPx = if (layoutParams.height > 0) layoutParams.height else playerView.measuredHeight + + if (widthPx <= 0 || heightPx <= 0) return false + + return isSmallDimensions(widthPx, heightPx, playerView.context) + } + return false + } + + return isSmallDimensions(width, height, playerView.context) + } + + private fun isSmallDimensions(widthPx: Int, heightPx: Int, context: Context): Boolean { + val density = context.resources.displayMetrics.density + val widthDp = widthPx / density + val heightDp = heightPx / density + + // Consider the video player "small" if width <= 400dp or height <= 300dp + // These thresholds are more appropriate for actual video player sizes + return widthDp <= 400 || heightDp <= 300 + } + + fun applyOptimizations( + playerView: PlayerView, + context: Context, + isFullscreen: Boolean = false + ) { + playerView.post { + try { + if (isFullscreen) { + // For fullscreen mode, use system defaults - no custom optimizations + // Let ExoPlayer use its default controller timeout and styling + return@post + } + + // Only apply optimizations if the video player itself is small + if (!isSmallVideoPlayer(playerView)) { + return@post + } + + val controllerView = playerView.findViewById(androidx.media3.ui.R.id.exo_controller) + controllerView?.let { controller -> + optimizeControlElementsForSmallPlayer(controller, context) + } + } catch (e: Exception) { + Log.w("ReactNativeVideo", "Error applying small video player optimizations: ${e.message}") + } + } + } + + private fun optimizeControlElementsForSmallPlayer( + controller: ViewGroup, + context: Context + ) { + val density = context.resources.displayMetrics.density + val primaryButtonSize = (48 * density).toInt() + val secondaryButtonSize = (44 * density).toInt() + + optimizeButtons(controller, primaryButtonSize, secondaryButtonSize) + optimizeProgressBar(controller, context) + optimizeTextElements(controller) + } + + private fun optimizeButtons( + container: ViewGroup, + primarySize: Int, + secondarySize: Int + ) { + for (i in 0 until container.childCount) { + val child = container.getChildAt(i) + when (child) { + is ImageButton -> { + val buttonSize = when (child.id) { + androidx.media3.ui.R.id.exo_play_pause -> primarySize + androidx.media3.ui.R.id.exo_fullscreen -> primarySize + androidx.media3.ui.R.id.exo_settings -> primarySize + androidx.media3.ui.R.id.exo_rew -> secondarySize + androidx.media3.ui.R.id.exo_ffwd -> secondarySize + androidx.media3.ui.R.id.exo_subtitle -> secondarySize + androidx.media3.ui.R.id.exo_prev -> secondarySize + androidx.media3.ui.R.id.exo_next -> secondarySize + else -> secondarySize + } + + val params = child.layoutParams + params.width = buttonSize + params.height = buttonSize + child.layoutParams = params + + // Hide less essential buttons on small video players + when (child.id) { + androidx.media3.ui.R.id.exo_shuffle, + androidx.media3.ui.R.id.exo_repeat_toggle, + androidx.media3.ui.R.id.exo_vr -> { + child.visibility = View.GONE + } + } + } + is ViewGroup -> { + optimizeButtons(child, primarySize, secondarySize) + } + } + } + } + + private fun optimizeProgressBar( + controller: ViewGroup, + context: Context + ) { + val progressContainer = controller.findViewById(androidx.media3.ui.R.id.exo_progress) + progressContainer?.let { progress -> + val params = progress.layoutParams as? ViewGroup.MarginLayoutParams + params?.let { + it.height = (4 * context.resources.displayMetrics.density).toInt() + progress.layoutParams = it + } + } + } + + private fun optimizeTextElements( + controller: ViewGroup + ) { + val timeContainer = controller.findViewById(androidx.media3.ui.R.id.exo_time) + timeContainer?.let { time -> + val positionView = time.findViewById(androidx.media3.ui.R.id.exo_position) + val durationView = time.findViewById(androidx.media3.ui.R.id.exo_duration) + + listOf(positionView, durationView).forEach { textView -> + if (textView is android.widget.TextView) { + textView.textSize = 12f + } + } + } + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/TextTrackUtils.kt b/android/src/main/java/com/twg/video/core/utils/TextTrackUtils.kt new file mode 100644 index 00000000..5d658626 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/TextTrackUtils.kt @@ -0,0 +1,175 @@ +package com.twg.video.core.utils + +import androidx.media3.common.C +import androidx.media3.common.TrackSelectionOverride +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlayer +import com.margelo.nitro.video.HybridVideoPlayerSourceSpec +import com.margelo.nitro.video.TextTrack + +@UnstableApi +object TextTrackUtils { + fun getAvailableTextTracks(player: ExoPlayer, source: HybridVideoPlayerSourceSpec): Array { + return Threading.runOnMainThreadSync { + val tracks = mutableListOf() + val currentTracks = player.currentTracks + var globalTrackIndex = 0 + + // Get all text tracks from the current player tracks (includes both built-in and external) + for (trackGroup in currentTracks.groups) { + if (trackGroup.type == C.TRACK_TYPE_TEXT) { + for (trackIndex in 0 until trackGroup.length) { + val format = trackGroup.getTrackFormat(trackIndex) + val trackId = format.id ?: "text-$globalTrackIndex" + val label = format.label ?: "Unknown ${globalTrackIndex + 1}" + val language = format.language + val isSelected = trackGroup.isTrackSelected(trackIndex) + + // Determine if this is an external track by checking if it matches external subtitle labels + val isExternal = source.config.externalSubtitles?.any { subtitle -> + label.contains(subtitle.label, ignoreCase = true) + } == true + + val finalTrackId = if (isExternal) "external-$globalTrackIndex" else trackId + + tracks.add( + TextTrack( + id = finalTrackId, + label = label, + language = language, + selected = isSelected + ) + ) + + globalTrackIndex++ + } + } + } + + tracks.toTypedArray() + } + } + + fun selectTextTrack( + player: ExoPlayer, + textTrack: TextTrack?, + source: HybridVideoPlayerSourceSpec, + onTrackChange: (TextTrack?) -> Unit, + ): Int? { + return Threading.runOnMainThreadSync { + val trackSelector = player.trackSelectionParameters.buildUpon() + + // If textTrack is null, disable all text tracks + if (textTrack == null) { + trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true) + player.trackSelectionParameters = trackSelector.build() + onTrackChange(null) + return@runOnMainThreadSync null + } + + if (textTrack.id.isEmpty()) { + // Disable all text tracks + trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true) + player.trackSelectionParameters = trackSelector.build() + onTrackChange(null) + return@runOnMainThreadSync null + } + + val currentTracks = player.currentTracks + var trackFound = false + var selectedExternalTrackIndex: Int? = null + var globalTrackIndex = 0 + + // Find and select the specific text track + for (trackGroup in currentTracks.groups) { + if (trackGroup.type == C.TRACK_TYPE_TEXT) { + for (trackIndex in 0 until trackGroup.length) { + val format = trackGroup.getTrackFormat(trackIndex) + val currentTrackId = format.id ?: "text-$globalTrackIndex" + val label = format.label ?: "Unknown ${globalTrackIndex + 1}" + + // Check if this matches our target track (either by original ID or by external ID) + val isExternal = source.config.externalSubtitles?.any { subtitle -> + label.contains(subtitle.label, ignoreCase = true) + } == true + + val finalTrackId = + if (isExternal) "external-$globalTrackIndex" else currentTrackId + + if (finalTrackId == textTrack.id) { + // Enable this specific track + trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, false) + trackSelector.setOverrideForType( + TrackSelectionOverride( + trackGroup.mediaTrackGroup, + listOf(trackIndex) + ) + ) + + // Update selection state + selectedExternalTrackIndex = if (isExternal) { + globalTrackIndex + } else { + null + } + + onTrackChange(textTrack) + trackFound = true + break + } + + globalTrackIndex++ + } + if (trackFound) { + break + } + } + } + + // Apply the track selection parameters regardless of whether we found a track + player.trackSelectionParameters = trackSelector.build() + selectedExternalTrackIndex + } + } + + fun getSelectedTrack(player: ExoPlayer, source: HybridVideoPlayerSourceSpec): TextTrack? { + return Threading.runOnMainThreadSync { + val currentTracks = player.currentTracks + var globalTrackIndex = 0 + + // Find the currently selected text track + for (trackGroup in currentTracks.groups) { + if (trackGroup.type == C.TRACK_TYPE_TEXT && trackGroup.isSelected) { + for (trackIndex in 0 until trackGroup.length) { + if (trackGroup.isTrackSelected(trackIndex)) { + val format = trackGroup.getTrackFormat(trackIndex) + val trackId = format.id ?: "text-$globalTrackIndex" + val label = format.label ?: "Unknown ${globalTrackIndex + 1}" + val language = format.language + + // Determine if this is an external track by checking if it matches external subtitle labels + val isExternal = source.config.externalSubtitles?.any { subtitle -> + label.contains(subtitle.label, ignoreCase = true) + } == true + + val finalTrackId = if (isExternal) "external-$globalTrackIndex" else trackId + + return@runOnMainThreadSync TextTrack( + id = finalTrackId, + label = label, + language = language, + selected = true + ) + } + globalTrackIndex++ + } + } else if (trackGroup.type == C.TRACK_TYPE_TEXT) { + // Still need to increment global index for non-selected text track groups + globalTrackIndex += trackGroup.length + } + } + + null + } + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/Threading.kt b/android/src/main/java/com/twg/video/core/utils/Threading.kt new file mode 100644 index 00000000..21f0e6d2 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/Threading.kt @@ -0,0 +1,75 @@ +package com.twg.video.core.utils + +import android.os.Handler +import android.os.Looper +import com.margelo.nitro.NitroModules +import com.twg.video.core.LibraryError +import java.util.concurrent.Callable +import java.util.concurrent.FutureTask +import kotlin.reflect.KProperty + +object Threading { + @JvmStatic + fun runOnMainThread(action: () -> Unit) { + // We are already on the main thread, run and return + if (Looper.myLooper() == Looper.getMainLooper()) { + action() + return + } + + // If application context is null, throw an error + if (NitroModules.applicationContext == null) { + throw LibraryError.ApplicationContextNotFound + } + + // Post the action to the main thread + Handler(NitroModules.applicationContext!!.mainLooper).post { + action() + } + } + + @JvmStatic + fun runOnMainThreadSync(action: Callable): T { + return if (Looper.myLooper() == Looper.getMainLooper()) { + // Already on the main thread, run and return the result + action.call() + } else { + // Post the action to the main thread and wait for the result + val futureTask = FutureTask(action) + Handler(Looper.getMainLooper()).post(futureTask) + futureTask.get() + } + } + + class MainThreadProperty( + private val get: Reference.() -> Type, + private val set: (Reference.(Type) -> Unit)? = null + ) { + operator fun getValue(thisRef: Reference, property: KProperty<*>): Type { + return runOnMainThreadSync { thisRef.get() } + } + + operator fun setValue(thisRef: Reference, property: KProperty<*>, value: Type) { + val setter = set ?: throw IllegalStateException("Property ${property.name} is read-only") + runOnMainThread { thisRef.setter(value) } + } + } + + /** + * Read-only property that runs on main thread + * @param get The getter function that runs synchronously on the main thread. + * + * @throws [IllegalStateException] if there will be a write operation + */ + fun Reference.mainThreadProperty(get: Reference.() -> T) = MainThreadProperty(get) + + /** + * Read-only property that runs on main thread + * @param get The getter function that runs synchronously on the main thread + * @param set The setter function that runs asynchronously on the main thread + */ + fun Reference.mainThreadProperty( + get: Reference.() -> T, + set: Reference.(T) -> Unit + ) = MainThreadProperty(get, set) +} diff --git a/android/src/main/java/com/twg/video/core/utils/VideoFileHelper.kt b/android/src/main/java/com/twg/video/core/utils/VideoFileHelper.kt new file mode 100644 index 00000000..c12e97db --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/VideoFileHelper.kt @@ -0,0 +1,51 @@ +package com.twg.video.core.utils + +import android.Manifest +import android.content.pm.PackageManager +import android.net.Uri +import android.webkit.URLUtil +import com.margelo.nitro.NitroModules +import com.twg.video.core.SourceError +import java.io.File +import java.net.URL +import java.net.URLConnection + +object VideoFileHelper { + private fun hasReadPermission(): Boolean { + return NitroModules.applicationContext?.checkSelfPermission( + Manifest.permission.READ_EXTERNAL_STORAGE + ) == PackageManager.PERMISSION_GRANTED + } + + fun validateReadPermission(uri: String) { + if (!hasReadPermission()) throw SourceError.MissingReadFilePermission(uri) + + val file = File(Uri.parse(uri).path ?: throw SourceError.InvalidUri(uri)) + + // Check if file exists and is readable + if (!file.exists()) throw SourceError.FileDoesNotExist(uri) + + // Check if file is readable + if (!file.canRead()) throw SourceError.MissingReadFilePermission(uri) + } + + fun getFileSizeFromUri(uri: String): Long { + return try { + when { + URLUtil.isFileUrl(uri) -> { + validateReadPermission(uri) + val file = File(Uri.parse(uri).path ?: return -1) + if (file.exists()) file.length() else -1 + } + URLUtil.isNetworkUrl(uri) -> { + val connection: URLConnection = URL(uri).openConnection() + connection.connect() + connection.contentLength.toLong() + } + else -> -1 + } + } catch (e: Exception) { + -1 + } + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/VideoInformationUtils.kt b/android/src/main/java/com/twg/video/core/utils/VideoInformationUtils.kt new file mode 100644 index 00000000..90a63d77 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/VideoInformationUtils.kt @@ -0,0 +1,67 @@ +package com.twg.video.core.utils + +import android.media.MediaFormat +import android.media.MediaMetadataRetriever +import android.net.Uri +import android.os.Build +import android.webkit.URLUtil +import com.margelo.nitro.video.VideoInformation +import androidx.core.net.toUri + +object VideoInformationUtils { + fun fromUri(uri: String, headers: Map = emptyMap()): VideoInformation { + val retriever = MediaMetadataRetriever() + + when { + URLUtil.isFileUrl(uri) -> { + retriever.setDataSource(uri.toUri().path) + } + else -> { + retriever.setDataSource(uri, headers) + } + } + + // Get dimensions + val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toDoubleOrNull() ?: Double.NaN + val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toDoubleOrNull() ?: Double.NaN + + // Get duration in milliseconds, convert to long + val duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: -1L + + // If we have some valid info, but there is no duration it might be live + val isLive = !width.isNaN() && !height.isNaN() && duration <= 0 + + // Get bitrate + val bitrate = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)?.toDoubleOrNull() ?: Double.NaN + + // Get rotation + val rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toIntOrNull() ?: 0 + + // Check for HDR by looking at color transfer (API 30+) + val isHDR = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val colorTransfer = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COLOR_TRANSFER)?.toIntOrNull() + colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084 || colorTransfer == MediaFormat.COLOR_TRANSFER_HLG + } else { + false + } + + // Clean up + retriever.release() + + // Get file size + val fileSize = VideoFileHelper.getFileSizeFromUri(uri) + + val videoInfo = VideoInformation( + bitrate = bitrate, + width = width, + height = height, + duration = duration, + fileSize = fileSize, + isHDR = isHDR, + isLive = isLive, + orientation = VideoOrientationUtils.fromWHR(width.toInt(), height.toInt(), rotation) + ) + + return videoInfo + } +} diff --git a/android/src/main/java/com/twg/video/core/utils/VideoOrientationUtils.kt b/android/src/main/java/com/twg/video/core/utils/VideoOrientationUtils.kt new file mode 100644 index 00000000..7ebc12f9 --- /dev/null +++ b/android/src/main/java/com/twg/video/core/utils/VideoOrientationUtils.kt @@ -0,0 +1,30 @@ +package com.twg.video.core.utils + +import com.margelo.nitro.video.VideoOrientation + +object VideoOrientationUtils { + fun fromWHR(width: Int?, height: Int?, rotation: Int?): VideoOrientation { + if (width == 0 || height == 0 || height == null || width == null) return VideoOrientation.UNKNOWN + + if (width == height) return VideoOrientation.SQUARE + + // Check if video is portrait or landscape using natural size + val isNaturalSizePortrait = height > width + + // If rotation is not available, use natural size to determine orientation + if (rotation == null) { + return if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT + } + + // Normalize rotation to 0-360 range + val normalizedRotation = ((rotation % 360) + 360) % 360 + + return when (normalizedRotation) { + 0 -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT + 90 -> VideoOrientation.PORTRAIT + 180 -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT_UPSIDE_DOWN else VideoOrientation.LANDSCAPE_LEFT + 270 -> VideoOrientation.PORTRAIT_UPSIDE_DOWN + else -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT + } + } +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayer.kt b/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayer.kt new file mode 100644 index 00000000..fb9d4e9f --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayer.kt @@ -0,0 +1,606 @@ +package com.margelo.nitro.video + +import android.os.Handler +import android.os.Looper +import android.util.Log +import androidx.media3.common.C +import androidx.media3.common.Metadata +import androidx.media3.common.PlaybackException +import androidx.media3.common.PlaybackParameters +import androidx.media3.common.Player +import androidx.media3.common.Tracks +import androidx.media3.common.text.CueGroup +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.DefaultLoadControl +import androidx.media3.exoplayer.DefaultRenderersFactory +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.analytics.AnalyticsListener +import androidx.media3.exoplayer.upstream.DefaultAllocator +import androidx.media3.extractor.metadata.emsg.EventMessage +import androidx.media3.extractor.metadata.id3.Id3Frame +import androidx.media3.extractor.metadata.id3.TextInformationFrame +import androidx.media3.ui.PlayerView +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.NitroModules +import com.margelo.nitro.core.Promise +import com.twg.video.core.LibraryError +import com.twg.video.core.PlayerError +import com.twg.video.core.VideoManager +import com.twg.video.core.extensions.startService +import com.twg.video.core.extensions.stopService +import com.twg.video.core.player.OnAudioFocusChangedListener +import com.twg.video.core.recivers.AudioBecomingNoisyReceiver +import com.twg.video.core.services.playback.VideoPlaybackService +import com.twg.video.core.services.playback.VideoPlaybackServiceConnection +import com.twg.video.core.utils.TextTrackUtils +import com.twg.video.core.utils.Threading.mainThreadProperty +import com.twg.video.core.utils.Threading.runOnMainThread +import com.twg.video.core.utils.Threading.runOnMainThreadSync +import com.twg.video.core.utils.VideoOrientationUtils +import com.twg.video.view.VideoView +import java.lang.ref.WeakReference +import kotlin.math.max + +@UnstableApi +@DoNotStrip +class HybridVideoPlayer() : HybridVideoPlayerSpec() { + override lateinit var source: HybridVideoPlayerSourceSpec + override var eventEmitter = HybridVideoPlayerEventEmitter() + set(value) { + if (field != value) { + audioFocusChangedListener.setEventEmitter(value) + audioBecomingNoisyReceiver.setEventEmitter(value) + } + field = value + } + + private var allocator: DefaultAllocator? = null + private var context = NitroModules.applicationContext + ?: run { + throw LibraryError.ApplicationContextNotFound + } + + lateinit var player: ExoPlayer + var loadedWithSource = false + private var currentPlayerView: WeakReference? = null + + var wasAutoPaused = false + + // Buffer Config + private var bufferConfig: BufferConfig? = null + get() = source.config.bufferConfig + + // Time updates + private val progressHandler = Handler(Looper.getMainLooper()) + private var progressRunnable: Runnable? = null + + // Listeners + private val audioFocusChangedListener = OnAudioFocusChangedListener() + private val audioBecomingNoisyReceiver = AudioBecomingNoisyReceiver() + + // Service Connection + private val videoPlaybackServiceConnection = VideoPlaybackServiceConnection(WeakReference(this)) + + // Text track selection state + private var selectedExternalTrackIndex: Int? = null + + private companion object { + const val PROGRESS_UPDATE_INTERVAL_MS = 250L + private const val TAG = "HybridVideoPlayer" + private const val DEFAULT_MIN_BUFFER_DURATION_MS = 5000 + private const val DEFAULT_MAX_BUFFER_DURATION_MS = 10000 + private const val DEFAULT_BUFFER_FOR_PLAYBACK_DURATION_MS = 1000 + private const val DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_DURATION_MS = 2000 + private const val DEFAULT_BACK_BUFFER_DURATION_MS = 0 + } + + override var status: VideoPlayerStatus = VideoPlayerStatus.IDLE + set(value) { + if (field != value) { + eventEmitter.onStatusChange(value) + } + field = value + } + + override var showNotificationControls: Boolean = false + set(value) { + val wasRunning = (field || playInBackground) + val shouldRun = (value || playInBackground) + + if (shouldRun && !wasRunning) { + VideoPlaybackService.startService(context, videoPlaybackServiceConnection) + } + if (!shouldRun && wasRunning) { + VideoPlaybackService.stopService(this, videoPlaybackServiceConnection) + } + + field = value + // Inform service to refresh notification/session layout + try { videoPlaybackServiceConnection.serviceBinder?.service?.updatePlayerPreferences(this) } catch (_: Exception) {} + } + + // Player Properties + override var currentTime: Double by mainThreadProperty( + get = { player.currentPosition.toDouble() / 1000.0 }, + set = { value -> runOnMainThread { player.seekTo((value * 1000).toLong()) } } + ) + + // volume defined by user + var userVolume: Double = 1.0 + + override var volume: Double by mainThreadProperty( + get = { player.volume.toDouble() }, + set = { value -> + userVolume = value + player.volume = value.toFloat() + } + ) + + override val duration: Double by mainThreadProperty( + get = { + val duration = player.duration + return@mainThreadProperty if (duration == C.TIME_UNSET) Double.NaN else duration.toDouble() / 1000.0 + } + ) + + override var loop: Boolean by mainThreadProperty( + get = { + player.repeatMode == Player.REPEAT_MODE_ONE + }, + set = { value -> + player.repeatMode = if (value) Player.REPEAT_MODE_ONE else Player.REPEAT_MODE_OFF + } + ) + + override var muted: Boolean by mainThreadProperty( + get = { + val playerVolume = player.volume.toDouble() + return@mainThreadProperty playerVolume == 0.0 + }, + set = { value -> + if (value) { + userVolume = volume + player.volume = 0f + } else { + player.volume = userVolume.toFloat() + } + eventEmitter.onVolumeChange(onVolumeChangeData( + volume = player.volume.toDouble(), + muted = muted + )) + } + ) + + override var rate: Double by mainThreadProperty( + get = { player.playbackParameters.speed.toDouble() }, + set = { value -> + player.playbackParameters = player.playbackParameters.withSpeed(value.toFloat()) + } + ) + + override var mixAudioMode: MixAudioMode = MixAudioMode.AUTO + set(value) { + VideoManager.audioFocusManager.requestAudioFocusUpdate() + field = value + } + + // iOS only property + override var ignoreSilentSwitchMode: IgnoreSilentSwitchMode = IgnoreSilentSwitchMode.AUTO + + override var playInBackground: Boolean = false + set(value) { + val shouldRun = (value || showNotificationControls) + val wasRunning = (field || showNotificationControls) + + if (shouldRun && !wasRunning) { + VideoPlaybackService.startService(context, videoPlaybackServiceConnection) + } + if (!shouldRun && wasRunning) { + VideoPlaybackService.stopService(this, videoPlaybackServiceConnection) + } + field = value + // Update preferences to refresh notifications/registration + try { videoPlaybackServiceConnection.serviceBinder?.service?.updatePlayerPreferences(this) } catch (_: Exception) {} + } + + override var playWhenInactive: Boolean = false + + override var isPlaying: Boolean by mainThreadProperty( + get = { player.isPlaying == true } + ) + + private fun initializePlayer() { + if (NitroModules.applicationContext == null) { + throw LibraryError.ApplicationContextNotFound + } + + val hybridSource = source as? HybridVideoPlayerSource ?: throw PlayerError.InvalidSource + + // Initialize the allocator + allocator = DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE) + + // Create a LoadControl with the allocator + val loadControl = DefaultLoadControl.Builder() + .setAllocator(allocator!!) + .setBufferDurationsMs( + bufferConfig?.minBufferMs?.toInt() ?: DEFAULT_MIN_BUFFER_DURATION_MS, // minBufferMs + bufferConfig?.maxBufferMs?.toInt() ?: DEFAULT_MAX_BUFFER_DURATION_MS, // maxBufferMs + bufferConfig?.bufferForPlaybackMs?.toInt() + ?: DEFAULT_BUFFER_FOR_PLAYBACK_DURATION_MS, // bufferForPlaybackMs + bufferConfig?.bufferForPlaybackAfterRebufferMs?.toInt() + ?: DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_DURATION_MS // bufferForPlaybackAfterRebufferMs + ) + .setBackBuffer( + bufferConfig?.backBufferDurationMs?.toInt() + ?: DEFAULT_BACK_BUFFER_DURATION_MS, // backBufferDurationMs, + false // retainBackBufferFromKeyframe + ) + .build() + + val renderersFactory = DefaultRenderersFactory(context) + .forceEnableMediaCodecAsynchronousQueueing() + .setEnableDecoderFallback(true) + + // Build the player with the LoadControl + player = ExoPlayer.Builder(context) + .setLoadControl(loadControl) + .setLooper(Looper.getMainLooper()) + .setRenderersFactory(renderersFactory) + .build() + + loadedWithSource = true + + player.addListener(playerListener) + player.addAnalyticsListener(analyticsListener) + player.setMediaSource(hybridSource.mediaSource) + + // Emit onLoadStart + val sourceType = if (hybridSource.uri.startsWith("http")) SourceType.NETWORK else SourceType.LOCAL + eventEmitter.onLoadStart(onLoadStartData(sourceType = sourceType, source = hybridSource)) + status = VideoPlayerStatus.LOADING + startProgressUpdates() + } + + override fun initialize(): Promise { + return Promise.async { + return@async runOnMainThreadSync { + initializePlayer() + player.prepare() + } + } + } + + constructor(source: HybridVideoPlayerSource) : this() { + this.source = source + + runOnMainThread { + if (source.config.initializeOnCreation == true) { + initializePlayer() + player.prepare() + } else { + player = ExoPlayer.Builder(context).build() + } + } + + VideoManager.registerPlayer(this) + } + + override fun play() { + runOnMainThread { + player.play() + } + } + + override fun pause() { + runOnMainThread { + player.pause() + } + } + + override fun seekBy(time: Double) { + currentTime = (currentTime + time).coerceIn(0.0, duration) + } + + override fun seekTo(time: Double) { + currentTime = time.coerceIn(0.0, duration) + } + + override fun replaceSourceAsync(source: HybridVideoPlayerSourceSpec?): Promise { + return Promise.async { + if (source == null) { + release() + return@async + } + + val hybridSource = source as? HybridVideoPlayerSource ?: throw PlayerError.InvalidSource + + runOnMainThreadSync { + // Update source + this.source = source + player.setMediaSource(hybridSource.mediaSource) + + // Prepare player + player.prepare() + } + } + } + + override fun preload(): Promise { + return Promise.async { + runOnMainThreadSync { + if (!loadedWithSource) { + initializePlayer() + } + + if (player.playbackState != Player.STATE_IDLE) { + return@runOnMainThreadSync + } + + player.prepare() + } + } + } + + private fun release() { + if (playInBackground || showNotificationControls) { + VideoPlaybackService.stopService(this, videoPlaybackServiceConnection) + } + + VideoManager.unregisterPlayer(this) + stopProgressUpdates() + loadedWithSource = false + runOnMainThread { + player.removeListener(playerListener) + player.removeAnalyticsListener(analyticsListener) + player.release() // Release player + + // Clean Listeners + audioFocusChangedListener.removeEventEmitter() + audioBecomingNoisyReceiver.removeEventEmitter() + + // Update status + status = VideoPlayerStatus.IDLE + } + } + + fun movePlayerToVideoView(videoView: VideoView) { + VideoManager.addViewToPlayer(videoView, this) + + runOnMainThreadSync { + PlayerView.switchTargetView(player, currentPlayerView?.get(), videoView.playerView) + currentPlayerView = WeakReference(videoView.playerView) + } + } + + override fun dispose() { + release() + } + + override val memorySize: Long + get() = allocator?.totalBytesAllocated?.toLong() ?: 0L + + private fun startProgressUpdates() { + stopProgressUpdates() // Ensure no multiple runnables + progressRunnable = object : Runnable { + override fun run() { + if (player.playbackState != Player.STATE_IDLE && player.playbackState != Player.STATE_ENDED) { + val currentTimeSeconds = player.currentPosition / 1000.0 + val bufferedDurationSeconds = player.bufferedPosition / 1000.0 + // bufferDuration is the time from current time that is buffered. + val playableDurationFromNow = max(0.0, bufferedDurationSeconds - currentTimeSeconds) + + eventEmitter.onProgress( + onProgressData( + currentTime = currentTimeSeconds, + bufferDuration = playableDurationFromNow + ) + ) + progressHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS) + } + } + } + progressHandler.post(progressRunnable ?: return) + } + + private fun stopProgressUpdates() { + progressRunnable?.let { progressHandler.removeCallbacks(it) } + progressRunnable = null + } + + private val analyticsListener = object: AnalyticsListener { + override fun onBandwidthEstimate( + eventTime: AnalyticsListener.EventTime, + totalLoadTimeMs: Int, + totalBytesLoaded: Long, + bitrateEstimate: Long + ) { + val videoFormat = player.videoFormat + eventEmitter.onBandwidthUpdate( + BandwidthData( + bitrate = bitrateEstimate.toDouble(), + width = if (videoFormat != null) videoFormat.width.toDouble() else null, + height = if (videoFormat != null) videoFormat.height.toDouble() else null + ) + ) + } + } + + private val playerListener = object : Player.Listener { + override fun onPlaybackStateChanged(playbackState: Int) { + val isPlayingUpdate = player.isPlaying + val isBufferingUpdate = playbackState == Player.STATE_BUFFERING + + eventEmitter.onPlaybackStateChange( + onPlaybackStateChangeData( + isPlaying = isPlayingUpdate, + isBuffering = isBufferingUpdate + ) + ) + + when (playbackState) { + Player.STATE_IDLE -> { + status = VideoPlayerStatus.IDLE + eventEmitter.onBuffer(false) + } + Player.STATE_BUFFERING -> { + status = VideoPlayerStatus.LOADING + eventEmitter.onBuffer(true) + } + Player.STATE_READY -> { + status = VideoPlayerStatus.READYTOPLAY + eventEmitter.onBuffer(false) + + val generalVideoFormat = player.videoFormat + val currentTracks = player.currentTracks + + val selectedVideoTrackGroup = currentTracks.groups.find { group -> group.type == C.TRACK_TYPE_VIDEO && group.isSelected } + val selectedVideoTrackFormat = if (selectedVideoTrackGroup != null && selectedVideoTrackGroup.length > 0) { + selectedVideoTrackGroup.getTrackFormat(0) + } else { + null + } + + val width = selectedVideoTrackFormat?.width ?: generalVideoFormat?.width ?: 0 + val height = selectedVideoTrackFormat?.height ?: generalVideoFormat?.height ?: 0 + val rotationDegrees = selectedVideoTrackFormat?.rotationDegrees ?: generalVideoFormat?.rotationDegrees + + eventEmitter.onLoad( + onLoadData( + currentTime = player.currentPosition / 1000.0, + duration = if (player.duration == C.TIME_UNSET) Double.NaN else player.duration / 1000.0, + width = width.toDouble(), + height = height.toDouble(), + orientation = VideoOrientationUtils.fromWHR(width, height, rotationDegrees) + ) + ) + // If player becomes ready and is set to play, start progress updates + if (player.playWhenReady) { + startProgressUpdates() + } + + eventEmitter.onReadyToDisplay() + } + Player.STATE_ENDED -> { + status = VideoPlayerStatus.IDLE // Or a specific 'COMPLETED' status if you add one + eventEmitter.onEnd() + eventEmitter.onBuffer(false) + stopProgressUpdates() + } + } + } + + override fun onIsPlayingChanged(isPlaying: Boolean) { + super.onIsPlayingChanged(isPlaying) + eventEmitter.onPlaybackStateChange( + onPlaybackStateChangeData( + isPlaying = isPlaying, + isBuffering = player.playbackState == Player.STATE_BUFFERING + ) + ) + if (isPlaying) { + VideoManager.setLastPlayedPlayer(this@HybridVideoPlayer) + startProgressUpdates() + } else { + if (player.playbackState == Player.STATE_ENDED || player.playbackState == Player.STATE_IDLE) { + stopProgressUpdates() + } + } + } + + override fun onPlayerError(error: PlaybackException) { + status = VideoPlayerStatus.ERROR + stopProgressUpdates() + } + + override fun onPositionDiscontinuity( + oldPosition: Player.PositionInfo, + newPosition: Player.PositionInfo, + reason: Int + ) { + if (reason == Player.DISCONTINUITY_REASON_SEEK || reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT) { + eventEmitter.onSeek(newPosition.positionMs / 1000.0) + } + // Update progress immediately after a discontinuity if needed by your logic + val currentTimeSeconds = newPosition.positionMs / 1000.0 + val bufferedDurationSeconds = player.bufferedPosition / 1000.0 + eventEmitter.onProgress( + onProgressData( + currentTime = currentTimeSeconds, + bufferDuration = max(0.0, bufferedDurationSeconds - currentTimeSeconds) + ) + ) + } + + override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) { + eventEmitter.onPlaybackRateChange(playbackParameters.speed.toDouble()) + } + + override fun onVolumeChanged(volume: Float) { + // We get here device volume changes, and if + // player is not muted we will sync it + if (!muted) { + this@HybridVideoPlayer.volume = volume.toDouble() + } + + VideoManager.audioFocusManager.requestAudioFocusUpdate() + eventEmitter.onVolumeChange(onVolumeChangeData( + volume = volume.toDouble(), + muted = muted + )) + } + + override fun onCues(cueGroup: CueGroup) { + val texts = cueGroup.cues.mapNotNull { it.text?.toString() } + if (texts.isNotEmpty()) { + eventEmitter.onTextTrackDataChanged(texts.toTypedArray()) + } + } + + override fun onMetadata(metadata: Metadata) { + val timedMetadataObjects = mutableListOf() + for (i in 0 until metadata.length()) { + val entry = metadata.get(i) + + when (entry) { + is Id3Frame -> { + var value = "" + + if (entry is TextInformationFrame) { + value = entry.values.first() + } + + timedMetadataObjects.add(TimedMetadataObject(entry.id, value)) + } + is EventMessage -> + timedMetadataObjects.add(TimedMetadataObject(entry.schemeIdUri, entry.value)) + else -> Log.d(TAG, "Unknown metadata: $entry") + } + } + if (timedMetadataObjects.isNotEmpty()) { + eventEmitter.onTimedMetadata(TimedMetadata(metadata = timedMetadataObjects.toTypedArray())) + } + } + + override fun onTracksChanged(tracks: Tracks) { + super.onTracksChanged(tracks) + } + } + + // MARK: - Text Track Management + + override fun getAvailableTextTracks(): Array { + return TextTrackUtils.getAvailableTextTracks(player, source) + } + + override fun selectTextTrack(textTrack: TextTrack?) { + selectedExternalTrackIndex = TextTrackUtils.selectTextTrack( + player = player, + textTrack = textTrack, + source = source, + onTrackChange = { track -> eventEmitter.onTrackChange(track) } + ) + } + + override val selectedTrack: TextTrack? + get() = TextTrackUtils.getSelectedTrack(player, source) +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayerFactory.kt b/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayerFactory.kt new file mode 100644 index 00000000..edf00a06 --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayerFactory.kt @@ -0,0 +1,16 @@ +package com.margelo.nitro.video + +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.facebook.proguard.annotations.DoNotStrip + +@DoNotStrip +class HybridVideoPlayerFactory(): HybridVideoPlayerFactorySpec() { + @OptIn(UnstableApi::class) + override fun createPlayer(source: HybridVideoPlayerSourceSpec): HybridVideoPlayerSpec { + return HybridVideoPlayer(source as HybridVideoPlayerSource) + } + + override val memorySize: Long + get() = 0 +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoplayereventemitter/HybridVideoPlayerEventEmitter.kt b/android/src/main/java/com/twg/video/hybrids/videoplayereventemitter/HybridVideoPlayerEventEmitter.kt new file mode 100644 index 00000000..56aa61de --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoplayereventemitter/HybridVideoPlayerEventEmitter.kt @@ -0,0 +1,41 @@ +package com.margelo.nitro.video + +class HybridVideoPlayerEventEmitter(): HybridVideoPlayerEventEmitterSpec() { + override var onAudioBecomingNoisy: () -> Unit = {} + + override var onAudioFocusChange: (Boolean) -> Unit = {} + + override var onBandwidthUpdate: (BandwidthData) -> Unit = {} + + override var onBuffer: (Boolean) -> Unit = {} + + override var onControlsVisibleChange: (Boolean) -> Unit = {} + + override var onEnd: () -> Unit = {} + + override var onExternalPlaybackChange: (Boolean) -> Unit = {} + + override var onLoad: (onLoadData) -> Unit = {} + + override var onLoadStart: (onLoadStartData) -> Unit = {} + + override var onPlaybackStateChange: (onPlaybackStateChangeData) -> Unit = {} + + override var onPlaybackRateChange: (Double) -> Unit = {} + + override var onProgress: (onProgressData) -> Unit = {} + + override var onReadyToDisplay: () -> Unit = {} + + override var onSeek: (Double) -> Unit = {} + + override var onTimedMetadata: (TimedMetadata) -> Unit = {} + + override var onTextTrackDataChanged: (Array) -> Unit = {} + + override var onTrackChange: (TextTrack?) -> Unit = {} + + override var onVolumeChange: (onVolumeChangeData) -> Unit = {} + + override var onStatusChange: (VideoPlayerStatus) -> Unit = {} +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSource.kt b/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSource.kt new file mode 100644 index 00000000..1f4e77a8 --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSource.kt @@ -0,0 +1,62 @@ +package com.margelo.nitro.video + +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.drm.DrmSessionManager +import androidx.media3.exoplayer.source.MediaSource +import com.margelo.nitro.NitroModules +import com.margelo.nitro.core.Promise +import com.twg.video.core.LibraryError +import com.twg.video.core.player.DRMManagerSpec +import com.twg.video.core.player.buildMediaSource +import com.twg.video.core.player.createMediaItemFromVideoConfig +import com.twg.video.core.plugins.PluginsRegistry +import com.twg.video.core.utils.VideoInformationUtils + +class HybridVideoPlayerSource(): HybridVideoPlayerSourceSpec() { + override lateinit var uri: String + override lateinit var config: NativeVideoConfig + + private lateinit var mediaItem: MediaItem + lateinit var mediaSource: MediaSource + + var drmManager: DRMManagerSpec? = null + + @UnstableApi + var drmSessionManager: DrmSessionManager? = null + + constructor(config: NativeVideoConfig) : this() { + this.uri = config.uri + this.config = config + + val overriddenSource = PluginsRegistry.shared.overrideSource(this) + + config.drm?.let { + drmManager = PluginsRegistry.shared.getDRMManager(this) + drmSessionManager = drmManager?.buildDrmSessionManager(it) + } + + this.mediaItem = createMediaItemFromVideoConfig( + overriddenSource + ) + + NitroModules.applicationContext?.let { + this.mediaSource = buildMediaSource( + context = it, + source = overriddenSource, + mediaItem + ) + } ?: run { + throw LibraryError.ApplicationContextNotFound + } + } + + override fun getAssetInformationAsync(): Promise { + return Promise.async { + return@async VideoInformationUtils.fromUri(uri, config.headers ?: emptyMap()) + } + } + + override val memorySize: Long + get() = 0 +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSourceFactory.kt b/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSourceFactory.kt new file mode 100644 index 00000000..090c4683 --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSourceFactory.kt @@ -0,0 +1,27 @@ +package com.margelo.nitro.video + +import com.facebook.proguard.annotations.DoNotStrip + +@DoNotStrip +class HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec() { + override fun fromUri(uri: String): HybridVideoPlayerSourceSpec { + val config = NativeVideoConfig( + uri = uri, + externalSubtitles = null, + drm = null, + headers = null, + bufferConfig = null, + metadata = null, + initializeOnCreation = true + ) + + return HybridVideoPlayerSource(config) + } + + override fun fromVideoConfig(config: NativeVideoConfig): HybridVideoPlayerSourceSpec { + return HybridVideoPlayerSource(config) + } + + override val memorySize: Long + get() = 0 +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt b/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt new file mode 100644 index 00000000..9042463e --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt @@ -0,0 +1,130 @@ +package com.margelo.nitro.video + +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.facebook.proguard.annotations.DoNotStrip +import com.twg.video.core.VideoManager +import com.twg.video.core.VideoViewError +import com.twg.video.core.utils.PictureInPictureUtils +import com.twg.video.core.utils.Threading + +@DoNotStrip +@OptIn(UnstableApi::class) +class HybridVideoViewViewManager(nitroId: Int): HybridVideoViewViewManagerSpec(), VideoViewEvents { + private var videoView = + VideoManager.getVideoViewWeakReferenceByNitroId(nitroId) ?: throw VideoViewError.ViewNotFound(nitroId) + + override var player: HybridVideoPlayerSpec? + get() { + return Threading.runOnMainThreadSync { return@runOnMainThreadSync videoView.get()?.hybridPlayer } + } + set(value) { + Threading.runOnMainThread { + videoView.get()?.hybridPlayer = value as? HybridVideoPlayer + } + } + + override fun canEnterPictureInPicture(): Boolean { + return PictureInPictureUtils.canEnterPictureInPicture() + } + + override fun enterFullscreen() { + videoView.get()?.enterFullscreen() + } + + override fun exitFullscreen() { + videoView.get()?.exitFullscreen() + } + + override fun enterPictureInPicture() { + Threading.runOnMainThread { + videoView.get()?.enterPictureInPicture() + } + } + + override fun exitPictureInPicture() { + Threading.runOnMainThread { + videoView.get()?.exitPictureInPicture() + } + } + + override var autoEnterPictureInPicture: Boolean + get() = videoView.get()?.autoEnterPictureInPicture == true + set(value) { + videoView.get()?.autoEnterPictureInPicture = value + } + + override var pictureInPicture: Boolean + get() = videoView.get()?.pictureInPictureEnabled == true + set(value) { + videoView.get()?.pictureInPictureEnabled = value + } + + override var controls: Boolean + get() = videoView.get()?.useController == true + set(value) { + videoView.get()?.useController = value + } + + override var resizeMode: ResizeMode + get() = videoView.get()?.resizeMode ?: ResizeMode.NONE + set(value) { + videoView.get()?.resizeMode = value + } + + override var keepScreenAwake: Boolean + get() = videoView.get()?.keepScreenAwake == true + set(value) { + videoView.get()?.keepScreenAwake = value + } + + override var surfaceType: SurfaceType + get() = videoView.get()?.surfaceType ?: SurfaceType.SURFACE + set(value) { + videoView.get()?.surfaceType = value + } + + // View callbacks + override var onPictureInPictureChange: ((Boolean) -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.onPictureInPictureChange = value + } + override var onFullscreenChange: ((Boolean) -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.onFullscreenChange = value + } + override var willEnterFullscreen: (() -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.willEnterFullscreen = value + } + override var willExitFullscreen: (() -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.willExitFullscreen = value + } + override var willEnterPictureInPicture: (() -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.willEnterPictureInPicture = value + } + override var willExitPictureInPicture: (() -> Unit)? = null + set(value) { + field = value + videoView.get()?.events?.willExitPictureInPicture = value + } + + override val memorySize: Long + get() = 0 +} + +interface VideoViewEvents { + var onPictureInPictureChange: ((Boolean) -> Unit)? + var onFullscreenChange: ((Boolean) -> Unit)? + var willEnterFullscreen: (() -> Unit)? + var willExitFullscreen: (() -> Unit)? + var willEnterPictureInPicture: (() -> Unit)? + var willExitPictureInPicture: (() -> Unit)? +} diff --git a/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManagerFactory.kt b/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManagerFactory.kt new file mode 100644 index 00000000..00865e63 --- /dev/null +++ b/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManagerFactory.kt @@ -0,0 +1,13 @@ +package com.margelo.nitro.video + +import com.facebook.proguard.annotations.DoNotStrip + +@DoNotStrip +class HybridVideoViewViewManagerFactory: HybridVideoViewViewManagerFactorySpec() { + override fun createViewManager(nitroId: Double): HybridVideoViewViewManagerSpec { + return HybridVideoViewViewManager(nitroId.toInt()) + } + + override val memorySize: Long + get() = 0 +} diff --git a/android/src/main/java/com/twg/video/react/VideoPackage.kt b/android/src/main/java/com/twg/video/react/VideoPackage.kt new file mode 100644 index 00000000..3bb566cb --- /dev/null +++ b/android/src/main/java/com/twg/video/react/VideoPackage.kt @@ -0,0 +1,26 @@ +package com.twg.video.react + +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + + +class VideoPackage : ReactPackage { + override fun createNativeModules(reactContext: ReactApplicationContext): List { + return emptyList() + } + + @OptIn(UnstableApi::class) + override fun createViewManagers(reactContext: ReactApplicationContext): List> { + return listOf(VideoViewViewManager()) + } + + companion object { + init { + System.loadLibrary("ReactNativeVideo") + } + } +} diff --git a/android/src/main/java/com/twg/video/react/VideoViewViewManager.kt b/android/src/main/java/com/twg/video/react/VideoViewViewManager.kt new file mode 100644 index 00000000..ed47dfb3 --- /dev/null +++ b/android/src/main/java/com/twg/video/react/VideoViewViewManager.kt @@ -0,0 +1,78 @@ +package com.twg.video.react + +import androidx.media3.common.util.UnstableApi +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.WritableMap +import com.facebook.react.common.MapBuilder +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.SimpleViewManager +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.ViewManagerDelegate +import com.facebook.react.uimanager.annotations.ReactProp +import com.facebook.react.uimanager.events.Event +import com.facebook.react.viewmanagers.RNCVideoViewManagerDelegate +import com.facebook.react.viewmanagers.RNCVideoViewManagerInterface +import com.twg.video.view.VideoView + +internal class NitroIdChange( + surfaceId: Int, + viewTag: Int, + val nitroId: Int +) : Event(surfaceId, viewTag) { + override fun getEventName() = EVENT_NAME + + override fun getEventData(): WritableMap = Arguments.createMap().apply { + putInt("nitroId", nitroId) + } + + companion object { + const val EVENT_NAME = "topNitroIdChange" + } +} + +@UnstableApi +@ReactModule(name = VideoViewViewManager.NAME) +class VideoViewViewManager : SimpleViewManager(), RNCVideoViewManagerInterface { + private val mDelegate: ViewManagerDelegate + + init { + mDelegate = RNCVideoViewManagerDelegate(this) + } + + @ReactProp(name = "nitroId") + override fun setNitroId(view: VideoView, nitroId: Int) { + view.nitroId = nitroId + } + + public override fun createViewInstance(reactContext: ThemedReactContext): VideoView { + return VideoView(reactContext) + } + + override fun getExportedCustomDirectEventTypeConstants(): Map { + return MapBuilder.builder() + .put(NitroIdChange.EVENT_NAME, MapBuilder.of("registrationName", "onNitroIdChange")) + .build() + } + + override fun getName() = NAME + + override fun getDelegate() = mDelegate + + override fun addEventEmitters(reactContext: ThemedReactContext, view: VideoView) { + super.addEventEmitters(reactContext, view) + + val surfaceId = UIManagerHelper.getSurfaceId(reactContext) + val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id) + + if (dispatcher != null) { + view.onNitroIdChange = { + dispatcher.dispatchEvent(NitroIdChange(surfaceId, view.id, view.nitroId)) + } + } + } + + companion object { + const val NAME = "RNCVideoView" + } +} diff --git a/android/src/main/java/com/twg/video/view/VideoView.kt b/android/src/main/java/com/twg/video/view/VideoView.kt new file mode 100644 index 00000000..ad2c256a --- /dev/null +++ b/android/src/main/java/com/twg/video/view/VideoView.kt @@ -0,0 +1,523 @@ +package com.twg.video.view + +import android.annotation.SuppressLint +import android.app.PictureInPictureParams +import android.content.Context +import android.graphics.Color +import android.os.Build +import android.util.AttributeSet +import android.util.DisplayMetrics +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.FrameLayout +import android.widget.ImageButton +import androidx.annotation.RequiresApi +import androidx.core.view.isVisible +import androidx.fragment.app.FragmentActivity +import androidx.media3.common.util.UnstableApi +import androidx.media3.ui.PlayerView +import com.facebook.react.bridge.ReactApplicationContext +import com.margelo.nitro.NitroModules +import com.margelo.nitro.video.HybridVideoPlayer +import com.margelo.nitro.video.ResizeMode +import com.margelo.nitro.video.SurfaceType +import com.margelo.nitro.video.VideoViewEvents +import com.twg.video.core.LibraryError +import com.twg.video.core.VideoManager +import com.twg.video.core.VideoViewError +import com.twg.video.core.fragments.FullscreenVideoFragment +import com.twg.video.core.fragments.PictureInPictureHelperFragment +import com.twg.video.core.utils.PictureInPictureUtils.canEnterPictureInPicture +import com.twg.video.core.utils.PictureInPictureUtils.createPictureInPictureParams +import com.twg.video.core.utils.PictureInPictureUtils.safeEnterPictureInPictureMode +import com.twg.video.core.utils.Threading.runOnMainThread +import com.twg.video.core.extensions.toAspectRatioFrameLayout +import com.twg.video.core.utils.PictureInPictureUtils +import com.twg.video.core.utils.PictureInPictureUtils.createDisabledPictureInPictureParams +import com.twg.video.core.utils.SmallVideoPlayerOptimizer +import com.twg.video.R.layout.player_view_surface +import com.twg.video.R.layout.player_view_texture + +@UnstableApi +class VideoView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { + var hybridPlayer: HybridVideoPlayer? = null + set(value) { + // Clear the SurfaceView when player is about to be set to null + if (value == null && field != null) { + VideoManager.removeViewFromPlayer(this, field!!) + } + + field = value + + field?.movePlayerToVideoView(this) + } + + var nitroId: Int = -1 + set(value) { + if (field == -1) { + post { + onNitroIdChange?.let { it(value) } + VideoManager.registerView(this) + } + } + + VideoManager.updateVideoViewNitroId(oldNitroId = field, newNitroId = value, view = this) + field = value + } + + var autoEnterPictureInPicture: Boolean = false + set(value) { + field = value + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + PictureInPictureUtils.safeSetPictureInPictureParams( + if (value) createPictureInPictureParams(this) + else createDisabledPictureInPictureParams(this) + ) + } + } + + var useController: Boolean = false + set(value) { + field = value + runOnMainThread { + playerView.useController = value + } + } + + var pictureInPictureEnabled: Boolean = false + + var surfaceType: SurfaceType = SurfaceType.SURFACE + set(value) { + if (field == value) return + field = value + + runOnMainThread { + removeView(playerView) + playerView.player = null + playerView = createPlayerView() + playerView.player = hybridPlayer?.player + addView(playerView) + } + } + + var resizeMode: ResizeMode = ResizeMode.NONE + set(value) { + field = value + runOnMainThread { + applyResizeMode() + } + } + + var keepScreenAwake: Boolean + get() = playerView.keepScreenOn + set(value) { + runOnMainThread { + playerView.keepScreenOn = value + } + } + + var events = object : VideoViewEvents { + override var onPictureInPictureChange: ((Boolean) -> Unit)? = {} + override var onFullscreenChange: ((Boolean) -> Unit)? = {} + override var willEnterFullscreen: (() -> Unit)? = {} + override var willExitFullscreen: (() -> Unit)? = {} + override var willEnterPictureInPicture: (() -> Unit)? = {} + override var willExitPictureInPicture: (() -> Unit)? = {} + } + + var onNitroIdChange: ((Int?) -> Unit)? = null + var playerView = createPlayerView() + var isInFullscreen: Boolean = false + set(value) { + field = value + events.onFullscreenChange?.let { it(value) } + } + var isInPictureInPicture: Boolean = false + set(value) { + field = value + events.onPictureInPictureChange?.let { it(value) } + } + private var rootContentViews: List = listOf() + private var pictureInPictureHelperTag: String? = null + private var fullscreenFragmentTag: String? = null + private var movedToRootForPiP: Boolean = false + + val applicationContent: ReactApplicationContext + get() { + return NitroModules.applicationContext ?: throw LibraryError.ApplicationContextNotFound + } + + init { + addView(playerView) + setupFullscreenButton() + applyResizeMode() + } + + private fun applyResizeMode() { + playerView.resizeMode = resizeMode.toAspectRatioFrameLayout() + } + + @SuppressLint("InflateParams") + private fun createPlayerView(): PlayerView { + return when (surfaceType) { + SurfaceType.SURFACE -> LayoutInflater.from(context).inflate(player_view_surface, null) as PlayerView + SurfaceType.TEXTURE -> LayoutInflater.from(context).inflate(player_view_texture, null) as PlayerView + }.apply { + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + setShutterBackgroundColor(Color.TRANSPARENT) + setShowSubtitleButton(true) + useController = false + + // Apply optimizations based on video player size if needed + configureForSmallPlayer() + } + } + + private val layoutRunnable = Runnable { + measure( + MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) + ) + layout(left, top, right, bottom) + + // Additional layout fixes for small video players + applySmallPlayerLayoutFixes() + } + + override fun requestLayout() { + super.requestLayout() + + // https://github.com/facebook/react-native/blob/d19afc73f5048f81656d0b4424232ce6d69a6368/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java#L166 + // This fix issue where exoplayer views where wrong sizes + // Without it, controls, PictureInPicture, content fills, etc. don't work + post(layoutRunnable) + } + + @SuppressLint("PrivateResource") + private fun setupFullscreenButton() { + playerView.setFullscreenButtonClickListener { _ -> + enterFullscreen() + } + + playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) + ?.setImageResource(androidx.media3.ui.R.drawable.exo_ic_fullscreen_enter) + } + + fun enterFullscreen() { + if (isInFullscreen) { + return + } + + val currentActivity = applicationContent.currentActivity + if (currentActivity !is FragmentActivity) { + Log.e("ReactNativeVideo", "Current activity is not a FragmentActivity, cannot enter fullscreen") + return + } + + try { + events.willEnterFullscreen?.let { it() } + + val fragment = FullscreenVideoFragment(this) + fullscreenFragmentTag = fragment.id + + currentActivity.supportFragmentManager.beginTransaction() + .add(fragment, fragment.id) + .commitAllowingStateLoss() + + isInFullscreen = true + } catch (err: Exception) { + val debugMessage = "Failed to start fullscreen fragment for nitroId: $nitroId" + Log.e("ReactNativeVideo", debugMessage, err) + } + } + + @SuppressLint("PrivateResource") + fun exitFullscreen() { + if (!isInFullscreen) { + return + } + + events.willExitFullscreen?.let { it() } + + val currentActivity = applicationContent.currentActivity + fullscreenFragmentTag?.let { tag -> + (currentActivity as? FragmentActivity)?.let { activity -> + activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment -> + // The fragment will handle its own removal in exitFullscreen() + if (fragment is FullscreenVideoFragment) { + runOnMainThread { + fragment.exitFullscreen() + } + } + } + } + fullscreenFragmentTag = null + } + + // Change fullscreen button icon back to enter fullscreen and update callback + setupFullscreenButton() + + isInFullscreen = false + } + + private fun setupPipHelper() { + if (!canEnterPictureInPicture()) { + return + } + + val currentActivity = applicationContent.currentActivity + (currentActivity as? FragmentActivity)?.let { + val fragment = PictureInPictureHelperFragment(this) + pictureInPictureHelperTag = fragment.id + it.supportFragmentManager.beginTransaction() + .add(fragment, fragment.id) + .commitAllowingStateLoss() + } + } + + private fun removePipHelper() { + val currentActivity = applicationContent.currentActivity + pictureInPictureHelperTag?.let { tag -> + (currentActivity as? FragmentActivity)?.let { activity -> + activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment -> + activity.supportFragmentManager.beginTransaction() + .remove(fragment) + .commitAllowingStateLoss() + } + } + pictureInPictureHelperTag = null + } + } + + private fun removeFullscreenFragment() { + val currentActivity = applicationContent.currentActivity + fullscreenFragmentTag?.let { tag -> + (currentActivity as? FragmentActivity)?.let { activity -> + activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment -> + activity.supportFragmentManager.beginTransaction() + .remove(fragment) + .commitAllowingStateLoss() + } + } + fullscreenFragmentTag = null + } + } + + fun hideRootContentViews() { + // Safety check: Only proceed if this is the designated PiP video + if (VideoManager.getCurrentPictureInPictureVideo() != this) { + Log.w("ReactNativeVideo", "hideRootContentViews called on non-PiP video nitroId: $nitroId - ignoring") + return + } + + Log.d("ReactNativeVideo", "Hiding root content views for PiP video nitroId: $nitroId") + + // Remove playerView from parent + // In PiP mode, we don't want to show the controller + // Controls are handled by System if we have MediaSession + playerView.useController = false + playerView.setBackgroundColor(Color.BLACK) + playerView.setShutterBackgroundColor(Color.BLACK) + + // If we're already in fullscreen, the PlayerView is inside the fullscreen container + // and root content is already hidden. Avoid moving the PlayerView again. + if (isInFullscreen) { + Log.d("ReactNativeVideo", "PiP entered while in fullscreen - skipping reparent to root for nitroId: $nitroId") + movedToRootForPiP = false + return + } + + (playerView.parent as? ViewGroup)?.removeView(playerView) + + val currentActivity = applicationContent.currentActivity ?: return + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + rootContentViews = (0 until rootContent.childCount) + .map { rootContent.getChildAt(it) } + .filter { it.isVisible } + + rootContentViews.forEach { view -> view.visibility = GONE } + + rootContent.addView( + playerView, + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + ) + movedToRootForPiP = true + + Log.d("ReactNativeVideo", "Successfully moved player view to root content for PiP nitroId: $nitroId") + } + + fun restoreRootContentViews() { + Log.d("ReactNativeVideo", "Restoring root content views for video nitroId: $nitroId") + + // Reset PlayerView settings + playerView.useController = useController + + playerView.setBackgroundColor(Color.BLACK) + playerView.setShutterBackgroundColor(Color.BLACK) + + if (movedToRootForPiP) { + (playerView.parent as? ViewGroup)?.removeView(playerView) + + val currentActivity = applicationContent.currentActivity ?: return + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + + rootContent.removeView(playerView) + + // Restore root content views + rootContentViews.forEach { it.visibility = View.VISIBLE } + rootContentViews = listOf() + movedToRootForPiP = false + } + + // Add PlayerView back to this VideoView only if not already attached + if (playerView.parent != this) { + addView(playerView) + } + + Log.d("ReactNativeVideo", "Successfully restored root content views for video nitroId: $nitroId") + } + + fun enterPictureInPicture() { + if (isInPictureInPicture || isInFullscreen || !pictureInPictureEnabled) { + return + } + + if (!canEnterPictureInPicture()) { + throw VideoViewError.PictureInPictureNotSupported + } + + // Use centralized PiP manager to handle multiple videos + VideoManager.requestPictureInPicture(this) + } + + internal fun internalEnterPictureInPicture(): Boolean { + if (isInPictureInPicture || isInFullscreen || !pictureInPictureEnabled) { + return false + } + + if (!canEnterPictureInPicture()) { + return false + } + + val currentActivity = applicationContent.currentActivity ?: return false + + return try { + events.willEnterPictureInPicture?.let { it() } + + val success = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val params = createPictureInPictureParams(this) + safeEnterPictureInPictureMode(params) + } else { + try { + @Suppress("Deprecation") + currentActivity.enterPictureInPictureMode() + true + } catch (e: Exception) { + Log.e("ReactNativeVideo", "Failed to enter PiP mode (legacy)", e) + false + } + } + + if (success) { + Log.d("ReactNativeVideo", "Successfully requested PiP mode for nitroId: $nitroId") + // Note: isInPictureInPicture will be set to true by the system callback in PictureInPictureHelperFragment + } else { + Log.w("ReactNativeVideo", "Failed to enter PiP mode for nitroId: $nitroId") + } + + success + } catch (e: Exception) { + Log.e("ReactNativeVideo", "Exception in internalEnterPictureInPicture for nitroId: $nitroId", e) + false + } + } + + fun exitPictureInPicture() { + if (!isInPictureInPicture) return + + VideoManager.notifyPictureInPictureExited(this) + + events.willExitPictureInPicture?.let { it() } + + if (movedToRootForPiP) { + restoreRootContentViews() + } else { + Log.d("ReactNativeVideo", "Exiting PiP while in fullscreen - no reparent needed for nitroId: $nitroId") + } + + isInPictureInPicture = false + } + + internal fun forceExitPictureInPicture() { + if (!isInPictureInPicture) { + Log.d("ReactNativeVideo", "Force exit PiP skipped for nitroId: $nitroId (not in PiP)") + return + } + + Log.d("ReactNativeVideo", "Force exiting PiP for nitroId: $nitroId") + + try { + val currentActivity = applicationContent.currentActivity + if (currentActivity?.isInPictureInPictureMode == true) { + Log.d("ReactNativeVideo", "Activity is in PiP mode, preparing for transition") + } + + events.willExitPictureInPicture?.let { it() } + if (movedToRootForPiP) { + restoreRootContentViews() + } else { + Log.d("ReactNativeVideo", "Force exit PiP while in fullscreen - no reparent needed for nitroId: $nitroId") + } + isInPictureInPicture = false + + VideoManager.notifyPictureInPictureExited(this) + + Log.d("ReactNativeVideo", "Successfully force exited PiP for nitroId: $nitroId") + + } catch (e: Exception) { + Log.e("ReactNativeVideo", "Failed to force exit PiP mode for nitroId: $nitroId", e) + } + } + + // -------- View Lifecycle Methods -------- + override fun onDetachedFromWindow() { + removePipHelper() + removeFullscreenFragment() + VideoManager.unregisterView(this) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + PictureInPictureUtils.safeSetPictureInPictureParams( + createDisabledPictureInPictureParams(this) + ) + } + + super.onDetachedFromWindow() + } + + override fun onAttachedToWindow() { + hybridPlayer?.movePlayerToVideoView(this) + setupPipHelper() + super.onAttachedToWindow() + } + + private fun PlayerView.configureForSmallPlayer() { + SmallVideoPlayerOptimizer.applyOptimizations(this, context, isFullscreen = false) + + // Also apply after any layout changes + viewTreeObserver.addOnGlobalLayoutListener { + SmallVideoPlayerOptimizer.applyOptimizations(this, context, isFullscreen = false) + } + } + + private fun applySmallPlayerLayoutFixes() { + SmallVideoPlayerOptimizer.applyOptimizations(playerView, context, isFullscreen = false) + } +} diff --git a/android/src/main/res/layout/player_view_surface.xml b/android/src/main/res/layout/player_view_surface.xml new file mode 100644 index 00000000..abc3f647 --- /dev/null +++ b/android/src/main/res/layout/player_view_surface.xml @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/android/src/main/res/layout/player_view_texture.xml b/android/src/main/res/layout/player_view_texture.xml new file mode 100644 index 00000000..210a01b7 --- /dev/null +++ b/android/src/main/res/layout/player_view_texture.xml @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerDelegate.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerDelegate.java new file mode 100644 index 00000000..2a7c45bc --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerDelegate.java @@ -0,0 +1,32 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.uimanager.BaseViewManager; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.LayoutShadowNode; + +public class RNCVideoViewManagerDelegate & RNCVideoViewManagerInterface> extends BaseViewManagerDelegate { + public RNCVideoViewManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "nitroId": + mViewManager.setNitroId(view, value == null ? 0 : ((Double) value).intValue()); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerInterface.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerInterface.java new file mode 100644 index 00000000..fd4069fc --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerInterface.java @@ -0,0 +1,16 @@ +/** +* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). +* +* Do not edit this file as changes may cause incorrect behavior and will be lost +* once the code is regenerated. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; + +public interface RNCVideoViewManagerInterface { + void setNitroId(T view, int value); +} diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashMediaSource.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashMediaSource.kt new file mode 100644 index 00000000..38106e9f --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashMediaSource.kt @@ -0,0 +1,35 @@ +package androidx.media3.exoplayer.dash; + +import androidx.media3.common.MediaItem; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.datasource.DataSource; +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; + +class DashMediaSource { + + @UnstableApi + class Factory( + factory: DataSource.Factory, + ) : MediaSource.Factory { + // NOOP + + override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory { + throw UnsupportedOperationException("STUB") + } + + override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory { + throw UnsupportedOperationException("STUB") + } + + override fun getSupportedTypes(): IntArray { + return intArrayOf() + } + + override fun createMediaSource(mediaItem: MediaItem): MediaSource { + throw UnsupportedOperationException("STUB") + } + } +} + diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashUtil.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashUtil.kt new file mode 100644 index 00000000..0cf634bd --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashUtil.kt @@ -0,0 +1,11 @@ +package androidx.media3.exoplayer.dash + +import android.net.Uri +import androidx.media3.datasource.DataSource +import androidx.media3.exoplayer.dash.manifest.DashManifest + +object DashUtil { + fun loadManifest(ds: DataSource?, uri: Uri?): DashManifest? { + return null + } +} diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/AdaptationSet.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/AdaptationSet.kt new file mode 100644 index 00000000..efe5e9fd --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/AdaptationSet.kt @@ -0,0 +1,9 @@ +package androidx.media3.exoplayer.dash.manifest + +import androidx.collection.CircularArray + +class AdaptationSet { + var type: Int = 0 + var representations: CircularArray? = + null +} diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/DashManifest.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/DashManifest.kt new file mode 100644 index 00000000..d9bf6425 --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/DashManifest.kt @@ -0,0 +1,10 @@ +package androidx.media3.exoplayer.dash.manifest + +class DashManifest { + val periodCount: Int + get() = 0 + + fun getPeriod(index: Int): Period? { + return null + } +} diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Period.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Period.kt new file mode 100644 index 00000000..0f837858 --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Period.kt @@ -0,0 +1,7 @@ +package androidx.media3.exoplayer.dash.manifest + +import androidx.collection.CircularArray + +class Period { + var adaptationSets: CircularArray? = null +} diff --git a/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Representation.kt b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Representation.kt new file mode 100644 index 00000000..434d7132 --- /dev/null +++ b/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Representation.kt @@ -0,0 +1,8 @@ +package androidx.media3.exoplayer.dash.manifest + +import androidx.media3.common.Format + +class Representation { + var format: Format? = null + var presentationTimeOffsetUs: Long = 0 +} diff --git a/android/src/stubs/hls/androidx/media3/exoplayer/hls/HlsMediaSource.kt b/android/src/stubs/hls/androidx/media3/exoplayer/hls/HlsMediaSource.kt new file mode 100644 index 00000000..df7651ad --- /dev/null +++ b/android/src/stubs/hls/androidx/media3/exoplayer/hls/HlsMediaSource.kt @@ -0,0 +1,33 @@ +package androidx.media3.exoplayer.hls + +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.datasource.DataSource +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy + +class HlsMediaSource { + @UnstableApi + class Factory(private val mediaDataSourceFactory: DataSource.Factory) : MediaSource.Factory { + override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory { + throw UnsupportedOperationException("Not implemented") + } + + override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory { + throw UnsupportedOperationException("Not implemented") + } + + override fun getSupportedTypes(): IntArray { + return intArrayOf() + } + + override fun createMediaSource(mediaItem: MediaItem): MediaSource { + throw UnsupportedOperationException("Not implemented") + } + + fun setAllowChunklessPreparation(allowChunklessPreparation: Boolean): Factory { + return this + } + } +} diff --git a/app.plugin.js b/app.plugin.js new file mode 100644 index 00000000..162bcd89 --- /dev/null +++ b/app.plugin.js @@ -0,0 +1 @@ +module.exports = require('./lib/commonjs/expo-plugins/withReactNativeVideo'); diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..29f3a606 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + ['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }], + ], +}; diff --git a/ios/Video-Bridging-Header.h b/ios/Video-Bridging-Header.h new file mode 100644 index 00000000..16eb5eb1 --- /dev/null +++ b/ios/Video-Bridging-Header.h @@ -0,0 +1 @@ +#import diff --git a/ios/core/Extensions/AVAsset+estimatedMemoryUsage.swift b/ios/core/Extensions/AVAsset+estimatedMemoryUsage.swift new file mode 100644 index 00000000..836aa6cc --- /dev/null +++ b/ios/core/Extensions/AVAsset+estimatedMemoryUsage.swift @@ -0,0 +1,40 @@ +// +// AVAsset+estimatedMemoryUsage.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/01/2025. +// + +import AVFoundation + +extension AVAsset { + var estimatedMemoryUsage: Int { + var size = 0 + + // Get enabled video tracks + let enabledVideoTrack = tracks(withMediaType: .video) + .filter { $0.isEnabled } + + // Calculate memory usage for video tracks + for track in enabledVideoTrack { + let dimensions = track.naturalSize + let pixelCount = Int(dimensions.width * dimensions.height) + let frameSize = pixelCount * 4 // RGBA + let frames = 30 * 15 // 30 FPS * 15 seconds of buffer + + size += frameSize * frames + } + + // Get enabled audio tracks + let enabledAudioTrack = tracks(withMediaType: .audio) + .filter { $0.isEnabled } + + // Estimate memory usage for audio tracks + for _ in enabledAudioTrack { + let frameSize = 44100 * 2 * 2 // 44.1kHz * 2 channels * 2 seconds + size += frameSize + } + + return size + } +} \ No newline at end of file diff --git a/ios/core/Extensions/AVAssetTrack+orientation.swift b/ios/core/Extensions/AVAssetTrack+orientation.swift new file mode 100644 index 00000000..959eba51 --- /dev/null +++ b/ios/core/Extensions/AVAssetTrack+orientation.swift @@ -0,0 +1,41 @@ +// +// AVAssetTrack+orientation.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/01/2025. +// + +import AVFoundation + +extension AVAssetTrack { + var orientation: VideoOrientation { + let transform = preferredTransform + let size = naturalSize.applying(transform) + + // Check if video is square + if size.width == size.height { + return .square + } + + // Check if video is portrait or landscape + let isNaturalSizePortrait = size.width < size.height + + // Calculate video rotation + let angle = atan2(Double(transform.b), Double(transform.a)) + let degrees = angle * 180 / .pi + let rotation = degrees < 0 ? degrees + 360 : degrees + + switch rotation { + case 0: + return isNaturalSizePortrait ? .portrait : .landscapeRight + case 90, -270: + return .portrait + case 180, -180: + return isNaturalSizePortrait ? .portraitUpsideDown : .landscapeLeft + case 270, -90: + return .portraitUpsideDown + default: + return isNaturalSizePortrait ? .portrait : .landscape + } + } +} \ No newline at end of file diff --git a/ios/core/Extensions/AVPlayerItem+externalSubtitles.swift b/ios/core/Extensions/AVPlayerItem+externalSubtitles.swift new file mode 100644 index 00000000..dbd0ed4d --- /dev/null +++ b/ios/core/Extensions/AVPlayerItem+externalSubtitles.swift @@ -0,0 +1,35 @@ +// +// AVPlayerItem+externalSubtitles.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 08/05/2025. +// + +import AVFoundation +import Foundation + +extension AVPlayerItem { + static func withExternalSubtitles(for asset: AVURLAsset, config: NativeVideoConfig) async throws + -> AVPlayerItem + { + if config.externalSubtitles?.isEmpty != false { + return AVPlayerItem(asset: asset) + } + + if asset.url.pathExtension == "m3u8" { + let supportedExternalSubtitles = config.externalSubtitles?.filter { subtitle in + ExternalSubtitlesUtils.isSubtitleTypeSupported(subtitle: subtitle) + } + + if supportedExternalSubtitles?.isEmpty == true { + return AVPlayerItem(asset: asset) + } else { + return try await ExternalSubtitlesUtils.modifyStreamManifestWithExternalSubtitles( + for: asset, config: config) + } + } + + return try await ExternalSubtitlesUtils.createCompositionWithExternalSubtitles( + for: asset, config: config) + } +} diff --git a/ios/core/Extensions/AVPlayerItem+getBufferedDurration.swift b/ios/core/Extensions/AVPlayerItem+getBufferedDurration.swift new file mode 100644 index 00000000..b6e7a5b2 --- /dev/null +++ b/ios/core/Extensions/AVPlayerItem+getBufferedDurration.swift @@ -0,0 +1,34 @@ +// +// AVPlayerItem+getBufferedPosition.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 06/05/2025. +// + +import Foundation +import AVFoundation + +extension AVPlayerItem { + + // Duration that can be played using only the buffer (seconds) + func getbufferDuration() -> Double { + var effectiveTimeRange: CMTimeRange? + + for value in loadedTimeRanges { + let timeRange: CMTimeRange = value.timeRangeValue + if CMTimeRangeContainsTime(timeRange, time: currentTime()) { + effectiveTimeRange = timeRange + break + } + } + + if let effectiveTimeRange { + let playableDuration: Float64 = CMTimeGetSeconds(CMTimeRangeGetEnd(effectiveTimeRange)) + if playableDuration > 0 { + return playableDuration + } + } + + return 0 + } +} diff --git a/ios/core/Extensions/AVPlayerItem+setBufferConfig.swift b/ios/core/Extensions/AVPlayerItem+setBufferConfig.swift new file mode 100644 index 00000000..428c1275 --- /dev/null +++ b/ios/core/Extensions/AVPlayerItem+setBufferConfig.swift @@ -0,0 +1,37 @@ +// +// AVPlayerItem+setBufferConfig.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 13/09/2025. +// + +import Foundation +import AVFoundation + +extension AVPlayerItem { + func setBufferConfig(config: BufferConfig) { + if let forwardBufferDurationMs = config.preferredForwardBufferDurationMs { + preferredForwardBufferDuration = TimeInterval(forwardBufferDurationMs / 1000.0) + } + + if let peakBitRate = config.preferredPeakBitRate { + preferredPeakBitRate = Double(peakBitRate) + } + + if let maximumResolution = config.preferredMaximumResolution { + preferredMaximumResolution = CGSize(width: maximumResolution.width, height: maximumResolution.height) + } + + if let peakBitRateForExpensiveNetworks = config.preferredPeakBitRateForExpensiveNetworks { + preferredPeakBitRateForExpensiveNetworks = Double(peakBitRateForExpensiveNetworks) + } + + if let maximumResolutionForExpensiveNetworks = config.preferredMaximumResolutionForExpensiveNetworks { + preferredMaximumResolutionForExpensiveNetworks = CGSize(width: maximumResolutionForExpensiveNetworks.width, height: maximumResolutionForExpensiveNetworks.height) + } + + if let liveTargetOffsetMs = config.livePlayback?.targetOffsetMs { + configuredTimeOffsetFromLive = CMTime(seconds: Double(liveTargetOffsetMs) / 1000.0, preferredTimescale: 1000) + } + } +} diff --git a/ios/core/Extensions/AVPlayerViewController+Fullscreen.swift b/ios/core/Extensions/AVPlayerViewController+Fullscreen.swift new file mode 100644 index 00000000..e4b9342f --- /dev/null +++ b/ios/core/Extensions/AVPlayerViewController+Fullscreen.swift @@ -0,0 +1,21 @@ +// +// AVPlayerViewController+Fullscreen.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 27/04/2025. +// + +import Foundation +import AVKit + +extension AVPlayerViewController { + // https://stackoverflow.com/a/64466924 + + func enterFullscreen(animated: Bool) { + performIfResponds(NSSelectorFromString("enterFullScreenAnimated:completionHandler:"), with: animated, with: nil) + } + + func exitFullscreen(animated: Bool) { + performIfResponds(NSSelectorFromString("exitFullScreenAnimated:completionHandler:"), with: animated, with: nil) + } +} diff --git a/ios/core/Extensions/AVPlayerViewController+PictureInPicture.swift b/ios/core/Extensions/AVPlayerViewController+PictureInPicture.swift new file mode 100644 index 00000000..ec34962f --- /dev/null +++ b/ios/core/Extensions/AVPlayerViewController+PictureInPicture.swift @@ -0,0 +1,24 @@ +// +// AVPlayerViewController+PictureInPicture.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 27/04/2025. +// + +import Foundation +import AVKit + +extension AVPlayerViewController { + // https://github.com/expo/expo/blob/d37ae17df23c58011a3c5b9f5dedd563bf8e6521/packages/expo-video/ios/VideoView.swift#L110 + func startPictureInPicture() throws { + guard AVPictureInPictureController.isPictureInPictureSupported() else { + throw VideoViewError.pictureInPictureNotSupported.error() + } + + performIfResponds(NSSelectorFromString("startPictureInPicture")) + } + + func stopPictureInPicture() { + performIfResponds(NSSelectorFromString("stopPictureInPicture")) + } +} diff --git a/ios/core/Extensions/AVURLAsset+getAssetInformation.swift b/ios/core/Extensions/AVURLAsset+getAssetInformation.swift new file mode 100644 index 00000000..506df62d --- /dev/null +++ b/ios/core/Extensions/AVURLAsset+getAssetInformation.swift @@ -0,0 +1,68 @@ +import AVFoundation + +extension AVURLAsset { + func getAssetInformation() async throws -> VideoInformation { + // Initialize with default values + var videoInformation = VideoInformation( + bitrate: Double.nan, + width: Double.nan, + height: Double.nan, + duration: -1, + fileSize: -1, + isHDR: false, + isLive: false, + orientation: .unknown + ) + + videoInformation.fileSize = try await VideoFileHelper.getFileSize(for: url) + + // Check if asset is live stream + if duration.flags.contains(.indefinite) { + videoInformation.duration = -1 + videoInformation.isLive = true + } else { + videoInformation.duration = Int64(CMTimeGetSeconds(duration)) + videoInformation.isLive = false + } + + if let videoTrack = tracks(withMediaType: .video).first { + let size = videoTrack.naturalSize.applying(videoTrack.preferredTransform) + videoInformation.width = size.width + videoInformation.height = size.height + + videoInformation.bitrate = Double(videoTrack.estimatedDataRate) + + videoInformation.orientation = videoTrack.orientation + + if #available(iOS 14.0, tvOS 14.0, visionOS 1.0, *) { + videoInformation.isHDR = videoTrack.hasMediaCharacteristic(.containsHDRVideo) + } + } else if url.pathExtension == "m3u8" { + // For HLS streams, we cannot get video track information directly + // So we download manifest and try to extract video information from it + + let manifestContent = try await HLSManifestParser.downloadManifest(from: url) + let manifestInfo = try HLSManifestParser.parseM3U8Manifest(manifestContent) + + if let videoStream = manifestInfo.streams.first { + videoInformation.width = Double(videoStream.width ?? Int(Double.nan)) + videoInformation.height = Double(videoStream.height ?? Int(Double.nan)) + videoInformation.bitrate = Double(videoStream.bandwidth ?? Int(Double.nan)) + } + + if videoInformation.width > 0 && videoInformation.height > 0 { + if videoInformation.width == videoInformation.height { + videoInformation.orientation = .square + } else if videoInformation.width > videoInformation.height { + videoInformation.orientation = .landscapeRight + } else if videoInformation.width < videoInformation.height { + videoInformation.orientation = .portrait + } else { + videoInformation.orientation = .unknown + } + } + } + + return videoInformation + } +} diff --git a/ios/core/Extensions/NSObject+PerformIfResponds.swift b/ios/core/Extensions/NSObject+PerformIfResponds.swift new file mode 100644 index 00000000..ac1273d8 --- /dev/null +++ b/ios/core/Extensions/NSObject+PerformIfResponds.swift @@ -0,0 +1,30 @@ +// +// NSObject+PerformIfResponds.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 27/04/2025. +// + +import Foundation + +extension NSObject { + // Safe perform methods for Objective-C selectors + + func performIfResponds(_ selector: Selector) { + if self.responds(to: selector) { + self.perform(selector) + } + } + + func performIfResponds(_ selector: Selector, with object: Any?) { + if self.responds(to: selector) { + self.perform(selector, with: object) + } + } + + func performIfResponds(_ selector: Selector, with object1: Any?, with object2: Any?) { + if self.responds(to: selector) { + self.perform(selector, with: object1, with: object2) + } + } +} diff --git a/ios/core/Extensions/ResizeMode+VideoGravity.swift b/ios/core/Extensions/ResizeMode+VideoGravity.swift new file mode 100644 index 00000000..22a209ac --- /dev/null +++ b/ios/core/Extensions/ResizeMode+VideoGravity.swift @@ -0,0 +1,24 @@ +// +// ResizeMode.swift +// ReactNativeVideo +// +// Created for resizeMode feature +// + +import Foundation +import AVFoundation + +public extension ResizeMode { + func toVideoGravity() -> AVLayerVideoGravity { + switch self { + case .contain: + return .resizeAspect + case .cover: + return .resizeAspectFill + case .stretch: + return .resize + case .none: + return .resizeAspect // Default to aspect ratio if none specified + } + } +} diff --git a/ios/core/HLSSubtitleInjector.swift b/ios/core/HLSSubtitleInjector.swift new file mode 100644 index 00000000..fa036b43 --- /dev/null +++ b/ios/core/HLSSubtitleInjector.swift @@ -0,0 +1,381 @@ +import AVFoundation +import Foundation +import NitroModules + +class HLSSubtitleInjector: NSObject { + private let originalManifestUrl: URL + private let externalSubtitles: [NativeExternalSubtitle] + private var modifiedManifestContent: String? + private static let customScheme = "rnv-hls" + private static let subtitleScheme = "rnv-hls-subtitles" + private static let subtitleGroupID = "rnv-subs" + private static let resourceLoaderQueue = DispatchQueue( + label: "com.nitro.HLSSubtitleInjector.resourceLoaderQueue", + qos: .userInitiated + ) + + init(manifestUrl: URL, externalSubtitles: [NativeExternalSubtitle]) { + self.originalManifestUrl = manifestUrl + self.externalSubtitles = externalSubtitles + super.init() + } + + func createModifiedAsset() -> AVURLAsset { + let customURL = createCustomURL(from: originalManifestUrl) + let asset = AVURLAsset(url: customURL) + asset.resourceLoader.setDelegate( + self, + queue: Self.resourceLoaderQueue + ) + return asset + } + + private func createCustomURL(from originalURL: URL) -> URL { + var components = URLComponents( + url: originalURL, + resolvingAgainstBaseURL: false + )! + components.scheme = Self.customScheme + return components.url! + } + + private func getModifiedManifestContent() async throws -> String { + if let cached = modifiedManifestContent { + return cached + } + + let originalContent = try await HLSManifestParser.downloadManifest(from: originalManifestUrl) + let modifiedContent = try modifyM3U8Content( + originalContent, + with: externalSubtitles + ) + modifiedManifestContent = modifiedContent + return modifiedContent + } + + private func modifyM3U8Content( + _ originalContent: String, + with externalSubtitles: [NativeExternalSubtitle] + ) throws -> String { + let lines = originalContent.components(separatedBy: .newlines) + var modifiedLines: [String] = [] + var foundExtM3U = false + var isAfterVersionOrM3U = false + var hasSubtitleGroup = false + let baseURL = originalManifestUrl.deletingLastPathComponent() + + for line in lines { + let trimmedLine = line.trimmingCharacters(in: .whitespaces) + + if trimmedLine.hasPrefix("#EXTM3U") { + foundExtM3U = true + modifiedLines.append(line) + isAfterVersionOrM3U = true + continue + } + + if isAfterVersionOrM3U && !hasSubtitleGroup + && shouldInsertSubtitlesHere(line: trimmedLine) + { + for (index, subtitle) in externalSubtitles.enumerated() { + let subtitleTrack = createSubtitleTrackEntry(for: subtitle, index: index) + modifiedLines.append(subtitleTrack) + } + hasSubtitleGroup = true + isAfterVersionOrM3U = false + } + + let processedLine = HLSManifestParser.convertRelativeURLsToAbsolute( + line: line, + baseURL: baseURL + ) + + // Handle existing subtitle groups and stream info lines + if trimmedLine.hasPrefix("#EXT-X-MEDIA:") && trimmedLine.contains("TYPE=SUBTITLES") { + let modifiedMediaLine = replaceSubtitleGroupInMediaLine(processedLine) + modifiedLines.append(modifiedMediaLine) + } else if trimmedLine.hasPrefix("#EXT-X-STREAM-INF:") { + let modifiedStreamLine = replaceSubtitleGroupInStreamInf( + processedLine, hasSubtitleGroup: hasSubtitleGroup) + modifiedLines.append(modifiedStreamLine) + } else { + modifiedLines.append(processedLine) + } + } + + if foundExtM3U && !hasSubtitleGroup { + var finalLines: [String] = [] + var insertedSubtitles = false + + for line in modifiedLines { + finalLines.append(line) + + if !insertedSubtitles + && (line.hasPrefix("#EXTM3U") || line.hasPrefix("#EXT-X-VERSION")) + { + for (index, subtitle) in externalSubtitles.enumerated() { + let subtitleTrack = createSubtitleTrackEntry(for: subtitle, index: index) + finalLines.append(subtitleTrack) + } + insertedSubtitles = true + } + } + + modifiedLines = finalLines + } + + if !foundExtM3U { + throw SourceError.invalidUri(uri: originalManifestUrl.absoluteString) + .error() + } + + // Post-process: ensure every variant stream references our subtitle group if we injected it + if hasSubtitleGroup { + modifiedLines = modifiedLines.map { line in + if line.hasPrefix("#EXT-X-STREAM-INF:") && !line.contains("SUBTITLES=") { + if line.hasSuffix(",") { + return line + "SUBTITLES=\"\(Self.subtitleGroupID)\"" + } else { + return line + ",SUBTITLES=\"\(Self.subtitleGroupID)\"" + } + } + return line + } + } + + return modifiedLines.joined(separator: "\n") + } + + private func shouldInsertSubtitlesHere(line: String) -> Bool { + return line.hasPrefix("#EXT-X-STREAM-INF:") + || line.hasPrefix("#EXT-X-I-FRAME-STREAM-INF:") + || line.hasPrefix("#EXT-X-MEDIA:") + || line.hasPrefix("#EXTINF:") + || line.hasPrefix("#EXT-X-BYTERANGE:") + || (!line.hasPrefix("#") && !line.isEmpty + && !line.hasPrefix("#EXT-X-VERSION")) + } + + private func replaceSubtitleGroupInMediaLine(_ line: String) -> String { + // Find and replace GROUP-ID in subtitle media lines + let groupIdPattern = #"GROUP-ID="[^"]*""# + + if let regex = try? NSRegularExpression(pattern: groupIdPattern, options: []) { + let range = NSRange(location: 0, length: line.utf16.count) + let replacement = "GROUP-ID=\"\(Self.subtitleGroupID)\"" + return regex.stringByReplacingMatches( + in: line, options: [], range: range, withTemplate: replacement) + } + + return line + } + + private func replaceSubtitleGroupInStreamInf(_ line: String, hasSubtitleGroup: Bool) -> String { + // First, handle existing SUBTITLES= references + let subtitlesPattern = #"SUBTITLES="[^"]*""# + + var modifiedLine = line + if let regex = try? NSRegularExpression(pattern: subtitlesPattern, options: []) { + let range = NSRange(location: 0, length: line.utf16.count) + let replacement = "SUBTITLES=\"\(Self.subtitleGroupID)\"" + modifiedLine = regex.stringByReplacingMatches( + in: line, options: [], range: range, withTemplate: replacement) + } else if hasSubtitleGroup && !line.contains("SUBTITLES=") { + // Add subtitle group reference if we have subtitles but no existing reference + if line.hasSuffix(",") { + modifiedLine = line + "SUBTITLES=\"\(Self.subtitleGroupID)\"" + } else { + modifiedLine = line + ",SUBTITLES=\"\(Self.subtitleGroupID)\"" + } + } + + return modifiedLine + } + + private func createSubtitleTrackEntry(for subtitle: NativeExternalSubtitle, index: Int) + -> String + { + let subtitleM3U8URI = "\(Self.subtitleScheme)://\(index)/subtitle.m3u8" + + return + "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"\(Self.subtitleGroupID)\",NAME=\"\(subtitle.label)\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"\(subtitle.language)\",URI=\"\(subtitleM3U8URI)\"" + } +} + +// MARK: - AVAssetResourceLoaderDelegate + +extension HLSSubtitleInjector: AVAssetResourceLoaderDelegate { + func resourceLoader( + _ resourceLoader: AVAssetResourceLoader, + shouldWaitForLoadingOfRequestedResource loadingRequest: + AVAssetResourceLoadingRequest + ) -> Bool { + + guard let url = loadingRequest.request.url else { + return false + } + + switch url.scheme { + case Self.customScheme: + return handleMainManifest(url: url, loadingRequest: loadingRequest) + case Self.subtitleScheme: + return handleSubtitleM3U8(url: url, loadingRequest: loadingRequest) + default: + return false + } + } + + private func handleMainManifest(url: URL, loadingRequest: AVAssetResourceLoadingRequest) -> Bool { + guard url.path.hasSuffix(".m3u8") else { + return false + } + + Task { + do { + let modifiedContent = try await getModifiedManifestContent() + + guard let data = modifiedContent.data(using: .utf8) else { + throw SourceError.invalidUri(uri: "Failed to encode manifest content") + .error() + } + + if let contentRequest = loadingRequest.contentInformationRequest { + contentRequest.contentType = "application/x-mpegURL" + contentRequest.contentLength = Int64(data.count) + contentRequest.isByteRangeAccessSupported = true + } + + if let dataRequest = loadingRequest.dataRequest { + let requestedData: Data + + if dataRequest.requestedOffset > 0 || dataRequest.requestedLength > 0 { + let offset = Int(dataRequest.requestedOffset) + let length = + dataRequest.requestedLength > 0 + ? min(Int(dataRequest.requestedLength), data.count - offset) + : data.count - offset + + if offset < data.count && length > 0 { + requestedData = data.subdata(in: offset..<(offset + length)) + } else { + requestedData = Data() + } + } else { + requestedData = data + } + + dataRequest.respond(with: requestedData) + } + + loadingRequest.finishLoading() + } catch { + loadingRequest.finishLoading(with: error) + } + } + + return true + } + + private func handleSubtitleM3U8(url: URL, loadingRequest: AVAssetResourceLoadingRequest) -> Bool { + guard let indexString = url.host, let index = Int(indexString) else { + return false + } + + guard index < externalSubtitles.count else { + return false + } + + let subtitle = externalSubtitles[index] + + Task { + do { + guard let subtitleURL = URL(string: subtitle.uri) else { + throw SourceError.invalidUri(uri: "Invalid subtitle URI: \(subtitle.uri)").error() + } + + let (vttData, response) = try await URLSession.shared.data(from: subtitleURL) + + guard let httpResponse = response as? HTTPURLResponse, + 200...299 ~= httpResponse.statusCode + else { + throw SourceError.invalidUri(uri: "Subtitle request failed with status: \(response)") + .error() + } + + guard let vttString = String(data: vttData, encoding: .utf8) else { + throw SourceError.invalidUri(uri: "Failed to decode VTT content").error() + } + + let duration = extractDurationFromVTT(vttString) + + let m3u8Wrapper = """ + #EXTM3U + #EXT-X-VERSION:3 + #EXT-X-MEDIA-SEQUENCE:1 + #EXT-X-PLAYLIST-TYPE:VOD + #EXT-X-ALLOW-CACHE:NO + #EXT-X-TARGETDURATION:\(Int(duration)) + #EXTINF:\(String(format: "%.3f", duration)), no desc + \(subtitle.uri) + #EXT-X-ENDLIST + """ + + guard let m3u8Data = m3u8Wrapper.data(using: .utf8) else { + throw SourceError.invalidUri(uri: "Failed to create M3U8 wrapper").error() + } + + if let contentRequest = loadingRequest.contentInformationRequest { + contentRequest.contentType = "application/x-mpegURL" + contentRequest.contentLength = Int64(m3u8Data.count) + contentRequest.isByteRangeAccessSupported = true + } + + if let dataRequest = loadingRequest.dataRequest { + dataRequest.respond(with: m3u8Data) + } + + loadingRequest.finishLoading() + } catch { + loadingRequest.finishLoading(with: error) + } + } + + return true + } + + private func extractDurationFromVTT(_ vttString: String) -> Double { + // Extract duration from VTT timestamps (similar to the PR approach) + let timestampPattern = #"(?:(\d+):)?(\d+):([\d\.]+)"# + + guard let regex = try? NSRegularExpression(pattern: timestampPattern, options: []) else { + return 60.0 // Default fallback + } + + let matches = regex.matches( + in: vttString, + options: [], + range: NSRange(location: 0, length: vttString.utf16.count) + ) + + guard let lastMatch = matches.last, + let range = Range(lastMatch.range, in: vttString) + else { + return 60.0 // Default fallback + } + + let lastTimestampString = String(vttString[range]) + let components = lastTimestampString.components(separatedBy: ":").reversed() + .compactMap { Double($0) } + .enumerated() + .map { pow(60.0, Double($0.offset)) * $0.element } + .reduce(0, +) + + return max(components, 1.0) // Ensure at least 1 second + } + + func resourceLoader( + _ resourceLoader: AVAssetResourceLoader, + didCancel loadingRequest: AVAssetResourceLoadingRequest + ) { + } +} diff --git a/ios/core/NowPlayingInfoCenterManager.swift b/ios/core/NowPlayingInfoCenterManager.swift new file mode 100644 index 00000000..34144467 --- /dev/null +++ b/ios/core/NowPlayingInfoCenterManager.swift @@ -0,0 +1,323 @@ +import Foundation +import MediaPlayer + +class NowPlayingInfoCenterManager { + static let shared = NowPlayingInfoCenterManager() + + private let SEEK_INTERVAL_SECONDS: Double = 10 + + private weak var currentPlayer: AVPlayer? + private var players = NSHashTable.weakObjects() + + private var observers: [Int: NSKeyValueObservation] = [:] + private var playbackObserver: Any? + + private var playTarget: Any? + private var pauseTarget: Any? + private var skipForwardTarget: Any? + private var skipBackwardTarget: Any? + private var playbackPositionTarget: Any? + private var seekTarget: Any? + private var togglePlayPauseTarget: Any? + + private let remoteCommandCenter = MPRemoteCommandCenter.shared() + + var receivingRemoteControlEvents = false { + didSet { + if receivingRemoteControlEvents { + DispatchQueue.main.async { + VideoManager.shared.setRemoteControlEventsActive(true) + UIApplication.shared.beginReceivingRemoteControlEvents() + } + } else { + DispatchQueue.main.async { + UIApplication.shared.endReceivingRemoteControlEvents() + VideoManager.shared.setRemoteControlEventsActive(false) + } + } + } + } + + deinit { + cleanup() + } + + func registerPlayer(player: AVPlayer) { + if players.contains(player) { + return + } + + if receivingRemoteControlEvents == false { + receivingRemoteControlEvents = true + } + + if let oldObserver = observers[player.hashValue] { + oldObserver.invalidate() + } + + observers[player.hashValue] = observePlayers(player: player) + players.add(player) + + if currentPlayer == nil { + setCurrentPlayer(player: player) + } + } + + func removePlayer(player: AVPlayer) { + if !players.contains(player) { + return + } + + if let observer = observers[player.hashValue] { + observer.invalidate() + } + + observers.removeValue(forKey: player.hashValue) + players.remove(player) + + if currentPlayer == player { + currentPlayer = nil + updateNowPlayingInfo() + } + + if players.allObjects.isEmpty { + cleanup() + } + } + + public func cleanup() { + observers.removeAll() + players.removeAllObjects() + + if let playbackObserver { + currentPlayer?.removeTimeObserver(playbackObserver) + } + + invalidateCommandTargets() + + MPNowPlayingInfoCenter.default().nowPlayingInfo = [:] + receivingRemoteControlEvents = false + } + + private func setCurrentPlayer(player: AVPlayer) { + if player == currentPlayer { + return + } + + if let playbackObserver { + currentPlayer?.removeTimeObserver(playbackObserver) + } + + currentPlayer = player + registerCommandTargets() + + updateNowPlayingInfo() + playbackObserver = player.addPeriodicTimeObserver( + forInterval: CMTime(value: 1, timescale: 4), + queue: .global(), + using: { [weak self] _ in + self?.updateNowPlayingInfo() + } + ) + } + + private func registerCommandTargets() { + invalidateCommandTargets() + + playTarget = remoteCommandCenter.playCommand.addTarget { [weak self] _ in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + + if player.rate == 0 { + player.play() + } + + return .success + } + + pauseTarget = remoteCommandCenter.pauseCommand.addTarget { [weak self] _ in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + + if player.rate != 0 { + player.pause() + } + + return .success + } + + skipBackwardTarget = remoteCommandCenter.skipBackwardCommand.addTarget { + [weak self] _ in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + let newTime = + player.currentTime() + - CMTime(seconds: self.SEEK_INTERVAL_SECONDS, preferredTimescale: .max) + player.seek(to: newTime) + return .success + } + + skipForwardTarget = remoteCommandCenter.skipForwardCommand.addTarget { + [weak self] _ in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + + let newTime = + player.currentTime() + + CMTime(seconds: self.SEEK_INTERVAL_SECONDS, preferredTimescale: .max) + player.seek(to: newTime) + return .success + } + + playbackPositionTarget = remoteCommandCenter.changePlaybackPositionCommand + .addTarget { [weak self] event in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + if let event = event as? MPChangePlaybackPositionCommandEvent { + player.seek( + to: CMTime(seconds: event.positionTime, preferredTimescale: .max) + ) + return .success + } + return .commandFailed + } + + // Handler for togglePlayPauseCommand, sent by Apple's Earpods wired headphones + togglePlayPauseTarget = remoteCommandCenter.togglePlayPauseCommand.addTarget + { [weak self] _ in + guard let self, let player = self.currentPlayer else { + return .commandFailed + } + + if player.rate == 0 { + player.play() + } else { + player.pause() + } + + return .success + } + } + + private func invalidateCommandTargets() { + remoteCommandCenter.playCommand.removeTarget(playTarget) + remoteCommandCenter.pauseCommand.removeTarget(pauseTarget) + remoteCommandCenter.skipForwardCommand.removeTarget(skipForwardTarget) + remoteCommandCenter.skipBackwardCommand.removeTarget(skipBackwardTarget) + remoteCommandCenter.changePlaybackPositionCommand.removeTarget( + playbackPositionTarget + ) + remoteCommandCenter.togglePlayPauseCommand.removeTarget( + togglePlayPauseTarget + ) + } + + public func updateNowPlayingInfo() { + guard let player = currentPlayer, let currentItem = player.currentItem + else { + invalidateCommandTargets() + MPNowPlayingInfoCenter.default().nowPlayingInfo = [:] + return + } + + // commonMetadata is metadata from asset, externalMetadata is custom metadata set by user + // externalMetadata should override commonMetadata to allow override metadata from source + // When the metadata has the tag "iTunSMPB" or "iTunNORM" then the metadata is not converted correctly and comes [nil, nil, ...] + // This leads to a crash of the app + let metadata: [AVMetadataItem] = { + + let common = processMetadataItems(currentItem.asset.commonMetadata) + let external = processMetadataItems(currentItem.externalMetadata) + + return Array(common.merging(external) { _, new in new }.values) + }() + + let titleItem = + AVMetadataItem.metadataItems( + from: metadata, + filteredByIdentifier: .commonIdentifierTitle + ).first?.stringValue ?? "" + + let artistItem = + AVMetadataItem.metadataItems( + from: metadata, + filteredByIdentifier: .commonIdentifierArtist + ).first?.stringValue ?? "" + + // I have some issue with this - setting artworkItem when it not set dont return nil but also is crashing application + // this is very hacky workaround for it + let imgData = AVMetadataItem.metadataItems( + from: metadata, + filteredByIdentifier: .commonIdentifierArtwork + ).first?.dataValue + let image = imgData.flatMap { UIImage(data: $0) } ?? UIImage() + let artworkItem = MPMediaItemArtwork(boundsSize: image.size) { _ in image } + + let newNowPlayingInfo: [String: Any] = [ + MPMediaItemPropertyTitle: titleItem, + MPMediaItemPropertyArtist: artistItem, + MPMediaItemPropertyArtwork: artworkItem, + MPMediaItemPropertyPlaybackDuration: currentItem.duration.seconds, + MPNowPlayingInfoPropertyElapsedPlaybackTime: currentItem.currentTime() + .seconds.rounded(), + MPNowPlayingInfoPropertyPlaybackRate: player.rate, + MPNowPlayingInfoPropertyIsLiveStream: CMTIME_IS_INDEFINITE( + currentItem.asset.duration + ), + ] + let currentNowPlayingInfo = + MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:] + + MPNowPlayingInfoCenter.default().nowPlayingInfo = + currentNowPlayingInfo.merging(newNowPlayingInfo) { _, new in new } + } + + private func findNewCurrentPlayer() { + if let newPlayer = players.allObjects.first(where: { + $0.rate != 0 + }) { + setCurrentPlayer(player: newPlayer) + } + } + + // We will observe players rate to find last active player that info will be displayed + private func observePlayers(player: AVPlayer) -> NSKeyValueObservation { + return player.observe(\.rate) { [weak self] player, change in + guard let self else { return } + + let rate = change.newValue + + // case where there is new player that is not paused + // In this case event is triggered by non currentPlayer + if rate != 0 && self.currentPlayer != player { + self.setCurrentPlayer(player: player) + return + } + + // case where currentPlayer was paused + // In this case event is triggered by currentPlayer + if rate == 0 && self.currentPlayer == player { + self.findNewCurrentPlayer() + } + } + } + + private func processMetadataItems(_ items: [AVMetadataItem]) -> [String: + AVMetadataItem] + { + var result = [String: AVMetadataItem]() + + for item in items { + if let id = item.identifier?.rawValue, !id.isEmpty, result[id] == nil { + result[id] = item + } + } + + return result + } +} diff --git a/ios/core/Plugins/PluginsRegistry.swift b/ios/core/Plugins/PluginsRegistry.swift new file mode 100644 index 00000000..2b712a2c --- /dev/null +++ b/ios/core/Plugins/PluginsRegistry.swift @@ -0,0 +1,102 @@ +// +// PluginRegistry.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 22/07/2025. +// + +import AVFoundation +import Foundation + +public final class PluginsRegistry { + public static let shared = PluginsRegistry() + + // Plugin ID -> ReactNativeVideoPluginSpec + private var plugins: [String: ReactNativeVideoPluginSpec] = [:] + + // MARK: - Public API + + public func register(plugin: ReactNativeVideoPluginSpec) { + #if DEBUG + if hasPlugin(plugin: plugin) { + print( + "[ReactNativeVideo] Plugin \(plugin.name) (ID: \(plugin.id)) is already registered - overwriting." + ) + } else { + print( + "[ReactNativeVideo] Registering plugin \(plugin.name) (ID: \(plugin.id))." + ) + } + #endif + + plugins.updateValue(plugin, forKey: plugin.id) + } + + public func unregister(plugin: ReactNativeVideoPluginSpec) { + #if DEBUG + if !hasPlugin(plugin: plugin) { + print( + "[ReactNativeVideo] Plugin \(plugin.name) (ID: \(plugin.id)) is not registered - skipping." + ) + } else { + print("[ReactNativeVideo] Unregistering plugin \(plugin.name) (ID: \(plugin.id)).") + } + #endif + + plugins.removeValue(forKey: plugin.id) + } + + // MARK: - Internal API + + private func hasPlugin(plugin: ReactNativeVideoPluginSpec) -> Bool { + return plugins.contains { $0.value.id == plugin.id } + } + + internal func getDrmManager(source: NativeVideoPlayerSource) throws -> DRMManagerSpec? { + for plugin in plugins.values { + if let drmManager = plugin.getDRMManager(source: source) { + return drmManager + } + } + + throw LibraryError.DRMPluginNotFound.error() + } + + internal func overrideSource(source: NativeVideoPlayerSource) async + -> NativeVideoPlayerSource + { + var overriddenSource = source + + for plugin in plugins.values { + overriddenSource = await plugin.overrideSource(source: overriddenSource) + } + + return overriddenSource + } + + // MARK: - Notifications + + internal func notifyPlayerCreated(player: NativeVideoPlayer) { + for plugin in plugins.values { + plugin.onPlayerCreated(player: Weak(value: player)) + } + } + + internal func notifyPlayerDestroyed(player: NativeVideoPlayer) { + for plugin in plugins.values { + plugin.onPlayerDestroyed(player: Weak(value: player)) + } + } + + internal func notifyVideoViewCreated(view: VideoComponentView) { + for plugin in plugins.values { + plugin.onVideoViewCreated(view: Weak(value: view)) + } + } + + internal func notifyVideoViewDestroyed(view: VideoComponentView) { + for plugin in plugins.values { + plugin.onVideoViewDestroyed(view: Weak(value: view)) + } + } +} diff --git a/ios/core/Plugins/ReactNativeVideoPlugin.swift b/ios/core/Plugins/ReactNativeVideoPlugin.swift new file mode 100644 index 00000000..24a111e9 --- /dev/null +++ b/ios/core/Plugins/ReactNativeVideoPlugin.swift @@ -0,0 +1,91 @@ +// +// ReactNativeVideoPlugin.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 22/07/2025. +// + +import AVFoundation +import Foundation + +public protocol ReactNativeVideoPluginSpec { + /** + * The ID of the plugin. + */ + var id: String { get } + + /** + * The name of the plugin. + */ + var name: String { get } + + /** + * Called when a player is created. + * + * @param player The weak reference to the player instance. + */ + func onPlayerCreated(player: Weak) + + /** + * Called when a player is destroyed. + * + * @param player The weak reference to the player instance. + */ + func onPlayerDestroyed(player: Weak) + + /** + * Called when a video view is created. + * + * @param view The weak reference to the video view instance. + */ + func onVideoViewCreated(view: Weak) + + /** + * Called when a video view is destroyed. + * + * @param view The weak reference to the video view instance. + */ + func onVideoViewDestroyed(view: Weak) + + /** + * Called when a source is overridden. + * + * @param source The source instance. + * @return The overridden source instance. + */ + func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource + + /** + * Called when a DRM manager is requested. + * + * @param source The source instance. + * @return The DRM manager instance. + */ + func getDRMManager(source: NativeVideoPlayerSource) -> DRMManagerSpec? +} + +open class ReactNativeVideoPlugin: ReactNativeVideoPluginSpec { + public let id: String + public let name: String + + public init(name: String) { + self.name = name + self.id = "RNV_Plugin_\(name)" + + PluginsRegistry.shared.register(plugin: self) + } + + open func onPlayerCreated(player: Weak) { /* no-op */ } + open func onPlayerDestroyed(player: Weak) { /* no-op */ } + + open func onVideoViewCreated(view: Weak) { /* no-op */ } + open func onVideoViewDestroyed(view: Weak) { /* no-op */ } + + open func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource { + return source + } + + open func getDRMManager(source: NativeVideoPlayerSource) -> DRMManagerSpec? { + return nil + } +} diff --git a/ios/core/Spec/DRMManagerSpec.swift b/ios/core/Spec/DRMManagerSpec.swift new file mode 100644 index 00000000..105703b5 --- /dev/null +++ b/ios/core/Spec/DRMManagerSpec.swift @@ -0,0 +1,14 @@ +// +// DRMManagerSpec.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 05/08/2025. +// + +import Foundation +import AVFoundation + +public protocol DRMManagerSpec: AVContentKeySessionDelegate { + /// Creates a content key request for the given asset and DRM parameters. + func createContentKeyRequest(for asset: AVURLAsset, drmParams: NativeDrmParams) throws +} diff --git a/ios/core/Spec/NativeVideoPlayerSourceSpec.swift b/ios/core/Spec/NativeVideoPlayerSourceSpec.swift new file mode 100644 index 00000000..524d9f88 --- /dev/null +++ b/ios/core/Spec/NativeVideoPlayerSourceSpec.swift @@ -0,0 +1,36 @@ +// +// NativeVideoPlayerSourceSpec.swift +// react-native-video +// +// Created by Krzysztof Moch on 23/07/2025. +// + +import Foundation +import AVFoundation + +// Helper alias that allow to represet player source outside of module +public typealias NativeVideoPlayerSource = NativeVideoPlayerSourceSpec & HybridVideoPlayerSourceSpec + +public protocol NativeVideoPlayerSourceSpec { + // MARK: - Properties + + /// The underlying AVURLAsset instance + var asset: AVURLAsset? { get set } + + /// The URL of the video source + var url: URL { get } + + /// The memory size used by the source + var memorySize: Int { get } + + // MARK: - Methods + + /// Initialize the asset asynchronously + func initializeAsset() async throws + + /// Get non-null AVURLAsset instance (self.asset) + func getAsset() async throws -> AVURLAsset + + /// Release the asset resources + func releaseAsset() +} diff --git a/ios/core/Spec/NativeVideoPlayerSpec.swift b/ios/core/Spec/NativeVideoPlayerSpec.swift new file mode 100644 index 00000000..674ae58b --- /dev/null +++ b/ios/core/Spec/NativeVideoPlayerSpec.swift @@ -0,0 +1,42 @@ +// +// NativeVideoPlayerSpec.swift +// react-native-video +// +// Created by Krzysztof Moch on 09/10/2024. +// + +import Foundation +import AVFoundation + +// Helper alias that allow to represet player outside of module +public typealias NativeVideoPlayer = NativeVideoPlayerSpec & HybridVideoPlayerSpec + +public protocol NativeVideoPlayerSpec { + // MARK: - Properties + + /// The underlying AVPlayer instance (should not be used directly) + var player: AVPlayer { get set } + + /// The current player item + var playerItem: AVPlayerItem? { get set } + + /// The player observer for monitoring state changes + // var playerObserver: VideoPlayerObserver? { get set } + + /// Whether the player was auto-paused + var wasAutoPaused: Bool { get set } + + /// Whether the player is currently buffering + var isCurrentlyBuffering: Bool { get set } + + /// The memory size used by the player + var memorySize: Int { get } + + // MARK: - Methods + + /// Release the player resources + func release() + + /// Initialize the player item asynchronously + func initializePlayerItem() async throws -> AVPlayerItem +} diff --git a/ios/core/Utils/ExternalSubtitlesUtils.swift b/ios/core/Utils/ExternalSubtitlesUtils.swift new file mode 100644 index 00000000..ab175d11 --- /dev/null +++ b/ios/core/Utils/ExternalSubtitlesUtils.swift @@ -0,0 +1,119 @@ +import AVFoundation +import ObjectiveC + +private var HLSSubtitleInjectorAssociatedKey: UInt8 = 0 + +enum ExternalSubtitlesUtils { + static func isSubtitleTypeSupported(subtitle: NativeExternalSubtitle) -> Bool { + if subtitle.type == .vtt { + return true + } + + if let url = URL(string: subtitle.uri), url.pathExtension == "vtt" { + return true + } + + return false + } + + static func createCompositionWithExternalSubtitles( + for asset: AVURLAsset, + config: NativeVideoConfig + ) async throws -> AVPlayerItem { + let subtitlesAssets = try config.externalSubtitles?.map { subtitle in + guard let url = URL(string: subtitle.uri) else { + throw PlayerError.invalidTrackUrl(url: subtitle.uri).error() + } + + return AVURLAsset(url: url) + } + + do { + let mainVideoTracks = asset.tracks(withMediaType: .video) + let mainAudioTracks = asset.tracks(withMediaType: .audio) + let textTracks = + subtitlesAssets?.flatMap { $0.tracks(withMediaType: .text) } ?? [] + + let composition = AVMutableComposition() + + if let videoTrack = mainVideoTracks.first(where: { $0.mediaType == .video }){ + if let compositionVideoTrack = composition.addMutableTrack( + withMediaType: .video, + preferredTrackID: kCMPersistentTrackID_Invalid + ) { + try compositionVideoTrack.insertTimeRange( + CMTimeRange(start: .zero, duration: videoTrack.timeRange.duration), + of: videoTrack, + at: .zero + ) + } + } + + if let audioTrack = mainAudioTracks.first(where: { $0.mediaType == .audio }) { + if let compositionAudioTrack = composition.addMutableTrack( + withMediaType: .audio, + preferredTrackID: kCMPersistentTrackID_Invalid + ) { + try compositionAudioTrack.insertTimeRange( + CMTimeRange(start: .zero, duration: audioTrack.timeRange.duration), + of: audioTrack, + at: .zero + ) + } + } + + for textTrack in textTracks { + if let compositionTextTrack = composition.addMutableTrack( + withMediaType: .text, + preferredTrackID: kCMPersistentTrackID_Invalid + ) { + try compositionTextTrack.insertTimeRange( + CMTimeRange(start: .zero, duration: textTrack.timeRange.duration), + of: textTrack, + at: .zero + ) + + compositionTextTrack.languageCode = textTrack.languageCode + compositionTextTrack.isEnabled = true + } + } + + return await AVPlayerItem(asset: composition) + } + } + + static func modifyStreamManifestWithExternalSubtitles( + for asset: AVURLAsset, + config: NativeVideoConfig + ) async throws -> AVPlayerItem { + guard let externalSubtitles = config.externalSubtitles, + !externalSubtitles.isEmpty + else { + return AVPlayerItem(asset: asset) + } + + let supportedSubtitles = externalSubtitles.filter { subtitle in + isSubtitleTypeSupported(subtitle: subtitle) + } + + guard !supportedSubtitles.isEmpty else { + return AVPlayerItem(asset: asset) + } + + let subtitleInjector = HLSSubtitleInjector( + manifestUrl: asset.url, + externalSubtitles: supportedSubtitles + ) + let modifiedAsset = subtitleInjector.createModifiedAsset() + let playerItem = AVPlayerItem(asset: modifiedAsset) + + objc_setAssociatedObject( + playerItem, + &HLSSubtitleInjectorAssociatedKey, + subtitleInjector, + .OBJC_ASSOCIATION_RETAIN_NONATOMIC + ) + + return playerItem + } +} diff --git a/ios/core/Utils/HLSManifestParser.swift b/ios/core/Utils/HLSManifestParser.swift new file mode 100644 index 00000000..757fab51 --- /dev/null +++ b/ios/core/Utils/HLSManifestParser.swift @@ -0,0 +1,170 @@ +import AVFoundation +import Foundation +import NitroModules + +class HLSManifestParser { + + /// Downloads manifest content from the given URL + static func downloadManifest(from url: URL) async throws -> String { + let (data, response) = try await URLSession.shared.data(from: url) + + guard let httpResponse = response as? HTTPURLResponse, + 200...299 ~= httpResponse.statusCode + else { + throw SourceError.invalidUri(uri: url.absoluteString).error() + } + + guard let manifestContent = String(data: data, encoding: .utf8) else { + throw SourceError.invalidUri(uri: url.absoluteString).error() + } + + return manifestContent + } + + /// Converts relative URLs in a manifest line to absolute URLs + static func convertRelativeURLsToAbsolute(line: String, baseURL: URL) -> String { + let trimmedLine = line.trimmingCharacters(in: .whitespaces) + + if trimmedLine.isEmpty { + return line + } + + if trimmedLine.hasPrefix("#") { + if trimmedLine.contains("URI=") { + return convertURIParametersToAbsolute(line: line, baseURL: baseURL) + } + return line + } + + if !trimmedLine.hasPrefix("http://") && !trimmedLine.hasPrefix("https://") { + let absoluteURL = baseURL.appendingPathComponent(trimmedLine) + return absoluteURL.absoluteString + } + + return line + } + + /// Converts URI parameters in manifest lines to absolute URLs + static func convertURIParametersToAbsolute(line: String, baseURL: URL) -> String { + var modifiedLine = line + let uriPattern = #"URI="([^"]+)""# + + guard let regex = try? NSRegularExpression(pattern: uriPattern, options: []) + else { + return line + } + + let nsLine = line as NSString + let matches = regex.matches( + in: line, + options: [], + range: NSRange(location: 0, length: nsLine.length) + ) + + for match in matches.reversed() { + if match.numberOfRanges >= 2 { + let uriRange = match.range(at: 1) + let uri = nsLine.substring(with: uriRange) + + if !uri.hasPrefix("http://") && !uri.hasPrefix("https://") { + let absoluteURL = baseURL.appendingPathComponent(uri) + let fullRange = match.range(at: 0) + let replacement = "URI=\"\(absoluteURL.absoluteString)\"" + modifiedLine = (modifiedLine as NSString).replacingCharacters( + in: fullRange, + with: replacement + ) + } + } + } + + return modifiedLine + } + + /// Parses M3U8 manifest content and returns parsed information + static func parseM3U8Manifest(_ content: String) throws -> HLSManifestInfo { + let lines = content.components(separatedBy: .newlines) + var info = HLSManifestInfo() + + for line in lines { + let trimmedLine = line.trimmingCharacters(in: .whitespaces) + + if trimmedLine.hasPrefix("#EXTM3U") { + info.isValid = true + } + + // Parse version + if trimmedLine.hasPrefix("#EXT-X-VERSION:") { + let versionString = String(trimmedLine.dropFirst("#EXT-X-VERSION:".count)) + info.version = Int(versionString) + } + + // Parse stream info for resolution + if trimmedLine.hasPrefix("#EXT-X-STREAM-INF:") { + let streamInfo = parseStreamInf(trimmedLine) + info.streams.append(streamInfo) + } + } + + if !info.isValid { + throw SourceError.invalidUri(uri: "Invalid M3U8 format").error() + } + + return info + } + + /// Parses EXT-X-STREAM-INF line to extract stream information + private static func parseStreamInf(_ line: String) -> HLSStreamInfo { + var streamInfo = HLSStreamInfo() + + // Parse RESOLUTION + if let resolutionRange = line.range(of: "RESOLUTION=") { + let afterResolution = line[resolutionRange.upperBound...] + if let commaRange = afterResolution.range(of: ",") { + let resolutionValue = String(afterResolution[..` class is designed to hold a weak reference to an object of type `T`. +/// This is particularly useful in scenarios where strong references could lead to retain cycles +/// or memory leaks, such as in plugin systems or delegate patterns. +/// +/// - Note: The `value` property provides access to the referenced object, or `nil` if the object has been deallocated. +public class Weak { + private weak var _value: AnyObject? + public var value: T? { + return _value as? T + } + + public init(value: T) { + _value = value as AnyObject + } +} diff --git a/ios/core/VideoError.swift b/ios/core/VideoError.swift new file mode 100644 index 00000000..a585e72d --- /dev/null +++ b/ios/core/VideoError.swift @@ -0,0 +1,159 @@ +// +// VideoFileHelper.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 24/01/2025. +// + +import Foundation +import NitroModules + +// MARK: - LibraryError +enum LibraryError: VideoError { + case deallocated(objectName: String) + case DRMPluginNotFound + + var code: String { + switch self { + case .deallocated: + return "library/deallocated" + case .DRMPluginNotFound: + return "library/drm-plugin-not-found" + } + } + + var message: String { + switch self { + case let .deallocated(objectName: objectName): + return "Object \(objectName) has been deallocated" + case .DRMPluginNotFound: + return "No DRM plugin have been found, please add one to the project" + } + } +} + +// MARK: - PlayerError +enum PlayerError: VideoError { + case notInitialized + case assetNotInitialized + case invalidSource + case invalidTrackUrl(url: String) + + var code: String { + switch self { + case .notInitialized: + return "player/not-initialized" + case .assetNotInitialized: + return "player/asset-not-initialized" + case .invalidSource: + return "player/invalid-source" + case .invalidTrackUrl: + return "player/invalid-track-url" + } + } + + var message: String { + switch self { + case .notInitialized: + return "Player has not been initialized (Or has been set to nil)" + case .assetNotInitialized: + return "Asset has not been initialized (Or has been set to nil)" + case .invalidSource: + return "Invalid source passed to player" + case let .invalidTrackUrl(url: url): + return "Invalid track URL: \(url)" + } + } +} + +// MARK: - SourceError +enum SourceError: VideoError { + case invalidUri(uri: String) + case missingReadFilePermission(uri: String) + case fileDoesNotExist(uri: String) + case failedToInitializeAsset + case unsupportedContentType(uri: String) + + var code: String { + switch self { + case .invalidUri: + return "source/invalid-uri" + case .missingReadFilePermission: + return "source/missing-read-file-permission" + case .fileDoesNotExist: + return "source/file-does-not-exist" + case .failedToInitializeAsset: + return "source/failed-to-initialize-asset" + case .unsupportedContentType: + return "source/unsupported-content-type" + } + } + + var message: String { + switch self { + case let .invalidUri(uri: uri): + return "Invalid source file uri: \(uri)" + case let .missingReadFilePermission(uri: uri): + return "Missing read file permission for source file at \(uri)" + case let .fileDoesNotExist(uri: uri): + return "File does not exist at URI: \(uri)" + case .failedToInitializeAsset: + return "Failed to initialize asset" + case let .unsupportedContentType(uri: uri): + return "type of content (\(uri)) is not supported" + } + } +} + +// MARK: - VideoViewError +enum VideoViewError: VideoError { + case viewNotFound(nitroId: Double) + case viewIsDeallocated + case pictureInPictureNotSupported + + var code: String { + switch self { + case .viewNotFound: + return "view/not-found" + case .viewIsDeallocated: + return "view/deallocated" + case .pictureInPictureNotSupported: + return "view/picture-in-picture-not-supported" + } + } + + var message: String { + switch self { + case let .viewNotFound(nitroId: nitroId): + return "View with nitroId \(nitroId) not found" + case .viewIsDeallocated: + return "Attempt to access a view, but it has been deallocated (or not initialized)" + case .pictureInPictureNotSupported: + return "Picture in picture is not supported on this device" + } + } +} + +// MARK: - UnknownError +struct UnknownError: VideoError { + var code: String { "unknown/unknown" } + var message: String { "Unknown error" } +} + +// MARK: - VideoError +protocol VideoError { + var code: String { get } + var message: String { get } +} + +extension VideoError { + private func getMessage() -> String { + return "{%@\(code)::\(message)@%}" + } + + func error() -> Error { + return RuntimeError.error(withMessage: getMessage()) + } +} + + diff --git a/ios/core/VideoFileHelper.swift b/ios/core/VideoFileHelper.swift new file mode 100644 index 00000000..3f656e88 --- /dev/null +++ b/ios/core/VideoFileHelper.swift @@ -0,0 +1,48 @@ +// +// VideoFileHelper.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/01/2025. +// + +import Foundation +import NitroModules + +enum VideoFileHelper { + private static let fileManager = FileManager.default + + static func getFileSize(for url: URL) async throws -> Int64 { + if url.isFileURL { + return try getLocalFileSize(for: url) + } + return try await getRemoteFileSize(for: url) + } + + static func validateReadPermission(for url: URL) throws { + guard url.isFileURL else { return } + + if !fileManager.isReadableFile(atPath: url.path) { + throw SourceError.missingReadFilePermission(uri: url.path).error() + } + } + + // MARK: - Private + + private static func getLocalFileSize(for url: URL) throws -> Int64 { + Int64(try url.resourceValues(forKeys: [.fileSizeKey]).fileSize ?? -1) + } + + private static func getRemoteFileSize(for url: URL) async throws -> Int64 { + var request = URLRequest(url: url) + request.httpMethod = "HEAD" + + let (_, response) = try await URLSession.shared.data(for: request) + guard let httpResponse = response as? HTTPURLResponse, + let contentLength = httpResponse.allHeaderFields["Content-Length"] as? String, + let size = Int64(contentLength) else { + return -1 + } + + return size + } +} diff --git a/ios/core/VideoManager.swift b/ios/core/VideoManager.swift new file mode 100644 index 00000000..c89b52a3 --- /dev/null +++ b/ios/core/VideoManager.swift @@ -0,0 +1,412 @@ +// +// VideoManager.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 27/04/2025. +// + +import Foundation +import AVFoundation + +class VideoManager { + // MARK: - Singleton + static let shared = VideoManager() + + private var players = NSHashTable.weakObjects() + private var videoView = NSHashTable.weakObjects() + + private var isAudioSessionActive = false + private var remoteControlEventsActive = false + + // TODO: Create Global Config, and expose it there + private var isAudioSessionManagementDisabled: Bool = false + + private init() { + // Subscribe to audio interruption notifications + NotificationCenter.default.addObserver( + self, + selector: #selector(handleAudioSessionInterruption), + name: AVAudioSession.interruptionNotification, + object: nil + ) + + // Subscribe to route change notifications + NotificationCenter.default.addObserver( + self, + selector: #selector(handleAudioRouteChange), + name: AVAudioSession.routeChangeNotification, + object: nil + ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(applicationWillResignActive(notification:)), + name: UIApplication.willResignActiveNotification, + object: nil + ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(applicationDidBecomeActive(notification:)), + name: UIApplication.didBecomeActiveNotification, + object: nil + ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(applicationDidEnterBackground(notification:)), + name: UIApplication.didEnterBackgroundNotification, + object: nil + ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(applicationWillEnterForeground(notification:)), + name: UIApplication.willEnterForegroundNotification, + object: nil + ) + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + // MARK: - public + + func register(player: HybridVideoPlayer) { + players.add(player) + PluginsRegistry.shared.notifyPlayerCreated(player: player) + } + + func unregister(player: HybridVideoPlayer) { + players.remove(player) + PluginsRegistry.shared.notifyPlayerDestroyed(player: player) + } + + func register(view: VideoComponentView) { + videoView.add(view) + } + + func unregister(view: VideoComponentView) { + videoView.remove(view) + } + + func requestAudioSessionUpdate() { + updateAudioSessionConfiguration() + } + + // MARK: - Remote Control Events + func setRemoteControlEventsActive(_ active: Bool) { + if isAudioSessionManagementDisabled || remoteControlEventsActive == active { + return + } + + remoteControlEventsActive = active + requestAudioSessionUpdate() + } + + // MARK: - Audio Session Management + private func activateAudioSession() { + if isAudioSessionActive { + return + } + + do { + try AVAudioSession.sharedInstance().setActive(true) + isAudioSessionActive = true + } catch { + print("Failed to activate audio session: \(error.localizedDescription)") + } + } + + private func deactivateAudioSession() { + if !isAudioSessionActive { + return + } + + do { + try AVAudioSession.sharedInstance().setActive( + false, options: .notifyOthersOnDeactivation + ) + isAudioSessionActive = false + } catch { + print("Failed to deactivate audio session: \(error.localizedDescription)") + } + } + + private func updateAudioSessionConfiguration() { + let isAnyPlayerPlaying = players.allObjects.contains { hybridPlayer in + hybridPlayer.player.isMuted == false && hybridPlayer.player.rate != 0 + } + + let anyPlayerNeedsNotMixWithOthers = players.allObjects.contains { player in + player.mixAudioMode == .donotmix + } + + let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in + player.showNotificationControls + } + + if isAnyPlayerPlaying || anyPlayerNeedsNotMixWithOthers || anyPlayerNeedsNotificationControls || remoteControlEventsActive { + activateAudioSession() + } else { + deactivateAudioSession() + } + + configureAudioSession() + } + + private func configureAudioSession() { + let audioSession = AVAudioSession.sharedInstance() + var audioSessionCategoryOptions: AVAudioSession.CategoryOptions = audioSession.categoryOptions + + let anyViewNeedsPictureInPicture = videoView.allObjects.contains { view in + view.allowsPictureInPicturePlayback + } + + let anyPlayerNeedsSilentSwitchObey = players.allObjects.contains { player in + player.ignoreSilentSwitchMode == .obey + } + + let anyPlayerNeedsSilentSwitchIgnore = players.allObjects.contains { player in + player.ignoreSilentSwitchMode == .ignore + } + + let anyPlayerNeedsBackgroundPlayback = players.allObjects.contains { player in + player.playInBackground + } + + let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in + player.showNotificationControls + } + + if isAudioSessionManagementDisabled { + return + } + + let category: AVAudioSession.Category = determineAudioCategory( + silentSwitchObey: anyPlayerNeedsSilentSwitchObey, + silentSwitchIgnore: anyPlayerNeedsSilentSwitchIgnore, + earpiece: false, // TODO: Pass actual value after we add prop + pip: anyViewNeedsPictureInPicture, + backgroundPlayback: anyPlayerNeedsBackgroundPlayback, + notificationControls: anyPlayerNeedsNotificationControls + ) + + let audioMixingMode = determineAudioMixingMode() + + switch audioMixingMode { + case .mixwithothers: + audioSessionCategoryOptions.insert(.mixWithOthers) + case .donotmix: + audioSessionCategoryOptions.remove(.mixWithOthers) + case .duckothers: + audioSessionCategoryOptions.insert(.duckOthers) + case .auto: + audioSessionCategoryOptions.remove(.mixWithOthers) + audioSessionCategoryOptions.remove(.duckOthers) + } + + do { + try audioSession.setCategory(category, mode: .moviePlayback, options: audioSessionCategoryOptions) + } catch { + print("ReactNativeVideo: Failed to set audio session category: \(error.localizedDescription)") + } + } + + private func determineAudioCategory( + silentSwitchObey: Bool, + silentSwitchIgnore: Bool, + earpiece: Bool, + pip: Bool, + backgroundPlayback: Bool, + notificationControls: Bool + ) -> AVAudioSession.Category { + // Handle conflicting settings + if silentSwitchObey && silentSwitchIgnore { + print( + "Warning: Conflicting ignoreSilentSwitch settings found (obey vs ignore) - defaulting to ignore" + ) + return .playback + } + + // PiP, background playback, or notification controls require playback category + if pip || backgroundPlayback || notificationControls || remoteControlEventsActive { + if silentSwitchObey { + print( + "Warning: ignoreSilentSwitch=obey cannot be used with PiP, backgroundPlayback, or notification controls - using playback category" + ) + } + + if earpiece { + print( + "Warning: audioOutput=earpiece cannot be used with PiP, backgroundPlayback, or notification controls - using playback category" + ) + } + + // Set up background playback policy if needed + if backgroundPlayback { + players.allObjects.forEach { player in + if player.playInBackground { + player.player.audiovisualBackgroundPlaybackPolicy = .continuesIfPossible + } else { + player.player.audiovisualBackgroundPlaybackPolicy = .pauses + } + } + } + + return .playback + } + + // Earpiece requires playAndRecord + if earpiece { + if silentSwitchObey { + print( + "Warning: audioOutput=earpiece cannot be used with ignoreSilentSwitch=obey - using playAndRecord category" + ) + } + return .playAndRecord + } + + // Honor silent switch if requested + if silentSwitchObey { + return .ambient + } + + // Default to playback for most cases + return .playback + } + + func determineAudioMixingMode() -> MixAudioMode { + let activePlayers = players.allObjects.filter { player in + player.isPlaying && player.player.isMuted != true + } + + if activePlayers.isEmpty { + return .mixwithothers + } + + let anyPlayerNeedsMixWithOthers = activePlayers.contains { player in + player.mixAudioMode == .mixwithothers + } + + let anyPlayerNeedsNotMixWithOthers = activePlayers.contains { player in + player.mixAudioMode == .donotmix + } + + let anyPlayerNeedsDucksOthers = activePlayers.contains { player in + player.mixAudioMode == .duckothers + } + + let anyPlayerHasAutoMixAudioMode = activePlayers.contains { player in + player.mixAudioMode == .auto + } + + if anyPlayerNeedsNotMixWithOthers { + return .donotmix + } + + if anyPlayerHasAutoMixAudioMode { + return .auto + } + + if anyPlayerNeedsDucksOthers { + return .duckothers + } + + return .mixwithothers + } + + + // MARK: - Notification Handlers + + @objc + private func handleAudioSessionInterruption(notification: Notification) { + guard let userInfo = notification.userInfo, + let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt, + let type = AVAudioSession.InterruptionType(rawValue: typeValue) + else { + return + } + + switch type { + case .began: + // Audio session interrupted, nothing to do as players will pause automatically + break + + case .ended: + // Interruption ended, check if we should resume audio session + if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt { + let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue) + if options.contains(.shouldResume) { + updateAudioSessionConfiguration() + } + } + + @unknown default: + break + } + } + + @objc + private func handleAudioRouteChange(notification: Notification) { + guard let userInfo = notification.userInfo, + let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, + let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) + else { + return + } + + switch reason { + case .categoryChange, .override, .wakeFromSleep, .newDeviceAvailable, .oldDeviceUnavailable: + // Reconfigure audio session when route changes + updateAudioSessionConfiguration() + default: + break + } + } + + @objc func applicationWillResignActive(notification: Notification) { + // Pause all players when the app is about to become inactive + for player in players.allObjects { + if player.playInBackground || player.playWhenInactive || !player.isPlaying || player.player.isExternalPlaybackActive == true { + continue + } + + try? player.pause() + player.wasAutoPaused = true + } + } + + @objc func applicationDidBecomeActive(notification: Notification) { + // Resume all players when the app becomes active + for player in players.allObjects { + if player.wasAutoPaused { + try? player.play() + player.wasAutoPaused = false + } + } + } + + @objc func applicationDidEnterBackground(notification: Notification) { + // Pause all players when the app enters background + for player in players.allObjects { + if player.playInBackground || player.player.isExternalPlaybackActive == true || !player.isPlaying { + continue + } + + try? player.pause() + player.wasAutoPaused = true + } + } + + @objc func applicationWillEnterForeground(notification: Notification) { + // Resume all players when the app enters foreground + for player in players.allObjects { + if player.wasAutoPaused { + try? player.play() + player.wasAutoPaused = false + } + } + } +} diff --git a/ios/core/VideoPlayerObserver.swift b/ios/core/VideoPlayerObserver.swift new file mode 100644 index 00000000..fbc93833 --- /dev/null +++ b/ios/core/VideoPlayerObserver.swift @@ -0,0 +1,294 @@ +// +// VideoPlayerObserver.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 15/04/2025. +// + +import Foundation +import AVFoundation + +protocol VideoPlayerObserverDelegate: AnyObject { + func onPlayedToEnd(player: AVPlayer) + func onPlayerItemChange(player: AVPlayer, playerItem: AVPlayerItem?) + func onPlayerItemWillChange(hasNewPlayerItem: Bool) + func onTextTrackDataChanged(texts: [NSAttributedString]) + func onTimedMetadataChanged(timedMetadata: [AVMetadataItem]) + func onRateChanged(rate: Float) + func onPlaybackBufferEmpty() + func onPlaybackLikelyToKeepUp() + func onVolumeChanged(volume: Float) + func onExternalPlaybackActiveChanged(isActive: Bool) + func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus) + func onPlayerStatusChanged(status: AVPlayer.Status) + func onPlayerItemStatusChanged(status: AVPlayerItem.Status) + func onBandwidthUpdate(bitrate: Double) + func onProgressUpdate(currentTime: Double, bufferDuration: Double) +} + +extension VideoPlayerObserverDelegate { + func onPlayedToEnd(player: AVPlayer) {} + func onPlayerItemChange(player: AVPlayer, playerItem: AVPlayerItem?) {} + func onPlayerItemWillChange(hasNewPlayerItem: Bool) {} + func onTextTrackDataChanged(texts: [NSAttributedString]) {} + func onTimedMetadataChanged(timedMetadata: [AVMetadataItem]) {} + func onRateChanged(rate: Float) {} + func onPlaybackBufferEmpty() {} + func onPlaybackLikelyToKeepUp() {} + func onVolumeChanged(volume: Float) {} + func onExternalPlaybackActiveChanged(isActive: Bool) {} + func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus) {} + func onPlayerStatusChanged(status: AVPlayer.Status) {} + func onPlayerItemStatusChanged(status: AVPlayerItem.Status) {} + func onBandwidthUpdate(bitrate: Double) {} + func onProgressUpdate(currentTime: Double, bufferDuration: Double) {} +} + +class VideoPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate, AVPlayerItemLegibleOutputPushDelegate { + private weak var delegate: HybridVideoPlayer? + var player: AVPlayer? { + delegate?.player + } + + // Player observers + var playerCurrentItemObserver: NSKeyValueObservation? + var playerRateObserver: NSKeyValueObservation? + var playerTimeControlStatusObserver: NSKeyValueObservation? + var playerExternalPlaybackActiveObserver: NSKeyValueObservation? + var playerVolumeObserver: NSKeyValueObservation? + var playerTimedMetadataObserver: NSKeyValueObservation? + var playerStatusObserver: NSKeyValueObservation? + var playerProgressPeriodicObserver: Any? + + // Player item observers + var playbackEndedObserver: NSObjectProtocol? + var playbackBufferEmptyObserver: NSKeyValueObservation? + var playbackLikelyToKeepUpObserver: NSKeyValueObservation? + var playbackBufferFullObserver: NSKeyValueObservation? + var playerItemStatusObserver: NSKeyValueObservation? + var playerItemAccessLogObserver: NSObjectProtocol? + + var metadataOutput: AVPlayerItemMetadataOutput? + var legibleOutput: AVPlayerItemLegibleOutput? + + init(delegate: HybridVideoPlayer) { + self.delegate = delegate + } + + deinit { + invalidatePlayerObservers() + invalidatePlayerItemObservers() + } + + public func updatePlayerObservers() { + invalidatePlayerItemObservers() + invalidatePlayerObservers() + + initializePlayerObservers() + } + + func initializePlayerObservers() { + guard let player else { + return + } + + playerCurrentItemObserver = player.observe(\.currentItem, options: [.new, .old]) { [weak self] _, change in + self?.onPlayerCurrentItemChanged(player: player, change: change) + } + + playerRateObserver = player.observe(\.rate, options: [.new]) { [weak self] _, change in + guard let rate = change.newValue else { return } + self?.delegate?.onRateChanged(rate: rate) + } + + playerTimeControlStatusObserver = player.observe(\.timeControlStatus, options: [.new]) { [weak self] _, change in + guard let status = change.newValue else { return } + self?.delegate?.onTimeControlStatusChanged(status: status) + } + + playerExternalPlaybackActiveObserver = player.observe(\.isExternalPlaybackActive, options: [.new]) { [weak self] _, change in + guard let isActive = change.newValue else { return } + self?.delegate?.onExternalPlaybackActiveChanged(isActive: isActive) + } + + playerVolumeObserver = player.observe(\.volume, options: [.new]) { [weak self] _, change in + guard let volume = change.newValue else { return } + self?.delegate?.onVolumeChanged(volume: volume) + } + + playerStatusObserver = player.observe(\.status, options: [.new]) { [weak self] _, change in + guard let status = change.newValue else { return } + self?.delegate?.onPlayerStatusChanged(status: status) + } + + // 500ms interval TODO: Make this configurable + let interval = CMTime(seconds: 0.5, preferredTimescale: 600) + playerProgressPeriodicObserver = player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] _ in + guard let self, let player = self.player, let delegate = self.delegate else { return } + + delegate.onProgressUpdate(currentTime: player.currentTime().seconds, bufferDuration: player.currentItem?.getbufferDuration() ?? 0) + } + } + + private func initializePlayerItemObservers(player: AVPlayer, playerItem: AVPlayerItem) { + playbackEndedObserver = NotificationCenter.default.addObserver( + forName: .AVPlayerItemDidPlayToEndTime, + object: playerItem, + queue: nil + ) { [weak self] notification in + self?.delegate?.onPlayedToEnd(player: player) + } + + playerItemAccessLogObserver = NotificationCenter.default.addObserver( + forName: .AVPlayerItemNewAccessLogEntry, + object: playerItem, + queue: nil + ) { [weak self] notification in + self?.onPlayerAccessLog(playerItem: playerItem) + } + + setupBufferObservers(for: playerItem) + + playerItemStatusObserver = playerItem.observe(\.status, options: [.new]) { [weak self] _, change in + self?.delegate?.onPlayerItemStatusChanged(status: playerItem.status) + } + + let metadataOutput = AVPlayerItemMetadataOutput() + playerItem.add(metadataOutput) + metadataOutput.setDelegate(self, queue: .global(qos: .userInteractive)) + + let legibleOutput = AVPlayerItemLegibleOutput() + playerItem.add(legibleOutput) + metadataOutput.setDelegate(self, queue: .global(qos: .userInteractive)) + } + + private func invalidatePlayerItemObservers() { + // Remove NotificationCenter observers + if let playbackEndedObserver = playbackEndedObserver { + NotificationCenter.default.removeObserver(playbackEndedObserver) + self.playbackEndedObserver = nil + } + if let playerItemAccessLogObserver = playerItemAccessLogObserver { + NotificationCenter.default.removeObserver(playerItemAccessLogObserver) + self.playerItemAccessLogObserver = nil + } + // Invalidate KVO observers + clearBufferObservers() + playerItemStatusObserver?.invalidate() + playerItemStatusObserver = nil + // Remove outputs if needed + // (Assumes outputs are not shared between items) + if let playerItem = player?.currentItem { + if let metadataOutput = metadataOutput { + playerItem.remove(metadataOutput) + } + if let legibleOutput = legibleOutput { + playerItem.remove(legibleOutput) + } + } + metadataOutput = nil + legibleOutput = nil + } + + func invalidatePlayerObservers() { + // Invalidate KVO observers + playerCurrentItemObserver?.invalidate() + playerCurrentItemObserver = nil + playerRateObserver?.invalidate() + playerRateObserver = nil + playerTimeControlStatusObserver?.invalidate() + playerTimeControlStatusObserver = nil + playerExternalPlaybackActiveObserver?.invalidate() + playerExternalPlaybackActiveObserver = nil + playerVolumeObserver?.invalidate() + playerVolumeObserver = nil + playerStatusObserver?.invalidate() + playerStatusObserver = nil + // Remove periodic time observer from player + if let player = player, let periodicObserver = playerProgressPeriodicObserver { + player.removeTimeObserver(periodicObserver) + playerProgressPeriodicObserver = nil + } + } + + // MARK: - AVPlayerItemLegibleOutputPushDelegate + public func legibleOutput(_: AVPlayerItemLegibleOutput, + didOutputAttributedStrings strings: [NSAttributedString], + nativeSampleBuffers _: [Any], + forItemTime _: CMTime) { + delegate?.onTextTrackDataChanged(texts: strings) + } + + // MARK: - AVPlayerItemMetadataOutputPushDelegate + public func metadataOutput(_: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from _: AVPlayerItemTrack?) { + for metadataGroup in groups { + delegate?.onTimedMetadataChanged(timedMetadata: metadataGroup.items) + } + } + + // MARK: - AVPlayer Observers + func onPlayerCurrentItemChanged(player: AVPlayer, change: NSKeyValueObservedChange) { + let newPlayerItem = change.newValue?.flatMap { $0 } + + // Remove observers for old player item + invalidatePlayerItemObservers() + + // Notify delegate about player item state change + delegate?.onPlayerItemWillChange(hasNewPlayerItem: newPlayerItem != nil) + + if let playerItem = newPlayerItem { + // Initialize observers for new player item + initializePlayerItemObservers(player: player, playerItem: playerItem) + + delegate?.onPlayerItemChange(player: player, playerItem: playerItem) + } + } + + // MARK: - AVPlayerItem Observers + func onPlayerAccessLog(playerItem: AVPlayerItem) { + guard let accessLog = playerItem.accessLog() else { return } + guard let lastEvent = accessLog.events.last else { return } + + delegate?.onBandwidthUpdate(bitrate: lastEvent.indicatedBitrate) + } + + // MARK: - Buffer State Management + + func setupBufferObservers(for playerItem: AVPlayerItem) { + clearBufferObservers() + + // Observe buffer empty - this indicates definite buffering + playbackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .initial]) { [weak self] playerItem, change in + let isEmpty = change.newValue ?? playerItem.isPlaybackBufferEmpty + if isEmpty { + self?.delegate?.onPlaybackBufferEmpty() + } + } + + // Observe likely to keep up - this indicates that buffering has finished + playbackLikelyToKeepUpObserver = playerItem.observe(\.isPlaybackLikelyToKeepUp, options: [.new, .initial]) { [weak self] playerItem, change in + let isLikelyToKeepUp = change.newValue ?? playerItem.isPlaybackLikelyToKeepUp + if isLikelyToKeepUp { + self?.delegate?.onPlaybackLikelyToKeepUp() + } + } + + // Observe buffer full as an additional signal + playbackBufferFullObserver = playerItem.observe(\.isPlaybackBufferFull, options: [.new, .initial]) { [weak self] playerItem, change in + let isFull = change.newValue ?? playerItem.isPlaybackBufferFull + if isFull { + self?.delegate?.onPlaybackLikelyToKeepUp() + } + } + } + + func clearBufferObservers() { + playbackBufferEmptyObserver?.invalidate() + playbackBufferFullObserver?.invalidate() + playbackLikelyToKeepUpObserver?.invalidate() + + playbackBufferEmptyObserver = nil + playbackBufferFullObserver = nil + playbackLikelyToKeepUpObserver = nil + } +} diff --git a/ios/hybrids/VideoPlayer/HybridVideoPlayer+Events.swift b/ios/hybrids/VideoPlayer/HybridVideoPlayer+Events.swift new file mode 100644 index 00000000..3db4bc7b --- /dev/null +++ b/ios/hybrids/VideoPlayer/HybridVideoPlayer+Events.swift @@ -0,0 +1,184 @@ +// +// HybridVideoPlayer+Events.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 02/05/2025. +// + +import Foundation +import AVFoundation + +extension HybridVideoPlayer: VideoPlayerObserverDelegate { + // MARK: - VideoPlayerObserverDelegate + + func onPlayedToEnd(player: AVPlayer) { + eventEmitter.onEnd() + + if loop { + currentTime = 0 + try? play() + } + } + + func onRateChanged(rate: Float) { + eventEmitter.onPlaybackRateChange(Double(rate)) + NowPlayingInfoCenterManager.shared.updateNowPlayingInfo() + updateAndEmitPlaybackState() + } + + func onVolumeChanged(volume: Float) { + eventEmitter.onVolumeChange(onVolumeChangeData( + volume: Double(volume), + muted: muted + )) + } + + func onPlaybackBufferEmpty() { + isCurrentlyBuffering = true + status = .loading + updateAndEmitPlaybackState() + } + + func onProgressUpdate(currentTime: Double, bufferDuration: Double) { + eventEmitter.onProgress(.init(currentTime: currentTime, bufferDuration: bufferDuration)) + } + + func onPlaybackLikelyToKeepUp() { + isCurrentlyBuffering = false + if player.timeControlStatus == .playing { + status = .readytoplay + } + updateAndEmitPlaybackState() + } + + func onExternalPlaybackActiveChanged(isActive: Bool) { + eventEmitter.onExternalPlaybackChange(isActive) + } + + func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus) { + if player.status == .failed || playerItem?.status == .failed { + self.status = .error + isCurrentlyBuffering = false + eventEmitter.onPlaybackStateChange(.init(isPlaying: false, isBuffering: false)) + return + } + + switch status { + case .waitingToPlayAtSpecifiedRate: + isCurrentlyBuffering = true + self.status = .loading + break + + case .playing: + isCurrentlyBuffering = false + self.status = .readytoplay + break + + case .paused: + isCurrentlyBuffering = false + self.status = .readytoplay + break + + @unknown default: + break + } + + updateAndEmitPlaybackState() + } + + func onPlayerStatusChanged(status: AVPlayer.Status) { + if status == .failed || playerItem?.status == .failed { + self.status = .error + isCurrentlyBuffering = false + updateAndEmitPlaybackState() + } + } + + func onPlayerItemStatusChanged(status: AVPlayerItem.Status) { + if status == .failed { + self.status = .error + isCurrentlyBuffering = false + updateAndEmitPlaybackState() + return + } + + switch status { + case .unknown: + isCurrentlyBuffering = true + self.status = .loading + + // Set initial buffering state when we have a playerItem + if let playerItem = self.playerItem { + if playerItem.isPlaybackBufferEmpty { + isCurrentlyBuffering = true + } + } + + case .readyToPlay: + guard let playerItem else { return } + + let height = playerItem.presentationSize.height + let width = playerItem.presentationSize.width + let orientation: VideoOrientation = playerItem.asset.tracks.first(where: { $0.mediaType == .video })?.orientation ?? .unknown + + eventEmitter.onLoad( + .init(currentTime, duration, height, width, orientation) + ) + + if playerItem.isPlaybackLikelyToKeepUp && !playerItem.isPlaybackBufferEmpty { + isCurrentlyBuffering = false + self.status = .readytoplay + } + + case .failed: + self.status = .error + isCurrentlyBuffering = false + + @unknown default: + break + } + + updateAndEmitPlaybackState() + } + + func onTextTrackDataChanged(texts: [NSAttributedString]) { + eventEmitter.onTextTrackDataChanged(texts.map { $0.string }) + } + + func onTimedMetadataChanged(timedMetadata: [AVMetadataItem]) { + var metadata: [TimedMetadataObject] = [] + for item in timedMetadata { + let value = item.value as? String + let identifier = item.identifier?.rawValue + + if let value, let identifier { + metadata.append(.init(value: value, identifier: identifier)) + } + } + + eventEmitter.onTimedMetadata(.init(metadata: metadata)) + } + + func onBandwidthUpdate(bitrate: Double) { + eventEmitter.onBandwidthUpdate(.init(bitrate: bitrate, width: nil, height: nil)) + } + + func onPlayerItemWillChange(hasNewPlayerItem: Bool) { + if hasNewPlayerItem { + // Set initial buffering state when playerItem is assigned + isCurrentlyBuffering = true + status = .loading + updateAndEmitPlaybackState() + } else { + // Clean up state when playerItem is cleared + isCurrentlyBuffering = false + } + } + + func updateAndEmitPlaybackState() { + let isPlaying = player.rate > 0 && !isCurrentlyBuffering + + eventEmitter.onPlaybackStateChange(.init(isPlaying: isPlaying, isBuffering: isCurrentlyBuffering)) + eventEmitter.onBuffer(isCurrentlyBuffering) + } +} diff --git a/ios/hybrids/VideoPlayer/HybridVideoPlayer.swift b/ios/hybrids/VideoPlayer/HybridVideoPlayer.swift new file mode 100644 index 00000000..6bd918da --- /dev/null +++ b/ios/hybrids/VideoPlayer/HybridVideoPlayer.swift @@ -0,0 +1,485 @@ +// +// HybridVideoPlayer.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 09/10/2024. +// + +import AVFoundation +import Foundation +import NitroModules + +class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec { + /** + * Player instance for video playback + */ + var player: AVPlayer { + didSet { + playerObserver?.initializePlayerObservers() + } + willSet { + playerObserver?.invalidatePlayerObservers() + } + } + + var playerItem: AVPlayerItem? { + didSet { + if let bufferConfig = source.config.bufferConfig { + playerItem?.setBufferConfig(config: bufferConfig) + } + } + } + var playerObserver: VideoPlayerObserver? + + init(source: (any HybridVideoPlayerSourceSpec)) throws { + self.source = source + self.eventEmitter = HybridVideoPlayerEventEmitter() + + // Initialize AVPlayer with empty item + self.player = AVPlayer() + + super.init() + self.playerObserver = VideoPlayerObserver(delegate: self) + self.playerObserver?.initializePlayerObservers() + + Task { + if source.config.initializeOnCreation == true { + self.playerItem = try await initializePlayerItem() + self.player.replaceCurrentItem(with: self.playerItem) + } + } + + VideoManager.shared.register(player: self) + } + + deinit { + release() + } + + // MARK: - Hybrid Impl + + var source: any HybridVideoPlayerSourceSpec + + var status: VideoPlayerStatus = .idle { + didSet { + if status != oldValue { + eventEmitter.onStatusChange(status) + } + } + } + + var eventEmitter: HybridVideoPlayerEventEmitterSpec + + var volume: Double { + set { + player.volume = Float(newValue) + } + get { + return Double(player.volume) + } + } + + var muted: Bool { + set { + player.isMuted = newValue + eventEmitter.onVolumeChange( + onVolumeChangeData( + volume: Double(player.volume), + muted: muted + ) + ) + } + get { + return player.isMuted + } + } + + var currentTime: Double { + set { + eventEmitter.onSeek(newValue) + player.seek( + to: CMTime(seconds: newValue, preferredTimescale: 1000), + toleranceBefore: .zero, + toleranceAfter: .zero + ) + } + get { + player.currentTime().seconds + } + } + + var duration: Double { + Double(player.currentItem?.duration.seconds ?? Double.nan) + } + + var rate: Double { + set { + if #available(iOS 16.0, tvOS 16.0, *) { + player.defaultRate = Float(newValue) + } + + player.rate = Float(newValue) + } + get { + return Double(player.rate) + } + } + + var loop: Bool = false + + var mixAudioMode: MixAudioMode = .auto { + didSet { + VideoManager.shared.requestAudioSessionUpdate() + } + } + + var ignoreSilentSwitchMode: IgnoreSilentSwitchMode = .auto { + didSet { + VideoManager.shared.requestAudioSessionUpdate() + } + } + + var playInBackground: Bool = false { + didSet { + VideoManager.shared.requestAudioSessionUpdate() + } + } + + var playWhenInactive: Bool = false + + var wasAutoPaused: Bool = false + + // Text track selection state + private var selectedExternalTrackIndex: Int? = nil + + var isCurrentlyBuffering: Bool = false + + var isPlaying: Bool { + return player.rate != 0 + } + + var showNotificationControls: Bool = false { + didSet { + if showNotificationControls { + NowPlayingInfoCenterManager.shared.registerPlayer(player: player) + } else { + NowPlayingInfoCenterManager.shared.removePlayer(player: player) + } + } + } + + func initialize() throws -> Promise { + return Promise.async { [weak self] in + guard let self else { + throw LibraryError.deallocated(objectName: "HybridVideoPlayer").error() + } + + if self.playerItem != nil { + return + } + + self.playerItem = try await self.initializePlayerItem() + self.player.replaceCurrentItem(with: self.playerItem) + } + } + + func release() { + NowPlayingInfoCenterManager.shared.removePlayer(player: player) + self.player.replaceCurrentItem(with: nil) + self.playerItem = nil + + if let source = self.source as? HybridVideoPlayerSource { + source.releaseAsset() + } + + // Clear player observer + self.playerObserver = nil + status = .idle + + VideoManager.shared.unregister(player: self) + } + + func preload() throws -> NitroModules.Promise { + let promise = Promise() + + if status != .idle { + promise.resolve(withResult: ()) + return promise + } + + Task.detached(priority: .userInitiated) { [weak self] in + guard let self else { + promise.reject( + withError: LibraryError.deallocated(objectName: "HybridVideoPlayer") + .error() + ) + return + } + + do { + let playerItem = try await self.initializePlayerItem() + self.playerItem = playerItem + + self.player.replaceCurrentItem(with: playerItem) + promise.resolve(withResult: ()) + } catch { + promise.reject(withError: error) + } + } + + return promise + } + + func play() throws { + player.play() + } + + func pause() throws { + player.pause() + } + + func seekBy(time: Double) throws { + guard let currentItem = player.currentItem else { + throw PlayerError.notInitialized.error() + } + + let currentItemTime = currentItem.currentTime() + + // Duration is NaN for live streams + let fixedDurration = duration.isNaN ? Double.infinity : duration + + // Clap by <0, duration> + let newTime = max(0, min(currentItemTime.seconds + time, fixedDurration)) + + currentTime = newTime + } + + func seekTo(time: Double) { + currentTime = time + } + + func replaceSourceAsync(source: (any HybridVideoPlayerSourceSpec)?) throws + -> Promise + { + let promise = Promise() + + guard let source else { + release() + promise.resolve(withResult: ()) + return promise + } + + Task.detached(priority: .userInitiated) { [weak self] in + guard let self else { + promise.reject( + withError: LibraryError.deallocated(objectName: "HybridVideoPlayer") + .error() + ) + return + } + + self.source = source + self.playerItem = try await self.initializePlayerItem() + self.player.replaceCurrentItem(with: self.playerItem) + NowPlayingInfoCenterManager.shared.updateNowPlayingInfo() + promise.resolve(withResult: ()) + } + + return promise + } + + // MARK: - Methods + + func initializePlayerItem() async throws -> AVPlayerItem { + // Ensure the source is a valid HybridVideoPlayerSource + guard let _hybridSource = source as? HybridVideoPlayerSource else { + status = .error + throw PlayerError.invalidSource.error() + } + + // (maybe) Override source with plugins + let _source = await PluginsRegistry.shared.overrideSource( + source: _hybridSource + ) + + let isNetworkSource = _source.url.isFileURL == false + eventEmitter.onLoadStart( + .init(sourceType: isNetworkSource ? .network : .local, source: _source) + ) + + let asset = try await _source.getAsset() + + let playerItem: AVPlayerItem + + if let externalSubtitles = source.config.externalSubtitles, + externalSubtitles.isEmpty == false + { + playerItem = try await AVPlayerItem.withExternalSubtitles( + for: asset, + config: source.config + ) + } else { + playerItem = AVPlayerItem(asset: asset) + } + + return playerItem + } + + // MARK: - Text Track Management + + func getAvailableTextTracks() throws -> [TextTrack] { + guard let currentItem = player.currentItem else { + return [] + } + + var tracks: [TextTrack] = [] + + if let mediaSelection = currentItem.asset.mediaSelectionGroup( + forMediaCharacteristic: .legible + ) { + for (index, option) in mediaSelection.options.enumerated() { + let isSelected = + currentItem.currentMediaSelection.selectedMediaOption( + in: mediaSelection + ) == option + + let name = + option.commonMetadata.first(where: { $0.commonKey == .commonKeyTitle } + )?.stringValue + ?? option.displayName + + let isExternal = + source.config.externalSubtitles?.contains { subtitle in + name.contains(subtitle.label) + } ?? false + + let trackId = + isExternal + ? "external-\(index)" + : "builtin-\(option.displayName)-\(option.locale?.identifier ?? "unknown")" + + tracks.append( + TextTrack( + id: trackId, + label: option.displayName, + language: option.locale?.identifier, + selected: isSelected + ) + ) + } + } + + return tracks + } + + func selectTextTrack(textTrack: TextTrack?) throws { + guard let currentItem = player.currentItem else { + throw PlayerError.notInitialized.error() + } + + guard + let mediaSelection = currentItem.asset.mediaSelectionGroup( + forMediaCharacteristic: .legible + ) + else { + return + } + + // If textTrack is nil, deselect any selected track + guard let textTrack = textTrack else { + currentItem.select(nil, in: mediaSelection) + selectedExternalTrackIndex = nil + eventEmitter.onTrackChange(nil) + return + } + + // If textTrack id is empty, deselect any selected track + if textTrack.id.isEmpty { + currentItem.select(nil, in: mediaSelection) + selectedExternalTrackIndex = nil + eventEmitter.onTrackChange(nil) + return + } + + if textTrack.id.hasPrefix("external-") { + let trackIndexStr = String(textTrack.id.dropFirst("external-".count)) + if let trackIndex = Int(trackIndexStr), + trackIndex < mediaSelection.options.count + { + let option = mediaSelection.options[trackIndex] + currentItem.select(option, in: mediaSelection) + selectedExternalTrackIndex = trackIndex + eventEmitter.onTrackChange(textTrack) + } + } else if textTrack.id.hasPrefix("builtin-") { + for option in mediaSelection.options { + let optionId = + "builtin-\(option.displayName)-\(option.locale?.identifier ?? "unknown")" + if optionId == textTrack.id { + currentItem.select(option, in: mediaSelection) + selectedExternalTrackIndex = nil + eventEmitter.onTrackChange(textTrack) + return + } + } + } + } + + var selectedTrack: TextTrack? { + guard let currentItem = player.currentItem else { + return nil + } + + guard + let mediaSelection = currentItem.asset.mediaSelectionGroup( + forMediaCharacteristic: .legible + ) + else { + return nil + } + + guard + let selectedOption = currentItem.currentMediaSelection + .selectedMediaOption(in: mediaSelection) + else { + return nil + } + + guard let index = mediaSelection.options.firstIndex(of: selectedOption) + else { + return nil + } + + let isExternal = + source.config.externalSubtitles?.contains { subtitle in + selectedOption.displayName.contains(subtitle.label) + } ?? false + + let trackId = + isExternal + ? "external-\(index)" + : "builtin-\(selectedOption.displayName)-\(selectedOption.locale?.identifier ?? "unknown")" + + return TextTrack( + id: trackId, + label: selectedOption.displayName, + language: selectedOption.locale?.identifier, + selected: true + ) + } + + // MARK: - Memory Management + + func dispose() { + release() + } + + var memorySize: Int { + var size = 0 + + size += source.memorySize + size += playerItem?.asset.estimatedMemoryUsage ?? 0 + + return size + } +} diff --git a/ios/hybrids/VideoPlayer/HybridVideoPlayerFactory.swift b/ios/hybrids/VideoPlayer/HybridVideoPlayerFactory.swift new file mode 100644 index 00000000..9ab476dc --- /dev/null +++ b/ios/hybrids/VideoPlayer/HybridVideoPlayerFactory.swift @@ -0,0 +1,15 @@ +// +// HybridVideoPlayerFactory.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 09/10/2024. +// + +import Foundation +import NitroModules + +class HybridVideoPlayerFactory: HybridVideoPlayerFactorySpec { + func createPlayer(source: HybridVideoPlayerSourceSpec) throws -> HybridVideoPlayerSpec { + return try HybridVideoPlayer(source: source) + } +} diff --git a/ios/hybrids/VideoPlayerEmitter/HybridVideoPlayerEventEmitter.swift b/ios/hybrids/VideoPlayerEmitter/HybridVideoPlayerEventEmitter.swift new file mode 100644 index 00000000..622f0e78 --- /dev/null +++ b/ios/hybrids/VideoPlayerEmitter/HybridVideoPlayerEventEmitter.swift @@ -0,0 +1,49 @@ +// +// HybridVideoPlayerEventEmitter.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 02/05/2025. +// + +import Foundation +import NitroModules + +class HybridVideoPlayerEventEmitter: HybridVideoPlayerEventEmitterSpec { + var onAudioBecomingNoisy: (() -> Void) = {} + + var onAudioFocusChange: ((Bool) -> Void) = { _ in } + + var onBandwidthUpdate: ((BandwidthData) -> Void) = { _ in } + + var onBuffer: ((Bool) -> Void) = { _ in } + + var onControlsVisibleChange: ((Bool) -> Void) = { _ in } + + var onEnd: (() -> Void) = {} + + var onExternalPlaybackChange: ((Bool) -> Void) = { _ in } + + var onLoad: ((onLoadData) -> Void) = { _ in } + + var onLoadStart: ((onLoadStartData) -> Void) = { _ in } + + var onPlaybackStateChange: ((onPlaybackStateChangeData) -> Void) = { _ in } + + var onPlaybackRateChange: ((Double) -> Void) = { _ in } + + var onProgress: ((onProgressData) -> Void) = { _ in } + + var onReadyToDisplay: (() -> Void) = {} + + var onSeek: ((Double) -> Void) = { _ in } + + var onStatusChange: (VideoPlayerStatus) -> Void = { _ in } + + var onTimedMetadata: ((TimedMetadata) -> Void) = { _ in } + + var onTextTrackDataChanged: ([String]) -> Void = { _ in } + + var onTrackChange: ((TextTrack?) -> Void) = { _ in } + + var onVolumeChange: ((onVolumeChangeData) -> Void) = { _ in } +} diff --git a/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSource.swift b/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSource.swift new file mode 100644 index 00000000..5f318453 --- /dev/null +++ b/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSource.swift @@ -0,0 +1,137 @@ +// +// HybridVideoPlayerSource.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/09/2024. +// + +import Foundation +import AVFoundation +import NitroModules + +class HybridVideoPlayerSource: HybridVideoPlayerSourceSpec, NativeVideoPlayerSourceSpec { + var asset: AVURLAsset? + var uri: String + var config: NativeVideoConfig + + var drmManager: DRMManagerSpec? + + let url: URL + + init(config: NativeVideoConfig) throws { + self.uri = config.uri + self.config = config + + guard let url = URL(string: uri) else { + throw SourceError.invalidUri(uri: uri).error() + } + + self.url = url + + super.init() + + if config.drm != nil { + // Try to get the DRM manager + // If no DRM manager is found, it will throw an error + _ = try PluginsRegistry.shared.getDrmManager(source: self) + } + } + + deinit { + releaseAsset() + } + + func getAssetInformationAsync() -> Promise { + let promise = Promise() + + Task.detached(priority: .utility) { [weak self] in + guard let self else { + promise.reject(withError: LibraryError.deallocated(objectName: "HybridVideoPlayerSource").error()) + return + } + + do { + if self.url.isFileURL { + try VideoFileHelper.validateReadPermission(for: self.url) + } + + try await self.initializeAsset() + + guard let asset = self.asset else { + throw PlayerError.assetNotInitialized.error() + } + + let videoInformation = try await asset.getAssetInformation() + + promise.resolve(withResult: videoInformation) + } catch { + promise.reject(withError: error) + } + } + + return promise + } + + func initializeAsset() async throws { + guard asset == nil else { + return + } + + if let headers = config.headers { + let options = [ + "AVURLAssetHTTPHeaderFieldsKey": headers + ] + asset = AVURLAsset(url: url, options: options) + } else { + asset = AVURLAsset(url: url) + } + + guard let asset else { + throw SourceError.failedToInitializeAsset.error() + } + + if let drmParams = config.drm { + drmManager = try PluginsRegistry.shared.getDrmManager(source: self) + + guard let drmManager else { + throw LibraryError.DRMPluginNotFound.error() + } + + do { + try drmManager.createContentKeyRequest(for: asset, drmParams: drmParams) + } catch { + print("[ReactNativeVideo] Failed to create content key request for DRM: \(drmParams)") + } + } + + // Code browned from expo-video https://github.com/expo/expo/blob/ea17c9b1ce5111e1454b089ba381f3feb93f33cc/packages/expo-video/ios/VideoPlayerItem.swift#L40C30-L40C73 + // If we don't load those properties, they will be loaded on main thread causing lags + _ = try? await asset.load(.duration, .preferredTransform, .isPlayable) as Any + } + + func getAsset() async throws -> AVURLAsset { + if let asset { + return asset + } + + try await initializeAsset() + + guard let asset else { + throw SourceError.failedToInitializeAsset.error() + } + + return asset + } + + func releaseAsset() { + asset = nil + } + + var memorySize: Int { + var size = 0 + + size += asset?.estimatedMemoryUsage ?? 0 + + return size + } +} diff --git a/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSourceFactory.swift b/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSourceFactory.swift new file mode 100644 index 00000000..8b6caa2a --- /dev/null +++ b/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSourceFactory.swift @@ -0,0 +1,29 @@ +// +// HybridVideoPlayerSourceFactory.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/09/2024. +// + +import Foundation + +class HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec { + func fromVideoConfig(config: NativeVideoConfig) throws + -> any HybridVideoPlayerSourceSpec + { + return try HybridVideoPlayerSource(config: config) + } + + func fromUri(uri: String) throws -> HybridVideoPlayerSourceSpec { + let config = NativeVideoConfig( + uri: uri, + externalSubtitles: nil, + drm: nil, + headers: nil, + bufferConfig: nil, + metadata: nil, + initializeOnCreation: true + ) + return try HybridVideoPlayerSource(config: config) + } +} diff --git a/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManager.swift b/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManager.swift new file mode 100644 index 00000000..ff0efb97 --- /dev/null +++ b/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManager.swift @@ -0,0 +1,195 @@ +// +// HybridVideoViewViewManager.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/09/2024. +// + +import Foundation +import AVKit +import NitroModules + +class HybridVideoViewViewManager: HybridVideoViewViewManagerSpec { + weak var view: VideoComponentView? + + let DEALOCATED_WARNING = "ReactNativeVideo: VideoComponentView is no longer available. It is likely that the view was deallocated." + + init(nitroId: Double) throws { + guard let view = VideoComponentView.globalViewsMap.object(forKey: NSNumber(value: nitroId)) else { + throw VideoViewError.viewNotFound(nitroId: nitroId).error() + } + + self.view = view + super.init() + view.delegate = VideoViewDelegate(viewManager: self) + } + + // MARK: - Properties + + weak var player: (any HybridVideoPlayerSpec)? { + get { + guard let view = view else { + print(DEALOCATED_WARNING) + return nil + } + return view.player + } + set { + guard let view = view else { + print(DEALOCATED_WARNING) + return + } + view.player = newValue + } + } + + var controls: Bool { + get { + guard let view else { + print(DEALOCATED_WARNING) + return false + } + + return view.controls + } + set { + guard let view else { + print(DEALOCATED_WARNING) + return + } + + view.controls = newValue + } + } + + var pictureInPicture: Bool { + get { + guard let view else { + print(DEALOCATED_WARNING) + return false + } + + return view.allowsPictureInPicturePlayback + } + set { + guard let view else { + print(DEALOCATED_WARNING) + return + } + + view.allowsPictureInPicturePlayback = newValue + } + } + + var autoEnterPictureInPicture: Bool { + get { + guard let view else { + print(DEALOCATED_WARNING) + return false + } + + return view.autoEnterPictureInPicture + } + set { + guard let view else { + print(DEALOCATED_WARNING) + return + } + + view.autoEnterPictureInPicture = newValue + } + } + + var resizeMode: ResizeMode { + get { + guard let view else { + print(DEALOCATED_WARNING) + return .none + } + + return view.resizeMode + } + set { + guard let view else { + print(DEALOCATED_WARNING) + return + } + + view.resizeMode = newValue + } + } + + var keepScreenAwake: Bool { + get { + guard let view else { + print(DEALOCATED_WARNING) + return false + } + + return view.keepScreenAwake + } + set { + guard let view else { + print(DEALOCATED_WARNING) + return + } + + view.keepScreenAwake = newValue + } + } + + // Android only - no-op on iOS + var surfaceType: SurfaceType = .surface + + func enterFullscreen() throws { + guard let view else { + throw VideoViewError.viewIsDeallocated.error() + } + + try view.enterFullscreen() + } + + func exitFullscreen() throws { + guard let view else { + throw VideoViewError.viewIsDeallocated.error() + } + + try view.exitFullscreen() + } + + func enterPictureInPicture() throws { + guard let view else { + throw VideoViewError.viewIsDeallocated.error() + } + + try view.startPictureInPicture() + } + + func exitPictureInPicture() throws { + guard let view else { + throw VideoViewError.viewIsDeallocated.error() + } + + try view.stopPictureInPicture() + } + + func canEnterPictureInPicture() -> Bool { + return AVPictureInPictureController.isPictureInPictureSupported() + } + + // MARK: - Callbacks + + var onPictureInPictureChange: ((Bool) -> Void)? + + var onFullscreenChange: ((Bool) -> Void)? + + var willEnterFullscreen: (() -> Void)? + + var willExitFullscreen: (() -> Void)? + + var willEnterPictureInPicture: (() -> Void)? + + var willExitPictureInPicture: (() -> Void)? + + var onReadyToDisplay: (() -> Void)? +} diff --git a/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManagerFactory.swift b/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManagerFactory.swift new file mode 100644 index 00000000..4c26a092 --- /dev/null +++ b/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManagerFactory.swift @@ -0,0 +1,14 @@ +// +// HybridVideoViewViewManagerFactory.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 23/09/2024. +// + +import Foundation + +class HybridVideoViewViewManagerFactory: HybridVideoViewViewManagerFactorySpec { + func createViewManager(nitroId: Double) throws -> any HybridVideoViewViewManagerSpec { + return try HybridVideoViewViewManager(nitroId: nitroId) + } +} diff --git a/ios/view/VideoComponentView.swift b/ios/view/VideoComponentView.swift new file mode 100644 index 00000000..1cf2423a --- /dev/null +++ b/ios/view/VideoComponentView.swift @@ -0,0 +1,261 @@ +// +// VideoComponent.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 30/09/2024. +// + +import Foundation +import UIKit +import AVFoundation +import AVKit + +@objc public class VideoComponentView: UIView { + public weak var player: HybridVideoPlayerSpec? = nil { + didSet { + guard let player = player as? HybridVideoPlayer else { return } + configureAVPlayerViewController(with: player.player) + } + } + + var delegate: VideoViewDelegate? + private var playerView: UIView? = nil + + private var observer: VideoComponentViewObserver? { + didSet { + playerViewController?.delegate = observer + observer?.updatePlayerViewControllerObservers() + } + } + + private var _keepScreenAwake: Bool = false + var keepScreenAwake: Bool { + get { + guard let player = player as? HybridVideoPlayer else { return false } + return player.player.preventsDisplaySleepDuringVideoPlayback + } + set { + guard let player = player as? HybridVideoPlayer else { return } + player.player.preventsDisplaySleepDuringVideoPlayback = newValue + _keepScreenAwake = newValue + } + } + + var playerViewController: AVPlayerViewController? { + didSet { + guard let observer, let playerViewController else { return } + playerViewController.delegate = observer + observer.updatePlayerViewControllerObservers() + } + } + + public var controls: Bool = false { + didSet { + DispatchQueue.main.async { [weak self] in + guard let self = self, let playerViewController = self.playerViewController else { return } + playerViewController.showsPlaybackControls = self.controls + } + } + } + + public var allowsPictureInPicturePlayback: Bool = false { + didSet { + DispatchQueue.main.async { [weak self] in + guard let self = self, let playerViewController = self.playerViewController else { return } + + VideoManager.shared.requestAudioSessionUpdate() + playerViewController.allowsPictureInPicturePlayback = self.allowsPictureInPicturePlayback + } + } + } + + public var autoEnterPictureInPicture: Bool = false { + didSet { + DispatchQueue.main.async { [weak self] in + guard let self = self, let playerViewController = self.playerViewController else { return } + + VideoManager.shared.requestAudioSessionUpdate() + playerViewController.canStartPictureInPictureAutomaticallyFromInline = self.allowsPictureInPicturePlayback + } + } + } + + public var resizeMode: ResizeMode = .none { + didSet { + DispatchQueue.main.async { [weak self] in + guard let self = self, let playerViewController = self.playerViewController else { return } + playerViewController.videoGravity = resizeMode.toVideoGravity() + } + } + } + + @objc public var nitroId: NSNumber = -1 { + didSet { + VideoComponentView.globalViewsMap.setObject(self, forKey: nitroId) + } + } + + @objc public static var globalViewsMap: NSMapTable = .strongToWeakObjects() + + @objc public override init(frame: CGRect) { + super.init(frame: frame) + VideoManager.shared.register(view: self) + setupPlayerView() + observer = VideoComponentViewObserver(view: self) + } + + deinit { + VideoManager.shared.unregister(view: self) + } + + @objc public required init?(coder: NSCoder) { + super.init(coder: coder) + setupPlayerView() + } + + func setNitroId(nitroId: NSNumber) -> Void { + self.nitroId = nitroId + } + + private func setupPlayerView() { + // Create a UIView to hold the video player layer + playerView = UIView(frame: self.bounds) + playerView?.translatesAutoresizingMaskIntoConstraints = false + if let playerView = playerView { + addSubview(playerView) + NSLayoutConstraint.activate([ + playerView.leadingAnchor.constraint(equalTo: self.leadingAnchor), + playerView.trailingAnchor.constraint(equalTo: self.trailingAnchor), + playerView.topAnchor.constraint(equalTo: self.topAnchor), + playerView.bottomAnchor.constraint(equalTo: self.bottomAnchor) + ]) + } + } + + public func configureAVPlayerViewController(with player: AVPlayer) { + DispatchQueue.main.async { [weak self] in + guard let self = self, let playerView = self.playerView else { return } + // Remove previous controller if any + self.playerViewController?.willMove(toParent: nil) + self.playerViewController?.view.removeFromSuperview() + self.playerViewController?.removeFromParent() + + let controller = AVPlayerViewController() + controller.player = player + controller.showsPlaybackControls = controls + controller.videoGravity = self.resizeMode.toVideoGravity() + controller.view.frame = playerView.bounds + controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + controller.view.backgroundColor = .clear + + // We manage this manually in NowPlayingInfoCenterManager + controller.updatesNowPlayingInfoCenter = false + + if #available(iOS 16.0, *) { + if let initialSpeed = controller.speeds.first(where: { $0.rate == player.rate }) { + controller.selectSpeed(initialSpeed) + } + } + + // Find nearest UIViewController + if let parentVC = self.findViewController() { + parentVC.addChild(controller) + playerView.addSubview(controller.view) + controller.didMove(toParent: parentVC) + self.playerViewController = controller + } + } + } + + // Helper to find nearest UIViewController + private func findViewController() -> UIViewController? { + var responder: UIResponder? = self + while let r = responder { + if let vc = r as? UIViewController { + return vc + } + responder = r.next + } + return nil + } + + public override func willMove(toSuperview newSuperview: UIView?) { + super.willMove(toSuperview: newSuperview) + + if newSuperview == nil { + PluginsRegistry.shared.notifyVideoViewDestroyed(view: self) + + // We want to disable this when view is about to unmount + if keepScreenAwake { + keepScreenAwake = false + } + } else { + PluginsRegistry.shared.notifyVideoViewCreated(view: self) + + // We want to restore keepScreenAwake after component remount + if _keepScreenAwake { + keepScreenAwake = true + } + } + } + + + public override func layoutSubviews() { + super.layoutSubviews() + + // Update the frame of the playerViewController's view when the view's layout changes + playerViewController?.view.frame = playerView?.bounds ?? .zero + playerViewController?.contentOverlayView?.frame = playerView?.bounds ?? .zero + for subview in playerViewController?.contentOverlayView?.subviews ?? [] { + subview.frame = playerView?.bounds ?? .zero + } + } + + public func enterFullscreen() throws { + guard let playerViewController else { + throw VideoViewError.viewIsDeallocated.error() + } + + DispatchQueue.main.async { + playerViewController.enterFullscreen(animated: true) + } + } + + public func exitFullscreen() throws { + guard let playerViewController else { + throw VideoViewError.viewIsDeallocated.error() + } + + DispatchQueue.main.async { + playerViewController.exitFullscreen(animated: true) + } + } + + public func startPictureInPicture() throws { + guard let playerViewController else { + throw VideoViewError.viewIsDeallocated.error() + } + + guard AVPictureInPictureController.isPictureInPictureSupported() else { + throw VideoViewError.pictureInPictureNotSupported.error() + } + + DispatchQueue.main.async { + // Here we skip error handling for simplicity + // We do check for PiP support earlier in the code + try? playerViewController.startPictureInPicture() + } + } + + public func stopPictureInPicture() throws { + guard let playerViewController else { + throw VideoViewError.viewIsDeallocated.error() + } + + DispatchQueue.main.async { + // Here we skip error handling for simplicity + // We do check for PiP support earlier in the code + playerViewController.stopPictureInPicture() + } + } +} diff --git a/ios/view/VideoComponentViewObserver.swift b/ios/view/VideoComponentViewObserver.swift new file mode 100644 index 00000000..4413f824 --- /dev/null +++ b/ios/view/VideoComponentViewObserver.swift @@ -0,0 +1,142 @@ +// +// VideoComponentViewObserver.swift +// ReactNativeVideo +// +// Created by Krzysztof Moch on 06/05/2025. +// + +import Foundation +import AVKit +import AVFoundation + +protocol VideoComponentViewDelegate: AnyObject { + func onPictureInPictureChange(_ isActive: Bool) + func onFullscreenChange(_ isActive: Bool) + func willEnterFullscreen() + func willExitFullscreen() + func willEnterPictureInPicture() + func willExitPictureInPicture() + func onReadyToDisplay() +} + +// Map delegate methods to view manager methods +final class VideoViewDelegate: NSObject, VideoComponentViewDelegate { + weak var viewManager: HybridVideoViewViewManager? + + init(viewManager: HybridVideoViewViewManager) { + self.viewManager = viewManager + } + + func onPictureInPictureChange(_ isActive: Bool) { + viewManager?.onPictureInPictureChange?(isActive) + } + + func onFullscreenChange(_ isActive: Bool) { + viewManager?.onFullscreenChange?(isActive) + } + + func willEnterFullscreen() { + viewManager?.willEnterFullscreen?() + } + + func willExitFullscreen() { + viewManager?.willExitFullscreen?() + } + + func willEnterPictureInPicture() { + viewManager?.willEnterPictureInPicture?() + } + + func willExitPictureInPicture() { + viewManager?.willExitPictureInPicture?() + } + + func onReadyToDisplay() { + viewManager?.player?.eventEmitter.onReadyToDisplay() + } +} + +class VideoComponentViewObserver: NSObject, AVPlayerViewControllerDelegate { + private weak var view: VideoComponentView? + + var delegate: VideoViewDelegate? { + get { + return view?.delegate + } + } + + var playerViewController: AVPlayerViewController? { + return view?.playerViewController + } + + // playerViewController observers + var onReadyToDisplayObserver: NSKeyValueObservation? + + init(view: VideoComponentView) { + self.view = view + super.init() + } + + func initializePlayerViewContorollerObservers() { + guard let playerViewController = playerViewController else { + return + } + + onReadyToDisplayObserver = playerViewController.observe(\.isReadyForDisplay, options: [.new]) { [weak self] _, change in + guard let self = self else { return } + if change.newValue == true { + self.delegate?.onReadyToDisplay() + } + } + } + + func removePlayerViewControllerObservers() { + onReadyToDisplayObserver?.invalidate() + onReadyToDisplayObserver = nil + } + + func updatePlayerViewControllerObservers() { + removePlayerViewControllerObservers() + initializePlayerViewContorollerObservers() + } + + func playerViewControllerDidStartPictureInPicture(_: AVPlayerViewController) { + delegate?.onPictureInPictureChange(true) + } + + func playerViewControllerDidStopPictureInPicture(_: AVPlayerViewController) { + delegate?.onPictureInPictureChange(false) + } + + func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) { + delegate?.willEnterPictureInPicture() + } + + func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) { + delegate?.willExitPictureInPicture() + } + + func playerViewController( + _: AVPlayerViewController, + willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator + ) { + delegate?.willExitFullscreen() + + coordinator.animate(alongsideTransition: nil) { [weak self] _ in + guard let self = self else { return } + self.delegate?.onFullscreenChange(false) + } + } + + func playerViewController( + _: AVPlayerViewController, + willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator + ) { + delegate?.willEnterFullscreen() + + coordinator.animate(alongsideTransition: nil) { [weak self] _ in + guard let self = self else { return } + self.delegate?.onFullscreenChange(true) + } + } +} diff --git a/ios/view/fabric/RCTVideoViewComponentView.h b/ios/view/fabric/RCTVideoViewComponentView.h new file mode 100644 index 00000000..a2e8c59d --- /dev/null +++ b/ios/view/fabric/RCTVideoViewComponentView.h @@ -0,0 +1,10 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RCTVideoViewComponentView : RCTViewComponentView + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/view/fabric/RCTVideoViewComponentView.mm b/ios/view/fabric/RCTVideoViewComponentView.mm new file mode 100644 index 00000000..3f6d5a42 --- /dev/null +++ b/ios/view/fabric/RCTVideoViewComponentView.mm @@ -0,0 +1,94 @@ +#import "RCTVideoViewComponentView.h" + +#import +#import +#import +#import + +#import "RCTFabricComponentsPlugins.h" + +#import "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +#if __has_include("ReactNativeVideo/ReactNativeVideo-Swift.h") +#import "ReactNativeVideo/ReactNativeVideo-Swift.h" +#else +#import "ReactNativeVideo-Swift.h" +#endif + +using namespace facebook::react; + +@interface RCTVideoViewComponentView () +@end + +@implementation RCTVideoViewComponentView { + VideoComponentView *_view; + int _nitroId; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = + std::make_shared(); + _props = defaultProps; + + _view = [[VideoComponentView alloc] initWithFrame:frame]; + + self.contentView = _view; + } + + // -1 means that nitroId wasn't set yet + _nitroId = -1; + + return self; +} + +- (void)updateProps:(Props::Shared const &)props + oldProps:(Props::Shared const &)oldProps { + const auto &oldViewProps = + *std::static_pointer_cast(_props); + const auto &newViewProps = + *std::static_pointer_cast(props); + + if (oldViewProps.nitroId != newViewProps.nitroId) { + [self setNitroId:newViewProps.nitroId]; + } + + [super updateProps:props oldProps:oldProps]; +} + +- (void)setNitroId:(int)nitroId { + _nitroId = nitroId; + [_view setNitroId:[NSNumber numberWithInt:nitroId]]; + [self onNitroIdChange:nitroId]; +} + ++ (BOOL)shouldBeRecycled +{ + return NO; +} + +// Event emitter convenience method +- (void)onNitroIdChange:(int)nitroId { + auto eventEmitter = + std::dynamic_pointer_cast(_eventEmitter); + if (!eventEmitter || nitroId == -1) { + return; + } + + eventEmitter->onNitroIdChange({.nitroId = nitroId}); +} + +- (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter { + [super updateEventEmitter:eventEmitter]; + [self onNitroIdChange:_nitroId]; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider { + return concreteComponentDescriptorProvider(); +} + +Class RNCVideoViewCls(void) { + return RCTVideoViewComponentView.class; +} + +@end diff --git a/ios/view/fabric/RCTVideoViewViewManager.mm b/ios/view/fabric/RCTVideoViewViewManager.mm new file mode 100644 index 00000000..5f638ff3 --- /dev/null +++ b/ios/view/fabric/RCTVideoViewViewManager.mm @@ -0,0 +1,14 @@ +#import +#import +#import "RCTBridge.h" + +@interface RCTVideoViewViewManager : RCTViewManager +@end + +@implementation RCTVideoViewViewManager + +RCT_EXPORT_MODULE(RNCVideoView) + +RCT_EXPORT_VIEW_PROPERTY(nitroId, NSNumber) + +@end diff --git a/ios/view/paper/RCTVideoViewComponentView.h b/ios/view/paper/RCTVideoViewComponentView.h new file mode 100644 index 00000000..9050b578 --- /dev/null +++ b/ios/view/paper/RCTVideoViewComponentView.h @@ -0,0 +1,9 @@ +#import + +@interface RCTVideoViewComponentView : RCTView + +@property (nonatomic, copy) NSNumber *nitroId; +@property (nonatomic, copy) RCTDirectEventBlock onNitroIdChange; + +@end + diff --git a/ios/view/paper/RCTVideoViewComponentView.mm b/ios/view/paper/RCTVideoViewComponentView.mm new file mode 100644 index 00000000..bb7fa43b --- /dev/null +++ b/ios/view/paper/RCTVideoViewComponentView.mm @@ -0,0 +1,45 @@ +#import "RCTVideoViewComponentView.h" + +#import "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +#if __has_include("ReactNativeVideo/ReactNativeVideo-Swift.h") +#import "ReactNativeVideo/ReactNativeVideo-Swift.h" +#else +#import "ReactNativeVideo-Swift.h" +#endif + +@implementation RCTVideoViewComponentView { + VideoComponentView *_view; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialize VideoComponentView with the given frame + _view = [[VideoComponentView alloc] initWithFrame:frame]; + _view.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_view]; + + // Set up constraints to make VideoComponentView fill + // RCTVideoViewComponentView + [NSLayoutConstraint activateConstraints:@[ + [_view.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], + [_view.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], + [_view.topAnchor constraintEqualToAnchor:self.topAnchor], + [_view.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] + ]]; + } + return self; +} + +- (void)setNitroId:(NSNumber *)nitroId { + _nitroId = nitroId; + [_view setNitroId:nitroId]; + + // Emit the onNitroIdChange event when nitroId is updated + if (self.onNitroIdChange) { + self.onNitroIdChange(@{@"nitroId" : nitroId}); + } +} + +@end diff --git a/ios/view/paper/RCTVideoViewViewManager.m b/ios/view/paper/RCTVideoViewViewManager.m new file mode 100644 index 00000000..685f4bf7 --- /dev/null +++ b/ios/view/paper/RCTVideoViewViewManager.m @@ -0,0 +1,18 @@ +#import +#import "RCTEventDispatcher.h" +#import "RCTVideoViewComponentView.h" + +@interface RCTVideoViewViewManager : RCTViewManager +@end + +@implementation RCTVideoViewViewManager + +RCT_EXPORT_MODULE(RNCVideoView) +RCT_EXPORT_VIEW_PROPERTY(nitroId, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(onNitroIdChange, RCTDirectEventBlock) + +- (UIView *)view { + return [[RCTVideoViewComponentView alloc] init]; +} + +@end diff --git a/lib/commonjs/core/VideoPlayer.js b/lib/commonjs/core/VideoPlayer.js new file mode 100644 index 00000000..bdbc651c --- /dev/null +++ b/lib/commonjs/core/VideoPlayer.js @@ -0,0 +1,241 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.VideoPlayer = void 0; +var _reactNative = require("react-native"); +var _reactNativeNitroModules = require("react-native-nitro-modules"); +var _VideoError = require("./types/VideoError.js"); +var _playerFactory = require("./utils/playerFactory.js"); +var _sourceFactory = require("./utils/sourceFactory.js"); +var _VideoPlayerEvents = require("./VideoPlayerEvents.js"); +class VideoPlayer extends _VideoPlayerEvents.VideoPlayerEvents { + constructor(source) { + const hybridSource = (0, _sourceFactory.createSource)(source); + const player = (0, _playerFactory.createPlayer)(hybridSource); + + // Initialize events + super(player.eventEmitter); + this.player = player; + } + + /** + * Cleans up player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * @internal + */ + __destroy() { + this.clearAllEvents(); + this.player.dispose(); + } + + /** + * Returns the native (hybrid) player instance. + * Should not be used outside of the module. + * @internal + */ + __getNativePlayer() { + return this.player; + } + + /** + * Handles parsing native errors to VideoRuntimeError and calling onError if provided + * @internal + */ + throwError(error) { + const parsedError = (0, _VideoError.tryParseNativeVideoError)(error); + if (parsedError instanceof _VideoError.VideoRuntimeError && this.triggerEvent('onError', parsedError)) { + // We don't throw errors if onError is provided + return; + } + throw parsedError; + } + + /** + * Wraps a promise to try parsing native errors to VideoRuntimeError + * @internal + */ + wrapPromise(promise) { + return new Promise((resolve, reject) => { + promise.then(resolve).catch(error => { + reject(this.throwError(error)); + }); + }); + } + + // Source + get source() { + return this.player.source; + } + + // Status + get status() { + return this.player.status; + } + + // Duration + get duration() { + return this.player.duration; + } + + // Volume + get volume() { + return this.player.volume; + } + set volume(value) { + this.player.volume = value; + } + + // Current Time + get currentTime() { + return this.player.currentTime; + } + set currentTime(value) { + this.player.currentTime = value; + } + + // Muted + get muted() { + return this.player.muted; + } + set muted(value) { + this.player.muted = value; + } + + // Loop + get loop() { + return this.player.loop; + } + set loop(value) { + this.player.loop = value; + } + + // Rate + get rate() { + return this.player.rate; + } + set rate(value) { + this.player.rate = value; + } + + // Mix Audio Mode + get mixAudioMode() { + return this.player.mixAudioMode; + } + set mixAudioMode(value) { + this.player.mixAudioMode = value; + } + + // Ignore Silent Switch Mode + get ignoreSilentSwitchMode() { + return this.player.ignoreSilentSwitchMode; + } + set ignoreSilentSwitchMode(value) { + if (__DEV__ && !['ios'].includes(_reactNative.Platform.OS)) { + console.warn('ignoreSilentSwitchMode is not supported on this platform, it wont have any effect'); + } + this.player.ignoreSilentSwitchMode = value; + } + + // Play In Background + get playInBackground() { + return this.player.playInBackground; + } + set playInBackground(value) { + this.player.playInBackground = value; + } + + // Play When Inactive + get playWhenInactive() { + return this.player.playWhenInactive; + } + set playWhenInactive(value) { + this.player.playWhenInactive = value; + } + + // Is Playing + get isPlaying() { + return this.player.isPlaying; + } + get showNotificationControls() { + return this.player.showNotificationControls; + } + set showNotificationControls(value) { + this.player.showNotificationControls = value; + } + async initialize() { + await this.wrapPromise(this.player.initialize()); + _reactNativeNitroModules.NitroModules.updateMemorySize(this.player); + } + async preload() { + await this.wrapPromise(this.player.preload()); + _reactNativeNitroModules.NitroModules.updateMemorySize(this.player); + } + + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release() { + this.__destroy(); + } + play() { + try { + this.player.play(); + } catch (error) { + this.throwError(error); + } + } + pause() { + try { + this.player.pause(); + } catch (error) { + this.throwError(error); + } + } + seekBy(time) { + try { + this.player.seekBy(time); + } catch (error) { + this.throwError(error); + } + } + seekTo(time) { + try { + this.player.seekTo(time); + } catch (error) { + this.throwError(error); + } + } + async replaceSourceAsync(source) { + await this.wrapPromise(this.player.replaceSourceAsync(source === null ? null : (0, _sourceFactory.createSource)(source))); + _reactNativeNitroModules.NitroModules.updateMemorySize(this.player); + } + + // Text Track Management + getAvailableTextTracks() { + try { + return this.player.getAvailableTextTracks(); + } catch (error) { + this.throwError(error); + return []; + } + } + selectTextTrack(textTrack) { + try { + this.player.selectTextTrack(textTrack); + } catch (error) { + this.throwError(error); + } + } + + // Selected Text Track + get selectedTrack() { + return this.player.selectedTrack; + } +} +exports.VideoPlayer = VideoPlayer; +//# sourceMappingURL=VideoPlayer.js.map \ No newline at end of file diff --git a/lib/commonjs/core/VideoPlayer.js.map b/lib/commonjs/core/VideoPlayer.js.map new file mode 100644 index 00000000..edc27dc9 --- /dev/null +++ b/lib/commonjs/core/VideoPlayer.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_reactNative","require","_reactNativeNitroModules","_VideoError","_playerFactory","_sourceFactory","_VideoPlayerEvents","VideoPlayer","VideoPlayerEvents","constructor","source","hybridSource","createSource","player","createPlayer","eventEmitter","__destroy","clearAllEvents","dispose","__getNativePlayer","throwError","error","parsedError","tryParseNativeVideoError","VideoRuntimeError","triggerEvent","wrapPromise","promise","Promise","resolve","reject","then","catch","status","duration","volume","value","currentTime","muted","loop","rate","mixAudioMode","ignoreSilentSwitchMode","__DEV__","includes","Platform","OS","console","warn","playInBackground","playWhenInactive","isPlaying","showNotificationControls","initialize","NitroModules","updateMemorySize","preload","release","play","pause","seekBy","time","seekTo","replaceSourceAsync","getAvailableTextTracks","selectTextTrack","textTrack","selectedTrack","exports"],"sourceRoot":"../../../src","sources":["core/VideoPlayer.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,wBAAA,GAAAD,OAAA;AAQA,IAAAE,WAAA,GAAAF,OAAA;AAMA,IAAAG,cAAA,GAAAH,OAAA;AACA,IAAAI,cAAA,GAAAJ,OAAA;AACA,IAAAK,kBAAA,GAAAL,OAAA;AAEA,MAAMM,WAAW,SAASC,oCAAiB,CAA4B;EAGrEC,WAAWA,CAACC,MAAqD,EAAE;IACjE,MAAMC,YAAY,GAAG,IAAAC,2BAAY,EAACF,MAAM,CAAC;IACzC,MAAMG,MAAM,GAAG,IAAAC,2BAAY,EAACH,YAAY,CAAC;;IAEzC;IACA,KAAK,CAACE,MAAM,CAACE,YAAY,CAAC;IAC1B,IAAI,CAACF,MAAM,GAAGA,MAAM;EACtB;;EAEA;AACF;AACA;AACA;AACA;EACEG,SAASA,CAAA,EAAG;IACV,IAAI,CAACC,cAAc,CAAC,CAAC;IACrB,IAAI,CAACJ,MAAM,CAACK,OAAO,CAAC,CAAC;EACvB;;EAEA;AACF;AACA;AACA;AACA;EACEC,iBAAiBA,CAAA,EAAG;IAClB,OAAO,IAAI,CAACN,MAAM;EACpB;;EAEA;AACF;AACA;AACA;EACUO,UAAUA,CAACC,KAAc,EAAE;IACjC,MAAMC,WAAW,GAAG,IAAAC,oCAAwB,EAACF,KAAK,CAAC;IAEnD,IACEC,WAAW,YAAYE,6BAAiB,IACxC,IAAI,CAACC,YAAY,CAAC,SAAS,EAAEH,WAAW,CAAC,EACzC;MACA;MACA;IACF;IAEA,MAAMA,WAAW;EACnB;;EAEA;AACF;AACA;AACA;EACUI,WAAWA,CAAIC,OAAmB,EAAE;IAC1C,OAAO,IAAIC,OAAO,CAAI,CAACC,OAAO,EAAEC,MAAM,KAAK;MACzCH,OAAO,CAACI,IAAI,CAACF,OAAO,CAAC,CAACG,KAAK,CAAEX,KAAK,IAAK;QACrCS,MAAM,CAAC,IAAI,CAACV,UAAU,CAACC,KAAK,CAAC,CAAC;MAChC,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ;;EAEA;EACA,IAAIX,MAAMA,CAAA,EAAsB;IAC9B,OAAO,IAAI,CAACG,MAAM,CAACH,MAAM;EAC3B;;EAEA;EACA,IAAIuB,MAAMA,CAAA,EAAsB;IAC9B,OAAO,IAAI,CAACpB,MAAM,CAACoB,MAAM;EAC3B;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAACrB,MAAM,CAACqB,QAAQ;EAC7B;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAW;IACnB,OAAO,IAAI,CAACtB,MAAM,CAACsB,MAAM;EAC3B;EAEA,IAAIA,MAAMA,CAACC,KAAa,EAAE;IACxB,IAAI,CAACvB,MAAM,CAACsB,MAAM,GAAGC,KAAK;EAC5B;;EAEA;EACA,IAAIC,WAAWA,CAAA,EAAW;IACxB,OAAO,IAAI,CAACxB,MAAM,CAACwB,WAAW;EAChC;EAEA,IAAIA,WAAWA,CAACD,KAAa,EAAE;IAC7B,IAAI,CAACvB,MAAM,CAACwB,WAAW,GAAGD,KAAK;EACjC;;EAEA;EACA,IAAIE,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAACzB,MAAM,CAACyB,KAAK;EAC1B;EAEA,IAAIA,KAAKA,CAACF,KAAc,EAAE;IACxB,IAAI,CAACvB,MAAM,CAACyB,KAAK,GAAGF,KAAK;EAC3B;;EAEA;EACA,IAAIG,IAAIA,CAAA,EAAY;IAClB,OAAO,IAAI,CAAC1B,MAAM,CAAC0B,IAAI;EACzB;EAEA,IAAIA,IAAIA,CAACH,KAAc,EAAE;IACvB,IAAI,CAACvB,MAAM,CAAC0B,IAAI,GAAGH,KAAK;EAC1B;;EAEA;EACA,IAAII,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAAC3B,MAAM,CAAC2B,IAAI;EACzB;EAEA,IAAIA,IAAIA,CAACJ,KAAa,EAAE;IACtB,IAAI,CAACvB,MAAM,CAAC2B,IAAI,GAAGJ,KAAK;EAC1B;;EAEA;EACA,IAAIK,YAAYA,CAAA,EAAiB;IAC/B,OAAO,IAAI,CAAC5B,MAAM,CAAC4B,YAAY;EACjC;EAEA,IAAIA,YAAYA,CAACL,KAAmB,EAAE;IACpC,IAAI,CAACvB,MAAM,CAAC4B,YAAY,GAAGL,KAAK;EAClC;;EAEA;EACA,IAAIM,sBAAsBA,CAAA,EAA2B;IACnD,OAAO,IAAI,CAAC7B,MAAM,CAAC6B,sBAAsB;EAC3C;EAEA,IAAIA,sBAAsBA,CAACN,KAA6B,EAAE;IACxD,IAAIO,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,CAACC,QAAQ,CAACC,qBAAQ,CAACC,EAAE,CAAC,EAAE;MAC7CC,OAAO,CAACC,IAAI,CACV,mFACF,CAAC;IACH;IAEA,IAAI,CAACnC,MAAM,CAAC6B,sBAAsB,GAAGN,KAAK;EAC5C;;EAEA;EACA,IAAIa,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI,CAACpC,MAAM,CAACoC,gBAAgB;EACrC;EAEA,IAAIA,gBAAgBA,CAACb,KAAc,EAAE;IACnC,IAAI,CAACvB,MAAM,CAACoC,gBAAgB,GAAGb,KAAK;EACtC;;EAEA;EACA,IAAIc,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI,CAACrC,MAAM,CAACqC,gBAAgB;EACrC;EAEA,IAAIA,gBAAgBA,CAACd,KAAc,EAAE;IACnC,IAAI,CAACvB,MAAM,CAACqC,gBAAgB,GAAGd,KAAK;EACtC;;EAEA;EACA,IAAIe,SAASA,CAAA,EAAY;IACvB,OAAO,IAAI,CAACtC,MAAM,CAACsC,SAAS;EAC9B;EAEA,IAAIC,wBAAwBA,CAAA,EAAY;IACtC,OAAO,IAAI,CAACvC,MAAM,CAACuC,wBAAwB;EAC7C;EAEA,IAAIA,wBAAwBA,CAAChB,KAAc,EAAE;IAC3C,IAAI,CAACvB,MAAM,CAACuC,wBAAwB,GAAGhB,KAAK;EAC9C;EAEA,MAAMiB,UAAUA,CAAA,EAAkB;IAChC,MAAM,IAAI,CAAC3B,WAAW,CAAC,IAAI,CAACb,MAAM,CAACwC,UAAU,CAAC,CAAC,CAAC;IAEhDC,qCAAY,CAACC,gBAAgB,CAAC,IAAI,CAAC1C,MAAM,CAAC;EAC5C;EAEA,MAAM2C,OAAOA,CAAA,EAAkB;IAC7B,MAAM,IAAI,CAAC9B,WAAW,CAAC,IAAI,CAACb,MAAM,CAAC2C,OAAO,CAAC,CAAC,CAAC;IAE7CF,qCAAY,CAACC,gBAAgB,CAAC,IAAI,CAAC1C,MAAM,CAAC;EAC5C;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE4C,OAAOA,CAAA,EAAS;IACd,IAAI,CAACzC,SAAS,CAAC,CAAC;EAClB;EAEA0C,IAAIA,CAAA,EAAS;IACX,IAAI;MACF,IAAI,CAAC7C,MAAM,CAAC6C,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,OAAOrC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAsC,KAAKA,CAAA,EAAS;IACZ,IAAI;MACF,IAAI,CAAC9C,MAAM,CAAC8C,KAAK,CAAC,CAAC;IACrB,CAAC,CAAC,OAAOtC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAuC,MAAMA,CAACC,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAAChD,MAAM,CAAC+C,MAAM,CAACC,IAAI,CAAC;IAC1B,CAAC,CAAC,OAAOxC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAyC,MAAMA,CAACD,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAAChD,MAAM,CAACiD,MAAM,CAACD,IAAI,CAAC;IAC1B,CAAC,CAAC,OAAOxC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEA,MAAM0C,kBAAkBA,CACtBrD,MAA4E,EAC7D;IACf,MAAM,IAAI,CAACgB,WAAW,CACpB,IAAI,CAACb,MAAM,CAACkD,kBAAkB,CAC5BrD,MAAM,KAAK,IAAI,GAAG,IAAI,GAAG,IAAAE,2BAAY,EAACF,MAAM,CAC9C,CACF,CAAC;IAED4C,qCAAY,CAACC,gBAAgB,CAAC,IAAI,CAAC1C,MAAM,CAAC;EAC5C;;EAEA;EACAmD,sBAAsBA,CAAA,EAAgB;IACpC,IAAI;MACF,OAAO,IAAI,CAACnD,MAAM,CAACmD,sBAAsB,CAAC,CAAC;IAC7C,CAAC,CAAC,OAAO3C,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;MACtB,OAAO,EAAE;IACX;EACF;EAEA4C,eAAeA,CAACC,SAA2B,EAAQ;IACjD,IAAI;MACF,IAAI,CAACrD,MAAM,CAACoD,eAAe,CAACC,SAAS,CAAC;IACxC,CAAC,CAAC,OAAO7C,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;;EAEA;EACA,IAAI8C,aAAaA,CAAA,EAA0B;IACzC,OAAO,IAAI,CAACtD,MAAM,CAACsD,aAAa;EAClC;AACF;AAACC,OAAA,CAAA7D,WAAA,GAAAA,WAAA","ignoreList":[]} diff --git a/lib/commonjs/core/VideoPlayer.web.js b/lib/commonjs/core/VideoPlayer.web.js new file mode 100644 index 00000000..8abf9609 --- /dev/null +++ b/lib/commonjs/core/VideoPlayer.web.js @@ -0,0 +1,241 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.VideoPlayer = void 0; +var _shakaPlayer = _interopRequireDefault(require("shaka-player")); +var _VideoError = require("./types/VideoError.js"); +var _VideoPlayerEvents = require("./VideoPlayerEvents.js"); +var _WebEventEmiter = require("./WebEventEmiter.js"); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +class VideoPlayer extends _VideoPlayerEvents.VideoPlayerEvents { + player = new _shakaPlayer.default.Player(); + headers = {}; + constructor(source) { + const video = document.createElement("video"); + super(new _WebEventEmiter.WebEventEmiter(video)); + this.video = video; + this.player.attach(this.video); + this.player.getNetworkingEngine().registerRequestFilter((_type, request) => { + request.headers = this.headers; + }); + this.replaceSourceAsync(source); + } + + /** + * Cleans up player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * @internal + */ + __destroy() { + this.player.destroy(); + } + __getNativeRef() { + return this.video; + } + + /** + * Handles parsing native errors to VideoRuntimeError and calling onError if provided + * @internal + */ + throwError(error) { + const parsedError = (0, _VideoError.tryParseNativeVideoError)(error); + if (parsedError instanceof _VideoError.VideoRuntimeError && this.triggerEvent("onError", parsedError)) { + // We don't throw errors if onError is provided + return; + } + throw parsedError; + } + + // Source + get source() { + // TODO: properly implement this + return { + uri: this.player.getAssetUri(), + config: {} + }; + } + + // Status + get status() { + if (this.video.error) return "error"; + if (this.video.readyState === HTMLMediaElement.HAVE_NOTHING) return "idle"; + if (this.video.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA || this.video.readyState === HTMLMediaElement.HAVE_FUTURE_DATA) return "readyToPlay"; + return "loading"; + } + + // Duration + get duration() { + return this.video.duration; + } + + // Volume + get volume() { + return this.video.volume; + } + set volume(value) { + this.video.volume = value; + } + + // Current Time + get currentTime() { + return this.video.currentTime; + } + set currentTime(value) { + this.video.currentTime = value; + } + + // Muted + get muted() { + return this.video.muted; + } + set muted(value) { + this.video.muted = value; + } + + // Loop + get loop() { + return this.video.loop; + } + set loop(value) { + this.video.loop = value; + } + + // Rate + get rate() { + return this.video.playbackRate; + } + set rate(value) { + this.video.playbackRate = value; + } + + // Mix Audio Mode + get mixAudioMode() { + return "auto"; + } + set mixAudioMode(_) { + if (__DEV__) { + console.warn("mixAudioMode is not supported on this platform, it wont have any effect"); + } + } + + // Ignore Silent Switch Mode + get ignoreSilentSwitchMode() { + return "auto"; + } + set ignoreSilentSwitchMode(_) { + if (__DEV__) { + console.warn("ignoreSilentSwitchMode is not supported on this platform, it wont have any effect"); + } + } + + // Play In Background + get playInBackground() { + return true; + } + set playInBackground(_) { + if (__DEV__) { + console.warn("playInBackground is not supported on this platform, it wont have any effect"); + } + } + + // Play When Inactive + get playWhenInactive() { + return true; + } + set playWhenInactive(_) { + if (__DEV__) { + console.warn("playWhenInactive is not supported on this platform, it wont have any effect"); + } + } + + // Is Playing + get isPlaying() { + return this.status === "readyToPlay" && !this.video.paused; + } + async initialize() { + // noop on web + } + async preload() { + // we start loading when initializing the source. + } + + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release() { + this.__destroy(); + } + play() { + try { + this.video.play(); + } catch (error) { + this.throwError(error); + } + } + pause() { + try { + this.video.pause(); + } catch (error) { + this.throwError(error); + } + } + seekBy(time) { + try { + this.video.currentTime += time; + } catch (error) { + this.throwError(error); + } + } + seekTo(time) { + try { + this.video.currentTime = time; + } catch (error) { + this.throwError(error); + } + } + async replaceSourceAsync(source) { + const src = typeof source === "object" && source && "uri" in source ? source.uri : source; + if (typeof src === "number") { + console.error("A source uri must be a string. Numbers are only supported on native."); + return; + } + // TODO: handle start time + this.player.load(src); + if (typeof source !== "object") return; + this.headers = source?.headers ?? {}; + // this.player.configure({ + // drm: undefined, + // streaming: { + // bufferingGoal: source?.bufferConfig?.maxBufferMs, + // }, + // } satisfies Partial); + } + + // Text Track Management + getAvailableTextTracks() { + return this.player.getTextTracks().map(x => ({ + id: x.id.toString(), + label: x.label ?? "", + language: x.language, + selected: x.active + })); + } + selectTextTrack(textTrack) { + this.player.setTextTrackVisibility(textTrack !== null); + if (!textTrack) return; + const track = this.player.getTextTracks().find(x => x.id === Number(textTrack.id)); + if (track) this.player.selectTextTrack(track); + } + + // Selected Text Track + get selectedTrack() { + return this.getAvailableTextTracks().find(x => x.selected); + } +} +exports.VideoPlayer = VideoPlayer; +//# sourceMappingURL=VideoPlayer.web.js.map \ No newline at end of file diff --git a/lib/commonjs/core/VideoPlayer.web.js.map b/lib/commonjs/core/VideoPlayer.web.js.map new file mode 100644 index 00000000..e9df602f --- /dev/null +++ b/lib/commonjs/core/VideoPlayer.web.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_shakaPlayer","_interopRequireDefault","require","_VideoError","_VideoPlayerEvents","_WebEventEmiter","e","__esModule","default","VideoPlayer","VideoPlayerEvents","player","shaka","Player","headers","constructor","source","video","document","createElement","WebEventEmiter","attach","getNetworkingEngine","registerRequestFilter","_type","request","replaceSourceAsync","__destroy","destroy","__getNativeRef","throwError","error","parsedError","tryParseNativeVideoError","VideoRuntimeError","triggerEvent","uri","getAssetUri","config","status","readyState","HTMLMediaElement","HAVE_NOTHING","HAVE_ENOUGH_DATA","HAVE_FUTURE_DATA","duration","volume","value","currentTime","muted","loop","rate","playbackRate","mixAudioMode","_","__DEV__","console","warn","ignoreSilentSwitchMode","playInBackground","playWhenInactive","isPlaying","paused","initialize","preload","release","play","pause","seekBy","time","seekTo","src","load","getAvailableTextTracks","getTextTracks","map","x","id","toString","label","language","selected","active","selectTextTrack","textTrack","setTextTrackVisibility","track","find","Number","selectedTrack","exports"],"sourceRoot":"../../../src","sources":["core/VideoPlayer.web.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAOA,IAAAC,WAAA,GAAAD,OAAA;AAMA,IAAAE,kBAAA,GAAAF,OAAA;AACA,IAAAG,eAAA,GAAAH,OAAA;AAAkD,SAAAD,uBAAAK,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAElD,MAAMG,WAAW,SAASC,oCAAiB,CAA4B;EAC3DC,MAAM,GAAG,IAAIC,oBAAK,CAACC,MAAM,CAAC,CAAC;EAE3BC,OAAO,GAA2B,CAAC,CAAC;EAE9CC,WAAWA,CAACC,MAAqD,EAAE;IACjE,MAAMC,KAAK,GAAGC,QAAQ,CAACC,aAAa,CAAC,OAAO,CAAC;IAC7C,KAAK,CAAC,IAAIC,8BAAc,CAACH,KAAK,CAAC,CAAC;IAChC,IAAI,CAACA,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACN,MAAM,CAACU,MAAM,CAAC,IAAI,CAACJ,KAAK,CAAC;IAC9B,IAAI,CAACN,MAAM,CAACW,mBAAmB,CAAC,CAAC,CAAEC,qBAAqB,CAAC,CAACC,KAAK,EAAEC,OAAO,KAAK;MAC3EA,OAAO,CAACX,OAAO,GAAG,IAAI,CAACA,OAAO;IAChC,CAAC,CAAC;IACF,IAAI,CAACY,kBAAkB,CAACV,MAAM,CAAC;EACjC;;EAEA;AACF;AACA;AACA;AACA;EACEW,SAASA,CAAA,EAAG;IACV,IAAI,CAAChB,MAAM,CAACiB,OAAO,CAAC,CAAC;EACvB;EAEAC,cAAcA,CAAA,EAAG;IACf,OAAO,IAAI,CAACZ,KAAK;EACnB;;EAEA;AACF;AACA;AACA;EACUa,UAAUA,CAACC,KAAc,EAAE;IACjC,MAAMC,WAAW,GAAG,IAAAC,oCAAwB,EAACF,KAAK,CAAC;IAEnD,IACEC,WAAW,YAAYE,6BAAiB,IACxC,IAAI,CAACC,YAAY,CAAC,SAAS,EAAEH,WAAW,CAAC,EACzC;MACA;MACA;IACF;IAEA,MAAMA,WAAW;EACnB;;EAEA;EACA,IAAIhB,MAAMA,CAAA,EAAsB;IAC9B;IACA,OAAO;MACLoB,GAAG,EAAE,IAAI,CAACzB,MAAM,CAAC0B,WAAW,CAAC,CAAE;MAC/BC,MAAM,EAAE,CAAC;IACX,CAAC;EACH;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAsB;IAC9B,IAAI,IAAI,CAACtB,KAAK,CAACc,KAAK,EAAE,OAAO,OAAO;IACpC,IAAI,IAAI,CAACd,KAAK,CAACuB,UAAU,KAAKC,gBAAgB,CAACC,YAAY,EAAE,OAAO,MAAM;IAC1E,IACE,IAAI,CAACzB,KAAK,CAACuB,UAAU,KAAKC,gBAAgB,CAACE,gBAAgB,IAC3D,IAAI,CAAC1B,KAAK,CAACuB,UAAU,KAAKC,gBAAgB,CAACG,gBAAgB,EAE3D,OAAO,aAAa;IACtB,OAAO,SAAS;EAClB;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAAC5B,KAAK,CAAC4B,QAAQ;EAC5B;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAW;IACnB,OAAO,IAAI,CAAC7B,KAAK,CAAC6B,MAAM;EAC1B;EAEA,IAAIA,MAAMA,CAACC,KAAa,EAAE;IACxB,IAAI,CAAC9B,KAAK,CAAC6B,MAAM,GAAGC,KAAK;EAC3B;;EAEA;EACA,IAAIC,WAAWA,CAAA,EAAW;IACxB,OAAO,IAAI,CAAC/B,KAAK,CAAC+B,WAAW;EAC/B;EAEA,IAAIA,WAAWA,CAACD,KAAa,EAAE;IAC7B,IAAI,CAAC9B,KAAK,CAAC+B,WAAW,GAAGD,KAAK;EAChC;;EAEA;EACA,IAAIE,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAAChC,KAAK,CAACgC,KAAK;EACzB;EAEA,IAAIA,KAAKA,CAACF,KAAc,EAAE;IACxB,IAAI,CAAC9B,KAAK,CAACgC,KAAK,GAAGF,KAAK;EAC1B;;EAEA;EACA,IAAIG,IAAIA,CAAA,EAAY;IAClB,OAAO,IAAI,CAACjC,KAAK,CAACiC,IAAI;EACxB;EAEA,IAAIA,IAAIA,CAACH,KAAc,EAAE;IACvB,IAAI,CAAC9B,KAAK,CAACiC,IAAI,GAAGH,KAAK;EACzB;;EAEA;EACA,IAAII,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAAClC,KAAK,CAACmC,YAAY;EAChC;EAEA,IAAID,IAAIA,CAACJ,KAAa,EAAE;IACtB,IAAI,CAAC9B,KAAK,CAACmC,YAAY,GAAGL,KAAK;EACjC;;EAEA;EACA,IAAIM,YAAYA,CAAA,EAAiB;IAC/B,OAAO,MAAM;EACf;EAEA,IAAIA,YAAYA,CAACC,CAAe,EAAE;IAChC,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,yEACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIC,sBAAsBA,CAAA,EAA2B;IACnD,OAAO,MAAM;EACf;EAEA,IAAIA,sBAAsBA,CAACJ,CAAyB,EAAE;IACpD,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,mFACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIE,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI;EACb;EAEA,IAAIA,gBAAgBA,CAACL,CAAU,EAAE;IAC/B,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,6EACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIG,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI;EACb;EAEA,IAAIA,gBAAgBA,CAACN,CAAU,EAAE;IAC/B,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,6EACF,CAAC;IACH;EACF;;EAEA;EACA,IAAII,SAASA,CAAA,EAAY;IACvB,OAAO,IAAI,CAACtB,MAAM,KAAK,aAAa,IAAI,CAAC,IAAI,CAACtB,KAAK,CAAC6C,MAAM;EAC5D;EAEA,MAAMC,UAAUA,CAAA,EAAkB;IAChC;EAAA;EAGF,MAAMC,OAAOA,CAAA,EAAkB;IAC7B;EAAA;;EAGF;AACF;AACA;AACA;AACA;AACA;EACEC,OAAOA,CAAA,EAAS;IACd,IAAI,CAACtC,SAAS,CAAC,CAAC;EAClB;EAEAuC,IAAIA,CAAA,EAAS;IACX,IAAI;MACF,IAAI,CAACjD,KAAK,CAACiD,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC,OAAOnC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAoC,KAAKA,CAAA,EAAS;IACZ,IAAI;MACF,IAAI,CAAClD,KAAK,CAACkD,KAAK,CAAC,CAAC;IACpB,CAAC,CAAC,OAAOpC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAqC,MAAMA,CAACC,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAACpD,KAAK,CAAC+B,WAAW,IAAIqB,IAAI;IAChC,CAAC,CAAC,OAAOtC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAuC,MAAMA,CAACD,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAACpD,KAAK,CAAC+B,WAAW,GAAGqB,IAAI;IAC/B,CAAC,CAAC,OAAOtC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEA,MAAML,kBAAkBA,CACtBV,MAIQ,EACO;IACf,MAAMuD,GAAG,GACP,OAAOvD,MAAM,KAAK,QAAQ,IAAIA,MAAM,IAAI,KAAK,IAAIA,MAAM,GACnDA,MAAM,CAACoB,GAAG,GACVpB,MAAM;IACZ,IAAI,OAAOuD,GAAG,KAAK,QAAQ,EAAE;MAC3Bf,OAAO,CAACzB,KAAK,CAAC,sEAAsE,CAAC;MACrF;IACF;IACA;IACA,IAAI,CAACpB,MAAM,CAAC6D,IAAI,CAACD,GAAG,CAAC;IACrB,IAAI,OAAOvD,MAAM,KAAK,QAAQ,EAAE;IAEhC,IAAI,CAACF,OAAO,GAAGE,MAAM,EAAEF,OAAO,IAAI,CAAC,CAAC;IACtC;IACA;IACA;IACA;IACA;IACA;EACA;;EAEA;EACA2D,sBAAsBA,CAAA,EAAgB;IACpC,OAAO,IAAI,CAAC9D,MAAM,CAAC+D,aAAa,CAAC,CAAC,CAACC,GAAG,CAACC,CAAC,KAAK;MAC3CC,EAAE,EAAED,CAAC,CAACC,EAAE,CAACC,QAAQ,CAAC,CAAC;MACnBC,KAAK,EAAEH,CAAC,CAACG,KAAK,IAAI,EAAE;MACpBC,QAAQ,EAAEJ,CAAC,CAACI,QAAQ;MACpBC,QAAQ,EAAEL,CAAC,CAACM;IACd,CAAC,CAAC,CAAC;EACL;EAEAC,eAAeA,CAACC,SAA2B,EAAQ;IACjD,IAAI,CAACzE,MAAM,CAAC0E,sBAAsB,CAACD,SAAS,KAAK,IAAI,CAAC;IACtD,IAAI,CAACA,SAAS,EAAE;IAChB,MAAME,KAAK,GAAG,IAAI,CAAC3E,MAAM,CACtB+D,aAAa,CAAC,CAAC,CACfa,IAAI,CAAEX,CAAC,IAAKA,CAAC,CAACC,EAAE,KAAKW,MAAM,CAACJ,SAAS,CAACP,EAAE,CAAC,CAAC;IAC7C,IAAIS,KAAK,EAAE,IAAI,CAAC3E,MAAM,CAACwE,eAAe,CAACG,KAAK,CAAC;EAC/C;;EAEA;EACA,IAAIG,aAAaA,CAAA,EAA0B;IACzC,OAAO,IAAI,CAAChB,sBAAsB,CAAC,CAAC,CAACc,IAAI,CAACX,CAAC,IAAIA,CAAC,CAACK,QAAQ,CAAC;EAC5D;AACF;AAACS,OAAA,CAAAjF,WAAA,GAAAA,WAAA","ignoreList":[]} diff --git a/lib/commonjs/core/VideoPlayerEvents.js b/lib/commonjs/core/VideoPlayerEvents.js new file mode 100644 index 00000000..67cb6e35 --- /dev/null +++ b/lib/commonjs/core/VideoPlayerEvents.js @@ -0,0 +1,51 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.VideoPlayerEvents = void 0; +var _Events = require("./types/Events.js"); +class VideoPlayerEvents { + eventListeners = {}; + supportedEvents = _Events.ALL_PLAYER_EVENTS; + constructor(eventEmitter) { + this.eventEmitter = eventEmitter; + for (const event of this.supportedEvents) { + // @ts-expect-error we narrow the type of the event + this.eventEmitter[event] = this.triggerEvent.bind(this, event); + } + } + triggerEvent(event, ...params) { + if (!this.eventListeners[event]?.size) return false; + for (const fn of this.eventListeners[event]) { + fn(...params); + } + return true; + } + addEventListener(event, callback) { + this.eventListeners[event] ??= new Set(); + this.eventListeners[event].add(callback); + } + removeEventListener(event, callback) { + this.eventListeners[event]?.delete(callback); + } + + /** + * Clears all events from the event emitter. + */ + clearAllEvents() { + this.supportedEvents.forEach(event => { + this.clearEvent(event); + }); + } + + /** + * Clears a specific event from the event emitter. + * @param event - The name of the event to clear. + */ + clearEvent(event) { + this.eventListeners[event]?.clear(); + } +} +exports.VideoPlayerEvents = VideoPlayerEvents; +//# sourceMappingURL=VideoPlayerEvents.js.map \ No newline at end of file diff --git a/lib/commonjs/core/VideoPlayerEvents.js.map b/lib/commonjs/core/VideoPlayerEvents.js.map new file mode 100644 index 00000000..20e71a6f --- /dev/null +++ b/lib/commonjs/core/VideoPlayerEvents.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_Events","require","VideoPlayerEvents","eventListeners","supportedEvents","ALL_PLAYER_EVENTS","constructor","eventEmitter","event","triggerEvent","bind","params","size","fn","addEventListener","callback","Set","add","removeEventListener","delete","clearAllEvents","forEach","clearEvent","clear","exports"],"sourceRoot":"../../../src","sources":["core/VideoPlayerEvents.ts"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAMO,MAAMC,iBAAiB,CAAC;EAEnBC,cAAc,GAEpB,CAAC,CAAC;EAEaC,eAAe,GAChCC,yBAAiB;EAEnBC,WAAWA,CAACC,YAAgC,EAAE;IAC5C,IAAI,CAACA,YAAY,GAAGA,YAAY;IAChC,KAAK,MAAMC,KAAK,IAAI,IAAI,CAACJ,eAAe,EAAE;MACxC;MACA,IAAI,CAACG,YAAY,CAACC,KAAK,CAAC,GAAG,IAAI,CAACC,YAAY,CAACC,IAAI,CAAC,IAAI,EAAEF,KAAK,CAAC;IAChE;EACF;EAEUC,YAAYA,CACpBD,KAAY,EACZ,GAAGG,MAAuC,EACjC;IACT,IAAI,CAAC,IAAI,CAACR,cAAc,CAACK,KAAK,CAAC,EAAEI,IAAI,EAAE,OAAO,KAAK;IACnD,KAAK,MAAMC,EAAE,IAAI,IAAI,CAACV,cAAc,CAACK,KAAK,CAAC,EAAE;MAC3CK,EAAE,CAAC,GAAGF,MAAM,CAAC;IACf;IACA,OAAO,IAAI;EACb;EAEAG,gBAAgBA,CACdN,KAAY,EACZO,QAA6B,EAC7B;IACA,IAAI,CAACZ,cAAc,CAACK,KAAK,CAAC,KAAK,IAAIQ,GAAG,CAAsB,CAAC;IAC7D,IAAI,CAACb,cAAc,CAACK,KAAK,CAAC,CAACS,GAAG,CAACF,QAAQ,CAAC;EAC1C;EAEAG,mBAAmBA,CACjBV,KAAY,EACZO,QAA6B,EAC7B;IACA,IAAI,CAACZ,cAAc,CAACK,KAAK,CAAC,EAAEW,MAAM,CAACJ,QAAQ,CAAC;EAC9C;;EAEA;AACF;AACA;EACEK,cAAcA,CAAA,EAAG;IACf,IAAI,CAAChB,eAAe,CAACiB,OAAO,CAAEb,KAAK,IAAK;MACtC,IAAI,CAACc,UAAU,CAACd,KAAK,CAAC;IACxB,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;EACEc,UAAUA,CAACd,KAAyB,EAAE;IACpC,IAAI,CAACL,cAAc,CAACK,KAAK,CAAC,EAAEe,KAAK,CAAC,CAAC;EACrC;AACF;AAACC,OAAA,CAAAtB,iBAAA,GAAAA,iBAAA","ignoreList":[]} diff --git a/lib/commonjs/core/WebEventEmiter.js b/lib/commonjs/core/WebEventEmiter.js new file mode 100644 index 00000000..5356b7fa --- /dev/null +++ b/lib/commonjs/core/WebEventEmiter.js @@ -0,0 +1,181 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebEventEmiter = void 0; +class WebEventEmiter { + _isBuferring = false; + constructor(video) { + this.video = video; + // TODO: add `onBandwithUpdate` + + // on buffer + this._onCanPlay = this._onCanPlay.bind(this); + this._onWaiting = this._onWaiting.bind(this); + this.video.addEventListener("canplay", this._onCanPlay); + this.video.addEventListener("waiting", this._onWaiting); + + // on end + this._onEnded = this._onEnded.bind(this); + this.video.addEventListener("ended", this._onEnded); + + // on load + this._onDurationChange = this._onDurationChange.bind(this); + this.video.addEventListener("durationchange", this._onDurationChange); + + // on load start + this._onLoadStart = this._onLoadStart.bind(this); + this.video.addEventListener("loadstart", this._onLoadStart); + + // on playback state change + this._onPlay = this._onPlay.bind(this); + this._onPause = this._onPause.bind(this); + this.video.addEventListener("play", this._onPlay); + this.video.addEventListener("pause", this._onPause); + + // on playback rate change + this._onRateChange = this._onRateChange.bind(this); + this.video.addEventListener("ratechange", this._onRateChange); + + // on progress + this._onTimeUpdate = this._onTimeUpdate.bind(this); + this.video.addEventListener("timeupdate", this._onTimeUpdate); + + // on ready to play + this._onLoadedData = this._onLoadedData.bind(this); + this.video.addEventListener("loadeddata", this._onLoadedData); + + // on seek + this._onSeeked = this._onSeeked.bind(this); + this.video.addEventListener("seeked", this._onSeeked); + + // on volume change + this._onVolumeChange = this._onVolumeChange.bind(this); + this.video.addEventListener("volumechange", this._onVolumeChange); + + // on status change + this._onError = this._onError.bind(this); + this.video.addEventListener("error", this._onError); + } + destroy() { + this.video.removeEventListener("canplay", this._onCanPlay); + this.video.removeEventListener("waiting", this._onWaiting); + this.video.removeEventListener("ended", this._onEnded); + this.video.removeEventListener("durationchange", this._onDurationChange); + this.video.removeEventListener("play", this._onPlay); + this.video.removeEventListener("pause", this._onPause); + this.video.removeEventListener("ratechange", this._onRateChange); + this.video.removeEventListener("timeupdate", this._onTimeUpdate); + this.video.removeEventListener("loadeddata", this._onLoadedData); + this.video.removeEventListener("seeked", this._onSeeked); + this.video.removeEventListener("volumechange", this._onVolumeChange); + this.video.removeEventListener("error", this._onError); + } + _onTimeUpdate() { + this.onProgress({ + currentTime: this.video.currentTime, + bufferDuration: this.video.buffered.length ? this.video.buffered.end(this.video.buffered.length - 1) : 0 + }); + } + _onCanPlay() { + this._isBuferring = false; + this.onBuffer(false); + this.onStatusChange("readyToPlay"); + } + _onWaiting() { + this._isBuferring = true; + this.onBuffer(true); + this.onStatusChange("loading"); + } + _onDurationChange() { + this.onLoad({ + currentTime: this.video.currentTime, + duration: this.video.duration, + width: this.video.width, + height: this.video.height, + orientation: "unknown" + }); + } + _onEnded() { + this.onEnd(); + this.onStatusChange("idle"); + } + _onLoadStart() { + this.onLoadStart({ + sourceType: "network", + source: { + uri: this.video.currentSrc, + config: { + uri: this.video.currentSrc, + externalSubtitles: [] + }, + getAssetInformationAsync: async () => { + return { + duration: BigInt(this.video.duration), + height: this.video.height, + width: this.video.width, + orientation: "unknown", + bitrate: NaN, + fileSize: BigInt(NaN), + isHDR: false, + isLive: false + }; + } + } + }); + } + _onPlay() { + this.onPlaybackStateChange({ + isPlaying: true, + isBuffering: this._isBuferring + }); + } + _onPause() { + this.onPlaybackStateChange({ + isPlaying: false, + isBuffering: this._isBuferring + }); + } + _onRateChange() { + this.onPlaybackRateChange(this.video.playbackRate); + } + _onLoadedData() { + this.onReadyToDisplay(); + } + _onSeeked() { + this.onSeek(this.video.currentTime); + } + _onVolumeChange() { + this.onVolumeChange({ + muted: this.video.muted, + volume: this.video.volume + }); + } + _onError() { + this.onStatusChange("error"); + } + NOOP = () => {}; + onError = this.NOOP; + onAudioBecomingNoisy = this.NOOP; + onAudioFocusChange = this.NOOP; + onBandwidthUpdate = this.NOOP; + onBuffer = this.NOOP; + onControlsVisibleChange = this.NOOP; + onEnd = this.NOOP; + onExternalPlaybackChange = this.NOOP; + onLoad = this.NOOP; + onLoadStart = this.NOOP; + onPlaybackStateChange = this.NOOP; + onPlaybackRateChange = this.NOOP; + onProgress = this.NOOP; + onReadyToDisplay = this.NOOP; + onSeek = this.NOOP; + onTimedMetadata = this.NOOP; + onTextTrackDataChanged = this.NOOP; + onTrackChange = this.NOOP; + onVolumeChange = this.NOOP; + onStatusChange = this.NOOP; +} +exports.WebEventEmiter = WebEventEmiter; +//# sourceMappingURL=WebEventEmiter.js.map \ No newline at end of file diff --git a/lib/commonjs/core/WebEventEmiter.js.map b/lib/commonjs/core/WebEventEmiter.js.map new file mode 100644 index 00000000..f46800bf --- /dev/null +++ b/lib/commonjs/core/WebEventEmiter.js.map @@ -0,0 +1 @@ +{"version":3,"names":["WebEventEmiter","_isBuferring","constructor","video","_onCanPlay","bind","_onWaiting","addEventListener","_onEnded","_onDurationChange","_onLoadStart","_onPlay","_onPause","_onRateChange","_onTimeUpdate","_onLoadedData","_onSeeked","_onVolumeChange","_onError","destroy","removeEventListener","onProgress","currentTime","bufferDuration","buffered","length","end","onBuffer","onStatusChange","onLoad","duration","width","height","orientation","onEnd","onLoadStart","sourceType","source","uri","currentSrc","config","externalSubtitles","getAssetInformationAsync","BigInt","bitrate","NaN","fileSize","isHDR","isLive","onPlaybackStateChange","isPlaying","isBuffering","onPlaybackRateChange","playbackRate","onReadyToDisplay","onSeek","onVolumeChange","muted","volume","NOOP","onError","onAudioBecomingNoisy","onAudioFocusChange","onBandwidthUpdate","onControlsVisibleChange","onExternalPlaybackChange","onTimedMetadata","onTextTrackDataChanged","onTrackChange","exports"],"sourceRoot":"../../../src","sources":["core/WebEventEmiter.ts"],"mappings":";;;;;;AAcO,MAAMA,cAAc,CAAyB;EAC1CC,YAAY,GAAG,KAAK;EAE5BC,WAAWA,CAASC,KAAuB,EAAE;IAAA,KAAzBA,KAAuB,GAAvBA,KAAuB;IACzC;;IAEA;IACA,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAACC,IAAI,CAAC,IAAI,CAAC;IAC5C,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAACD,IAAI,CAAC,IAAI,CAAC;IAC5C,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAACH,UAAU,CAAC;IACvD,IAAI,CAACD,KAAK,CAACI,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAACD,UAAU,CAAC;;IAEvD;IACA,IAAI,CAACE,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACH,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,QAAQ,CAAC;;IAEnD;IACA,IAAI,CAACC,iBAAiB,GAAG,IAAI,CAACA,iBAAiB,CAACJ,IAAI,CAAC,IAAI,CAAC;IAC1D,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAACE,iBAAiB,CAAC;;IAErE;IACA,IAAI,CAACC,YAAY,GAAG,IAAI,CAACA,YAAY,CAACL,IAAI,CAAC,IAAI,CAAC;IAChD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAACG,YAAY,CAAC;;IAE3D;IACA,IAAI,CAACC,OAAO,GAAG,IAAI,CAACA,OAAO,CAACN,IAAI,CAAC,IAAI,CAAC;IACtC,IAAI,CAACO,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACP,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAACI,OAAO,CAAC;IACjD,IAAI,CAACR,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACK,QAAQ,CAAC;;IAEnD;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACR,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACM,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACT,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACO,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACV,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACQ,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,SAAS,GAAG,IAAI,CAACA,SAAS,CAACX,IAAI,CAAC,IAAI,CAAC;IAC1C,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAACS,SAAS,CAAC;;IAErD;IACA,IAAI,CAACC,eAAe,GAAG,IAAI,CAACA,eAAe,CAACZ,IAAI,CAAC,IAAI,CAAC;IACtD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAACU,eAAe,CAAC;;IAEjE;IACA,IAAI,CAACC,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACb,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACW,QAAQ,CAAC;EACrD;EAEAC,OAAOA,CAAA,EAAG;IACR,IAAI,CAAChB,KAAK,CAACiB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAChB,UAAU,CAAC;IAC1D,IAAI,CAACD,KAAK,CAACiB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAACd,UAAU,CAAC;IAE1D,IAAI,CAACH,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACZ,QAAQ,CAAC;IAEtD,IAAI,CAACL,KAAK,CAACiB,mBAAmB,CAAC,gBAAgB,EAAE,IAAI,CAACX,iBAAiB,CAAC;IAExE,IAAI,CAACN,KAAK,CAACiB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAACT,OAAO,CAAC;IACpD,IAAI,CAACR,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACR,QAAQ,CAAC;IAEtD,IAAI,CAACT,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACP,aAAa,CAAC;IAEhE,IAAI,CAACV,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACN,aAAa,CAAC;IAEhE,IAAI,CAACX,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACL,aAAa,CAAC;IAEhE,IAAI,CAACZ,KAAK,CAACiB,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAACJ,SAAS,CAAC;IAExD,IAAI,CAACb,KAAK,CAACiB,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAACH,eAAe,CAAC;IAEpE,IAAI,CAACd,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACF,QAAQ,CAAC;EACxD;EAEAJ,aAAaA,CAAA,EAAG;IACd,IAAI,CAACO,UAAU,CAAC;MACdC,WAAW,EAAE,IAAI,CAACnB,KAAK,CAACmB,WAAW;MACnCC,cAAc,EAAE,IAAI,CAACpB,KAAK,CAACqB,QAAQ,CAACC,MAAM,GACtC,IAAI,CAACtB,KAAK,CAACqB,QAAQ,CAACE,GAAG,CAAC,IAAI,CAACvB,KAAK,CAACqB,QAAQ,CAACC,MAAM,GAAG,CAAC,CAAC,GACvD;IACN,CAAC,CAAC;EACJ;EAEArB,UAAUA,CAAA,EAAG;IACX,IAAI,CAACH,YAAY,GAAG,KAAK;IACzB,IAAI,CAAC0B,QAAQ,CAAC,KAAK,CAAC;IACpB,IAAI,CAACC,cAAc,CAAC,aAAa,CAAC;EACpC;EACAtB,UAAUA,CAAA,EAAG;IACX,IAAI,CAACL,YAAY,GAAG,IAAI;IACxB,IAAI,CAAC0B,QAAQ,CAAC,IAAI,CAAC;IACnB,IAAI,CAACC,cAAc,CAAC,SAAS,CAAC;EAChC;EAEAnB,iBAAiBA,CAAA,EAAG;IAClB,IAAI,CAACoB,MAAM,CAAC;MACVP,WAAW,EAAE,IAAI,CAACnB,KAAK,CAACmB,WAAW;MACnCQ,QAAQ,EAAE,IAAI,CAAC3B,KAAK,CAAC2B,QAAQ;MAC7BC,KAAK,EAAE,IAAI,CAAC5B,KAAK,CAAC4B,KAAK;MACvBC,MAAM,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,MAAM;MACzBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ;EAEAzB,QAAQA,CAAA,EAAG;IACT,IAAI,CAAC0B,KAAK,CAAC,CAAC;IACZ,IAAI,CAACN,cAAc,CAAC,MAAM,CAAC;EAC7B;EAEAlB,YAAYA,CAAA,EAAG;IACb,IAAI,CAACyB,WAAW,CAAC;MACfC,UAAU,EAAE,SAAS;MACrBC,MAAM,EAAE;QACNC,GAAG,EAAE,IAAI,CAACnC,KAAK,CAACoC,UAAU;QAC1BC,MAAM,EAAE;UACNF,GAAG,EAAE,IAAI,CAACnC,KAAK,CAACoC,UAAU;UAC1BE,iBAAiB,EAAE;QACrB,CAAC;QACDC,wBAAwB,EAAE,MAAAA,CAAA,KAAY;UACpC,OAAO;YACLZ,QAAQ,EAAEa,MAAM,CAAC,IAAI,CAACxC,KAAK,CAAC2B,QAAQ,CAAC;YACrCE,MAAM,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,MAAM;YACzBD,KAAK,EAAE,IAAI,CAAC5B,KAAK,CAAC4B,KAAK;YACvBE,WAAW,EAAE,SAAS;YACtBW,OAAO,EAAEC,GAAG;YACZC,QAAQ,EAAEH,MAAM,CAACE,GAAG,CAAC;YACrBE,KAAK,EAAE,KAAK;YACZC,MAAM,EAAE;UACV,CAAC;QACH;MACF;IACF,CAAC,CAAC;EACJ;EAEArC,OAAOA,CAAA,EAAG;IACR,IAAI,CAACsC,qBAAqB,CAAC;MACzBC,SAAS,EAAE,IAAI;MACfC,WAAW,EAAE,IAAI,CAAClD;IACpB,CAAC,CAAC;EACJ;EAEAW,QAAQA,CAAA,EAAG;IACT,IAAI,CAACqC,qBAAqB,CAAC;MACzBC,SAAS,EAAE,KAAK;MAChBC,WAAW,EAAE,IAAI,CAAClD;IACpB,CAAC,CAAC;EACJ;EAEAY,aAAaA,CAAA,EAAG;IACd,IAAI,CAACuC,oBAAoB,CAAC,IAAI,CAACjD,KAAK,CAACkD,YAAY,CAAC;EACpD;EAEAtC,aAAaA,CAAA,EAAG;IACd,IAAI,CAACuC,gBAAgB,CAAC,CAAC;EACzB;EAEAtC,SAASA,CAAA,EAAG;IACV,IAAI,CAACuC,MAAM,CAAC,IAAI,CAACpD,KAAK,CAACmB,WAAW,CAAC;EACrC;EAEAL,eAAeA,CAAA,EAAG;IAChB,IAAI,CAACuC,cAAc,CAAC;MAAEC,KAAK,EAAE,IAAI,CAACtD,KAAK,CAACsD,KAAK;MAAEC,MAAM,EAAE,IAAI,CAACvD,KAAK,CAACuD;IAAO,CAAC,CAAC;EAC7E;EAEAxC,QAAQA,CAAA,EAAG;IACT,IAAI,CAACU,cAAc,CAAC,OAAO,CAAC;EAC9B;EAEA+B,IAAI,GAAGA,CAAA,KAAM,CAAC,CAAC;EAEfC,OAAO,GAAuC,IAAI,CAACD,IAAI;EACvDE,oBAAoB,GAAe,IAAI,CAACF,IAAI;EAC5CG,kBAAkB,GAAqC,IAAI,CAACH,IAAI;EAChEI,iBAAiB,GAAkC,IAAI,CAACJ,IAAI;EAC5DhC,QAAQ,GAAiC,IAAI,CAACgC,IAAI;EAClDK,uBAAuB,GAA+B,IAAI,CAACL,IAAI;EAC/DzB,KAAK,GAAe,IAAI,CAACyB,IAAI;EAC7BM,wBAAwB,GACtB,IAAI,CAACN,IAAI;EACX9B,MAAM,GAA+B,IAAI,CAAC8B,IAAI;EAC9CxB,WAAW,GAAoC,IAAI,CAACwB,IAAI;EACxDV,qBAAqB,GAA8C,IAAI,CAACU,IAAI;EAC5EP,oBAAoB,GAA2B,IAAI,CAACO,IAAI;EACxDtC,UAAU,GAAmC,IAAI,CAACsC,IAAI;EACtDL,gBAAgB,GAAe,IAAI,CAACK,IAAI;EACxCJ,MAAM,GAA+B,IAAI,CAACI,IAAI;EAC9CO,eAAe,GAAsC,IAAI,CAACP,IAAI;EAC9DQ,sBAAsB,GAA8B,IAAI,CAACR,IAAI;EAC7DS,aAAa,GAAsC,IAAI,CAACT,IAAI;EAC5DH,cAAc,GAAuC,IAAI,CAACG,IAAI;EAC9D/B,cAAc,GAAwC,IAAI,CAAC+B,IAAI;AACjE;AAACU,OAAA,CAAArE,cAAA,GAAAA,cAAA","ignoreList":[]} diff --git a/lib/commonjs/core/hooks/useEvent.js b/lib/commonjs/core/hooks/useEvent.js new file mode 100644 index 00000000..5bfdf646 --- /dev/null +++ b/lib/commonjs/core/hooks/useEvent.js @@ -0,0 +1,22 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.useEvent = void 0; +var _react = require("react"); +/** + * Attaches an event listener to a `VideoPlayer` instance for a specified event. + * + * @param player - The player to attach the event to + * @param event - The name of the event to attach the callback to + * @param callback - The callback for the event + */ +const useEvent = (player, event, callback) => { + (0, _react.useEffect)(() => { + player.addEventListener(event, callback); + return () => player.removeEventListener(event, callback); + }, [player, event, callback]); +}; +exports.useEvent = useEvent; +//# sourceMappingURL=useEvent.js.map \ No newline at end of file diff --git a/lib/commonjs/core/hooks/useEvent.js.map b/lib/commonjs/core/hooks/useEvent.js.map new file mode 100644 index 00000000..6a209219 --- /dev/null +++ b/lib/commonjs/core/hooks/useEvent.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_react","require","useEvent","player","event","callback","useEffect","addEventListener","removeEventListener","exports"],"sourceRoot":"../../../../src","sources":["core/hooks/useEvent.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,QAAQ,GAAGA,CACtBC,MAAmB,EACnBC,KAAQ,EACRC,QAA4B,KACzB;EACH,IAAAC,gBAAS,EAAC,MAAM;IACdH,MAAM,CAACI,gBAAgB,CAACH,KAAK,EAAEC,QAAQ,CAAC;IAExC,OAAO,MAAMF,MAAM,CAACK,mBAAmB,CAACJ,KAAK,EAAEC,QAAQ,CAAC;EAC1D,CAAC,EAAE,CAACF,MAAM,EAAEC,KAAK,EAAEC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAACI,OAAA,CAAAP,QAAA,GAAAA,QAAA","ignoreList":[]} diff --git a/lib/commonjs/core/hooks/useManagedInstance.js b/lib/commonjs/core/hooks/useManagedInstance.js new file mode 100644 index 00000000..c818da57 --- /dev/null +++ b/lib/commonjs/core/hooks/useManagedInstance.js @@ -0,0 +1,79 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.useManagedInstance = void 0; +var _react = require("react"); +/** + * @internal + * A hook that helps to manage the lifecycle of a native instance in a React component. + * It allows instance to be recreated when dependencies change, but not when the component is hot reloaded. + * + * @param config.factory - The factory function that creates the instance. + * @param config.cleanup - The cleanup function that destroys the instance. + * @param config.dependenciesEqualFn - The function that compares the dependencies. + * + * @param dependencies - The dependencies array. + * @returns The managed instance. + */ +const useManagedInstance = (config, dependencies) => { + const { + factory, + cleanup, + dependenciesEqualFn + } = config; + const objectRef = (0, _react.useRef)(null); + const isFastRefresh = (0, _react.useRef)(false); + const previousDependencies = (0, _react.useRef)(dependencies); + + // Wee need to force a "re-render" to recalculate the object + const [released, setReleased] = (0, _react.useState)(false); + if (objectRef.current == null) { + objectRef.current = factory(); + } + const object = (0, _react.useMemo)(() => { + let newObject = objectRef.current; + const dependenciesChanged = previousDependencies.current?.length === dependencies.length && dependencies.every((value, index) => dependenciesEqualFn?.(value, previousDependencies.current[index]) ?? value === previousDependencies.current[index]); + if (!newObject || !dependenciesChanged || released) { + // Destroy the old object + if (objectRef.current) { + cleanup(objectRef.current); + objectRef.current = null; + } + + // Create a new object + newObject = factory(); + objectRef.current = newObject; + setReleased(false); + + // Update the previous dependencies + previousDependencies.current = dependencies; + } else { + // If useMemo is re-evaluated, but dependencies are the same + // and object is still the same, we can assume that that + // the component is being hot reloaded + isFastRefresh.current = true; + } + return newObject; + + // factory and cleanup are stable, so we don't need to re-evaluate + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [...dependencies, released]); + (0, _react.useEffect)(() => { + isFastRefresh.current = false; + return () => { + if (!isFastRefresh.current && objectRef.current) { + cleanup(objectRef.current); + objectRef.current = null; + setReleased(true); + } + }; + + // factory and cleanup are stable, so we don't need to re-evaluate + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return object; +}; +exports.useManagedInstance = useManagedInstance; +//# sourceMappingURL=useManagedInstance.js.map \ No newline at end of file diff --git a/lib/commonjs/core/hooks/useManagedInstance.js.map b/lib/commonjs/core/hooks/useManagedInstance.js.map new file mode 100644 index 00000000..8fc07915 --- /dev/null +++ b/lib/commonjs/core/hooks/useManagedInstance.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_react","require","useManagedInstance","config","dependencies","factory","cleanup","dependenciesEqualFn","objectRef","useRef","isFastRefresh","previousDependencies","released","setReleased","useState","current","object","useMemo","newObject","dependenciesChanged","length","every","value","index","useEffect","exports"],"sourceRoot":"../../../../src","sources":["core/hooks/useManagedInstance.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,kBAAkB,GAAGA,CAChCC,MAIC,EACDC,YAAiB,KACX;EACN,MAAM;IAAEC,OAAO;IAAEC,OAAO;IAAEC;EAAoB,CAAC,GAAGJ,MAAM;EAExD,MAAMK,SAAS,GAAG,IAAAC,aAAM,EAAW,IAAI,CAAC;EACxC,MAAMC,aAAa,GAAG,IAAAD,aAAM,EAAC,KAAK,CAAC;EACnC,MAAME,oBAAoB,GAAG,IAAAF,aAAM,EAACL,YAAY,CAAC;;EAEjD;EACA,MAAM,CAACQ,QAAQ,EAAEC,WAAW,CAAC,GAAG,IAAAC,eAAQ,EAAC,KAAK,CAAC;EAE/C,IAAIN,SAAS,CAACO,OAAO,IAAI,IAAI,EAAE;IAC7BP,SAAS,CAACO,OAAO,GAAGV,OAAO,CAAC,CAAC;EAC/B;EAEA,MAAMW,MAAM,GAAG,IAAAC,cAAO,EAAC,MAAM;IAC3B,IAAIC,SAAS,GAAGV,SAAS,CAACO,OAAO;IAEjC,MAAMI,mBAAmB,GACvBR,oBAAoB,CAACI,OAAO,EAAEK,MAAM,KAAKhB,YAAY,CAACgB,MAAM,IAC5DhB,YAAY,CAACiB,KAAK,CAChB,CAACC,KAAK,EAAEC,KAAK,KACXhB,mBAAmB,GAAGe,KAAK,EAAEX,oBAAoB,CAACI,OAAO,CAACQ,KAAK,CAAC,CAAC,IACjED,KAAK,KAAKX,oBAAoB,CAACI,OAAO,CAACQ,KAAK,CAChD,CAAC;IAEH,IAAI,CAACL,SAAS,IAAI,CAACC,mBAAmB,IAAIP,QAAQ,EAAE;MAClD;MACA,IAAIJ,SAAS,CAACO,OAAO,EAAE;QACrBT,OAAO,CAACE,SAAS,CAACO,OAAO,CAAC;QAC1BP,SAAS,CAACO,OAAO,GAAG,IAAI;MAC1B;;MAEA;MACAG,SAAS,GAAGb,OAAO,CAAC,CAAC;MACrBG,SAAS,CAACO,OAAO,GAAGG,SAAS;MAC7BL,WAAW,CAAC,KAAK,CAAC;;MAElB;MACAF,oBAAoB,CAACI,OAAO,GAAGX,YAAY;IAC7C,CAAC,MAAM;MACL;MACA;MACA;MACAM,aAAa,CAACK,OAAO,GAAG,IAAI;IAC9B;IAEA,OAAOG,SAAS;;IAEhB;IACA;EACF,CAAC,EAAE,CAAC,GAAGd,YAAY,EAAEQ,QAAQ,CAAC,CAAC;EAE/B,IAAAY,gBAAS,EAAC,MAAM;IACdd,aAAa,CAACK,OAAO,GAAG,KAAK;IAE7B,OAAO,MAAM;MACX,IAAI,CAACL,aAAa,CAACK,OAAO,IAAIP,SAAS,CAACO,OAAO,EAAE;QAC/CT,OAAO,CAACE,SAAS,CAACO,OAAO,CAAC;QAC1BP,SAAS,CAACO,OAAO,GAAG,IAAI;QACxBF,WAAW,CAAC,IAAI,CAAC;MACnB;IACF,CAAC;;IAED;IACA;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOG,MAAM;AACf,CAAC;AAACS,OAAA,CAAAvB,kBAAA,GAAAA,kBAAA","ignoreList":[]} diff --git a/lib/commonjs/core/hooks/useVideoPlayer.js b/lib/commonjs/core/hooks/useVideoPlayer.js new file mode 100644 index 00000000..9a387ae3 --- /dev/null +++ b/lib/commonjs/core/hooks/useVideoPlayer.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.useVideoPlayer = void 0; +var _sourceUtils = require("../utils/sourceUtils.js"); +var _VideoPlayer = require("../VideoPlayer"); +var _useManagedInstance = require("./useManagedInstance.js"); +const sourceEqual = (a, b) => { + if ((0, _sourceUtils.isVideoPlayerSource)(a) && (0, _sourceUtils.isVideoPlayerSource)(b)) { + return a.equals(b); + } + return JSON.stringify(a) === JSON.stringify(b); +}; + +/** + * Creates a `VideoPlayer` instance and manages its lifecycle. + * + * @param source - The source of the video to play + * @param setup - A function to setup the player + * @returns The `VideoPlayer` instance + */ +const useVideoPlayer = (source, setup) => { + return (0, _useManagedInstance.useManagedInstance)({ + factory: () => { + const player = new _VideoPlayer.VideoPlayer(source); + setup?.(player); + return player; + }, + cleanup: player => { + player.__destroy(); + }, + dependenciesEqualFn: sourceEqual + }, [JSON.stringify(source)]); +}; +exports.useVideoPlayer = useVideoPlayer; +//# sourceMappingURL=useVideoPlayer.js.map \ No newline at end of file diff --git a/lib/commonjs/core/hooks/useVideoPlayer.js.map b/lib/commonjs/core/hooks/useVideoPlayer.js.map new file mode 100644 index 00000000..83040233 --- /dev/null +++ b/lib/commonjs/core/hooks/useVideoPlayer.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_sourceUtils","require","_VideoPlayer","_useManagedInstance","sourceEqual","a","b","isVideoPlayerSource","equals","JSON","stringify","useVideoPlayer","source","setup","useManagedInstance","factory","player","VideoPlayer","cleanup","__destroy","dependenciesEqualFn","exports"],"sourceRoot":"../../../../src","sources":["core/hooks/useVideoPlayer.ts"],"mappings":";;;;;;AAGA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,mBAAA,GAAAF,OAAA;AAEA,MAAMG,WAAW,GAAGA,CAClBC,CAAI,EACJC,CAAK,KACF;EACH,IAAI,IAAAC,gCAAmB,EAACF,CAAC,CAAC,IAAI,IAAAE,gCAAmB,EAACD,CAAC,CAAC,EAAE;IACpD,OAAOD,CAAC,CAACG,MAAM,CAACF,CAAC,CAAC;EACpB;EAEA,OAAOG,IAAI,CAACC,SAAS,CAACL,CAAC,CAAC,KAAKI,IAAI,CAACC,SAAS,CAACJ,CAAC,CAAC;AAChD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMK,cAAc,GAAGA,CAC5BC,MAAqE,EACrEC,KAAqC,KAClC;EACH,OAAO,IAAAC,sCAAkB,EACvB;IACEC,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMC,MAAM,GAAG,IAAIC,wBAAW,CAACL,MAAM,CAAC;MACtCC,KAAK,GAAGG,MAAM,CAAC;MACf,OAAOA,MAAM;IACf,CAAC;IACDE,OAAO,EAAGF,MAAM,IAAK;MACnBA,MAAM,CAACG,SAAS,CAAC,CAAC;IACpB,CAAC;IACDC,mBAAmB,EAAEhB;EACvB,CAAC,EACD,CAACK,IAAI,CAACC,SAAS,CAACE,MAAM,CAAC,CACzB,CAAC;AACH,CAAC;AAACS,OAAA,CAAAV,cAAA,GAAAA,cAAA","ignoreList":[]} diff --git a/lib/commonjs/core/shaka.d.js b/lib/commonjs/core/shaka.d.js new file mode 100644 index 00000000..42a8a048 --- /dev/null +++ b/lib/commonjs/core/shaka.d.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=shaka.d.js.map \ No newline at end of file diff --git a/lib/commonjs/core/shaka.d.js.map b/lib/commonjs/core/shaka.d.js.map new file mode 100644 index 00000000..bcdbf28a --- /dev/null +++ b/lib/commonjs/core/shaka.d.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../src","sources":["core/shaka.d.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/BufferConfig.js b/lib/commonjs/core/types/BufferConfig.js new file mode 100644 index 00000000..04aece6c --- /dev/null +++ b/lib/commonjs/core/types/BufferConfig.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=BufferConfig.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/BufferConfig.js.map b/lib/commonjs/core/types/BufferConfig.js.map new file mode 100644 index 00000000..475dae06 --- /dev/null +++ b/lib/commonjs/core/types/BufferConfig.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/BufferConfig.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/DrmParams.js b/lib/commonjs/core/types/DrmParams.js new file mode 100644 index 00000000..cd36ce84 --- /dev/null +++ b/lib/commonjs/core/types/DrmParams.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=DrmParams.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/DrmParams.js.map b/lib/commonjs/core/types/DrmParams.js.map new file mode 100644 index 00000000..378982d5 --- /dev/null +++ b/lib/commonjs/core/types/DrmParams.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/DrmParams.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/Events.js b/lib/commonjs/core/types/Events.js new file mode 100644 index 00000000..2c059a46 --- /dev/null +++ b/lib/commonjs/core/types/Events.js @@ -0,0 +1,13 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ALL_PLAYER_EVENTS = void 0; +function allKeysOf() { + return (...arr) => { + return arr; + }; +} +const ALL_PLAYER_EVENTS = exports.ALL_PLAYER_EVENTS = allKeysOf()('onAudioBecomingNoisy', 'onAudioFocusChange', 'onBandwidthUpdate', 'onBuffer', 'onControlsVisibleChange', 'onEnd', 'onError', 'onExternalPlaybackChange', 'onLoad', 'onLoadStart', 'onPlaybackStateChange', 'onPlaybackRateChange', 'onProgress', 'onReadyToDisplay', 'onSeek', 'onTimedMetadata', 'onTextTrackDataChanged', 'onTrackChange', 'onVolumeChange', 'onStatusChange'); +//# sourceMappingURL=Events.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/Events.js.map b/lib/commonjs/core/types/Events.js.map new file mode 100644 index 00000000..e8f5fc86 --- /dev/null +++ b/lib/commonjs/core/types/Events.js.map @@ -0,0 +1 @@ +{"version":3,"names":["allKeysOf","arr","ALL_PLAYER_EVENTS","exports"],"sourceRoot":"../../../../src","sources":["core/types/Events.ts"],"mappings":";;;;;;AAiPA,SAASA,SAASA,CAAA,EAAM;EACtB,OAAO,CAAiC,GAAGC,GAAM,KAA4B;IAC3E,OAAOA,GAAG;EACZ,CAAC;AACH;AAEO,MAAMC,iBAA4C,GAAAC,OAAA,CAAAD,iBAAA,GACvDF,SAAS,CAAkB,CAAC,CAC1B,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,yBAAyB,EACzB,OAAO,EACP,SAAS,EACT,0BAA0B,EAC1B,QAAQ,EACR,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,gBACF,CAAC","ignoreList":[]} diff --git a/lib/commonjs/core/types/IgnoreSilentSwitchMode.js b/lib/commonjs/core/types/IgnoreSilentSwitchMode.js new file mode 100644 index 00000000..36aad76d --- /dev/null +++ b/lib/commonjs/core/types/IgnoreSilentSwitchMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=IgnoreSilentSwitchMode.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/IgnoreSilentSwitchMode.js.map b/lib/commonjs/core/types/IgnoreSilentSwitchMode.js.map new file mode 100644 index 00000000..5e9f8609 --- /dev/null +++ b/lib/commonjs/core/types/IgnoreSilentSwitchMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/IgnoreSilentSwitchMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/MixAudioMode.js b/lib/commonjs/core/types/MixAudioMode.js new file mode 100644 index 00000000..3558637e --- /dev/null +++ b/lib/commonjs/core/types/MixAudioMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=MixAudioMode.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/MixAudioMode.js.map b/lib/commonjs/core/types/MixAudioMode.js.map new file mode 100644 index 00000000..2c7a41f3 --- /dev/null +++ b/lib/commonjs/core/types/MixAudioMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/MixAudioMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/ResizeMode.js b/lib/commonjs/core/types/ResizeMode.js new file mode 100644 index 00000000..38e4fbec --- /dev/null +++ b/lib/commonjs/core/types/ResizeMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=ResizeMode.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/ResizeMode.js.map b/lib/commonjs/core/types/ResizeMode.js.map new file mode 100644 index 00000000..900bbe3a --- /dev/null +++ b/lib/commonjs/core/types/ResizeMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/ResizeMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/TextTrack.js b/lib/commonjs/core/types/TextTrack.js new file mode 100644 index 00000000..c4369731 --- /dev/null +++ b/lib/commonjs/core/types/TextTrack.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=TextTrack.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/TextTrack.js.map b/lib/commonjs/core/types/TextTrack.js.map new file mode 100644 index 00000000..2e92273f --- /dev/null +++ b/lib/commonjs/core/types/TextTrack.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/TextTrack.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/Utils.js b/lib/commonjs/core/types/Utils.js new file mode 100644 index 00000000..49c9c084 --- /dev/null +++ b/lib/commonjs/core/types/Utils.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=Utils.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/Utils.js.map b/lib/commonjs/core/types/Utils.js.map new file mode 100644 index 00000000..2a9f052a --- /dev/null +++ b/lib/commonjs/core/types/Utils.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/Utils.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoConfig.js b/lib/commonjs/core/types/VideoConfig.js new file mode 100644 index 00000000..9317cb8a --- /dev/null +++ b/lib/commonjs/core/types/VideoConfig.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoConfig.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoConfig.js.map b/lib/commonjs/core/types/VideoConfig.js.map new file mode 100644 index 00000000..c894f838 --- /dev/null +++ b/lib/commonjs/core/types/VideoConfig.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoConfig.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoError.js b/lib/commonjs/core/types/VideoError.js new file mode 100644 index 00000000..fafd0ac6 --- /dev/null +++ b/lib/commonjs/core/types/VideoError.js @@ -0,0 +1,108 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.tryParseNativeVideoError = exports.VideoRuntimeError = exports.VideoError = exports.VideoComponentError = void 0; +class VideoError extends Error { + get code() { + return this._code; + } + get message() { + return this._message; + } + get stack() { + return this._stack; + } + + /** + * @internal + */ + constructor(code, message, stack) { + super(`[${code}]: ${message}`); + super.name = `[ReactNativeVideo] ${code}`; + super.message = message; + super.stack = stack; + this._code = code; + this._message = message; + this._stack = stack; + } + toString() { + let string = `[${this.code}]: ${this.message}`; + return string; + } +} +exports.VideoError = VideoError; +class VideoComponentError extends VideoError {} +exports.VideoComponentError = VideoComponentError; +class VideoRuntimeError extends VideoError {} + +/** + * Check if the message contains code and message + */ +exports.VideoRuntimeError = VideoRuntimeError; +const getCodeAndMessage = message => { + // (...){%@(match[1])::(match[2]);@%}(...) + const regex = /\{%@([^:]+)::([^@]+)@%\}/; + const match = message.match(regex); + if (match && match.length === 3 && typeof match[1] === 'string' && typeof match[2] === 'string') { + return { + code: match[1], + message: match[2] + }; + } + return null; +}; + +/** + * Check if the error has a stack property + * If it does, it will try to parse the error message in the stack trace + * and replace it with the proper code and message + */ +const maybeFixErrorStack = error => { + if ('stack' in error && typeof error.stack === 'string') { + const stack = error.stack; + + // (...){%@(match[1])::(match[2]);@%}(...) + const regex = /\{%@([^:]+)::([^@]+)@%\}/; + const match = stack.match(regex); + if (match && match.length === 3 && typeof match[1] === 'string' && typeof match[2] === 'string') { + error.stack = error.stack.replace(regex, `[${match[1]}]: ${match[2]}`); + } + } +}; +const isVideoError = error => typeof error === 'object' && error != null && +// @ts-expect-error error is still unknown +typeof error.message === 'string' && +// @ts-expect-error error is still unknown +getCodeAndMessage(error.message) != null; +const hasStack = error => typeof error === 'object' && error != null && 'stack' in error && typeof error.stack === 'string'; + +/** + * Tries to parse an error coming from native to a typed JS video error. + * @param {VideoError} nativeError The native error instance. This is a JSON in the legacy native module architecture. + * @returns A {@linkcode VideoRuntimeError} or {@linkcode VideoComponentError}, or the `nativeError` itself if it's not parsable + * @method + */ +const tryParseNativeVideoError = nativeError => { + if (isVideoError(nativeError)) { + const result = getCodeAndMessage(nativeError.message); + if (result == null) { + return nativeError; + } + const { + code, + message + } = result; + maybeFixErrorStack(nativeError); + if (code.startsWith('view')) { + return new VideoComponentError(code, message, hasStack(nativeError) ? nativeError.stack : undefined); + } + return new VideoRuntimeError( + // @ts-expect-error the code is string, we narrow it down to TS union. + code, message, hasStack(nativeError) ? nativeError.stack : undefined); + } + return nativeError; +}; +exports.tryParseNativeVideoError = tryParseNativeVideoError; +//# sourceMappingURL=VideoError.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoError.js.map b/lib/commonjs/core/types/VideoError.js.map new file mode 100644 index 00000000..248839a1 --- /dev/null +++ b/lib/commonjs/core/types/VideoError.js.map @@ -0,0 +1 @@ +{"version":3,"names":["VideoError","Error","code","_code","message","_message","stack","_stack","constructor","name","toString","string","exports","VideoComponentError","VideoRuntimeError","getCodeAndMessage","regex","match","length","maybeFixErrorStack","error","replace","isVideoError","hasStack","tryParseNativeVideoError","nativeError","result","startsWith","undefined"],"sourceRoot":"../../../../src","sources":["core/types/VideoError.ts"],"mappings":";;;;;;AA+BO,MAAMA,UAAU,SAAuCC,KAAK,CAAC;EAKlE,IAAWC,IAAIA,CAAA,EAAU;IACvB,OAAO,IAAI,CAACC,KAAK;EACnB;EACA,IAAWC,OAAOA,CAAA,EAAW;IAC3B,OAAO,IAAI,CAACC,QAAQ;EACtB;EAEA,IAAWC,KAAKA,CAAA,EAAuB;IACrC,OAAO,IAAI,CAACC,MAAM;EACpB;;EAEA;AACF;AACA;EACEC,WAAWA,CAACN,IAAW,EAAEE,OAAe,EAAEE,KAAc,EAAE;IACxD,KAAK,CAAC,IAAIJ,IAAI,MAAME,OAAO,EAAE,CAAC;IAC9B,KAAK,CAACK,IAAI,GAAG,sBAAsBP,IAAI,EAAE;IACzC,KAAK,CAACE,OAAO,GAAGA,OAAO;IACvB,KAAK,CAACE,KAAK,GAAGA,KAAK;IACnB,IAAI,CAACH,KAAK,GAAGD,IAAI;IACjB,IAAI,CAACG,QAAQ,GAAGD,OAAO;IACvB,IAAI,CAACG,MAAM,GAAGD,KAAK;EACrB;EAEOI,QAAQA,CAAA,EAAW;IACxB,IAAIC,MAAM,GAAG,IAAI,IAAI,CAACT,IAAI,MAAM,IAAI,CAACE,OAAO,EAAE;IAC9C,OAAOO,MAAM;EACf;AACF;AAACC,OAAA,CAAAZ,UAAA,GAAAA,UAAA;AAEM,MAAMa,mBAAmB,SAASb,UAAU,CAAiB;AAAEY,OAAA,CAAAC,mBAAA,GAAAA,mBAAA;AAE/D,MAAMC,iBAAiB,SAASd,UAAU,CAE/C;;AAEF;AACA;AACA;AAFAY,OAAA,CAAAE,iBAAA,GAAAA,iBAAA;AAGA,MAAMC,iBAAiB,GACrBX,OAAe,IAC8B;EAC7C;EACA,MAAMY,KAAK,GAAG,0BAA0B;EACxC,MAAMC,KAAK,GAAGb,OAAO,CAACa,KAAK,CAACD,KAAK,CAAC;EAElC,IACEC,KAAK,IACLA,KAAK,CAACC,MAAM,KAAK,CAAC,IAClB,OAAOD,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAC5B,OAAOA,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAC5B;IACA,OAAO;MACLf,IAAI,EAAEe,KAAK,CAAC,CAAC,CAAC;MACdb,OAAO,EAAEa,KAAK,CAAC,CAAC;IAClB,CAAC;EACH;EACA,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,MAAME,kBAAkB,GAAIC,KAAa,IAAK;EAC5C,IAAI,OAAO,IAAIA,KAAK,IAAI,OAAOA,KAAK,CAACd,KAAK,KAAK,QAAQ,EAAE;IACvD,MAAMA,KAAK,GAAGc,KAAK,CAACd,KAAK;;IAEzB;IACA,MAAMU,KAAK,GAAG,0BAA0B;IACxC,MAAMC,KAAK,GAAGX,KAAK,CAACW,KAAK,CAACD,KAAK,CAAC;IAEhC,IACEC,KAAK,IACLA,KAAK,CAACC,MAAM,KAAK,CAAC,IAClB,OAAOD,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAC5B,OAAOA,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAC5B;MACAG,KAAK,CAACd,KAAK,GAAGc,KAAK,CAACd,KAAK,CAACe,OAAO,CAACL,KAAK,EAAE,IAAIC,KAAK,CAAC,CAAC,CAAC,MAAMA,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE;EACF;AACF,CAAC;AAED,MAAMK,YAAY,GAChBF,KAAc,IAEd,OAAOA,KAAK,KAAK,QAAQ,IACzBA,KAAK,IAAI,IAAI;AACb;AACA,OAAOA,KAAK,CAAChB,OAAO,KAAK,QAAQ;AACjC;AACAW,iBAAiB,CAACK,KAAK,CAAChB,OAAO,CAAC,IAAI,IAAI;AAE1C,MAAMmB,QAAQ,GAAIH,KAAc,IAC9B,OAAOA,KAAK,KAAK,QAAQ,IACzBA,KAAK,IAAI,IAAI,IACb,OAAO,IAAIA,KAAK,IAChB,OAAOA,KAAK,CAACd,KAAK,KAAK,QAAQ;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACO,MAAMkB,wBAAwB,GACnCC,WAAc,IACoC;EAClD,IAAIH,YAAY,CAACG,WAAW,CAAC,EAAE;IAC7B,MAAMC,MAAM,GAAGX,iBAAiB,CAACU,WAAW,CAACrB,OAAO,CAAC;IAErD,IAAIsB,MAAM,IAAI,IAAI,EAAE;MAClB,OAAOD,WAAW;IACpB;IAEA,MAAM;MAAEvB,IAAI;MAAEE;IAAQ,CAAC,GAAGsB,MAAM;IAEhCP,kBAAkB,CAACM,WAAW,CAAC;IAE/B,IAAIvB,IAAI,CAACyB,UAAU,CAAC,MAAM,CAAC,EAAE;MAC3B,OAAO,IAAId,mBAAmB,CAC5BX,IAAI,EACJE,OAAO,EACPmB,QAAQ,CAACE,WAAW,CAAC,GAAGA,WAAW,CAACnB,KAAK,GAAGsB,SAC9C,CAAC;IACH;IAEA,OAAO,IAAId,iBAAiB;IAC1B;IACAZ,IAAI,EACJE,OAAO,EACPmB,QAAQ,CAACE,WAAW,CAAC,GAAGA,WAAW,CAACnB,KAAK,GAAGsB,SAC9C,CAAC;EACH;EAEA,OAAOH,WAAW;AACpB,CAAC;AAACb,OAAA,CAAAY,wBAAA,GAAAA,wBAAA","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoInformation.js b/lib/commonjs/core/types/VideoInformation.js new file mode 100644 index 00000000..0eb031be --- /dev/null +++ b/lib/commonjs/core/types/VideoInformation.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoInformation.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoInformation.js.map b/lib/commonjs/core/types/VideoInformation.js.map new file mode 100644 index 00000000..8c9c9dcf --- /dev/null +++ b/lib/commonjs/core/types/VideoInformation.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoInformation.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoOrientation.js b/lib/commonjs/core/types/VideoOrientation.js new file mode 100644 index 00000000..494f91d8 --- /dev/null +++ b/lib/commonjs/core/types/VideoOrientation.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=VideoOrientation.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoOrientation.js.map b/lib/commonjs/core/types/VideoOrientation.js.map new file mode 100644 index 00000000..e2ddd0b6 --- /dev/null +++ b/lib/commonjs/core/types/VideoOrientation.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoOrientation.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoPlayerBase.js b/lib/commonjs/core/types/VideoPlayerBase.js new file mode 100644 index 00000000..4f005b7f --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerBase.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoPlayerBase.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoPlayerBase.js.map b/lib/commonjs/core/types/VideoPlayerBase.js.map new file mode 100644 index 00000000..b84fa188 --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerBase.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerBase.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoPlayerSourceBase.js b/lib/commonjs/core/types/VideoPlayerSourceBase.js new file mode 100644 index 00000000..1380b3af --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerSourceBase.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoPlayerSourceBase.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoPlayerSourceBase.js.map b/lib/commonjs/core/types/VideoPlayerSourceBase.js.map new file mode 100644 index 00000000..405a67e8 --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerSourceBase.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerSourceBase.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/types/VideoPlayerStatus.js b/lib/commonjs/core/types/VideoPlayerStatus.js new file mode 100644 index 00000000..4bea2aef --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerStatus.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=VideoPlayerStatus.js.map \ No newline at end of file diff --git a/lib/commonjs/core/types/VideoPlayerStatus.js.map b/lib/commonjs/core/types/VideoPlayerStatus.js.map new file mode 100644 index 00000000..26429e64 --- /dev/null +++ b/lib/commonjs/core/types/VideoPlayerStatus.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerStatus.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/core/utils/playerFactory.js b/lib/commonjs/core/utils/playerFactory.js new file mode 100644 index 00000000..f89c9017 --- /dev/null +++ b/lib/commonjs/core/utils/playerFactory.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createPlayer = void 0; +var _reactNativeNitroModules = require("react-native-nitro-modules"); +var _sourceFactory = require("./sourceFactory.js"); +var _VideoError = require("../types/VideoError.js"); +var _sourceUtils = require("./sourceUtils.js"); +const VideoPlayerFactory = _reactNativeNitroModules.NitroModules.createHybridObject('VideoPlayerFactory'); + +/** + * @internal + * Creates a Native VideoPlayer instance. + * + * @param source - The source of the video to play + * @returns The Native VideoPlayer instance + */ +const createPlayer = source => { + try { + if ((0, _sourceUtils.isVideoPlayerSource)(source)) { + return VideoPlayerFactory.createPlayer(source); + } + return VideoPlayerFactory.createPlayer((0, _sourceFactory.createSource)(source)); + } catch (error) { + throw (0, _VideoError.tryParseNativeVideoError)(error); + } +}; +exports.createPlayer = createPlayer; +//# sourceMappingURL=playerFactory.js.map \ No newline at end of file diff --git a/lib/commonjs/core/utils/playerFactory.js.map b/lib/commonjs/core/utils/playerFactory.js.map new file mode 100644 index 00000000..d30dc64e --- /dev/null +++ b/lib/commonjs/core/utils/playerFactory.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_reactNativeNitroModules","require","_sourceFactory","_VideoError","_sourceUtils","VideoPlayerFactory","NitroModules","createHybridObject","createPlayer","source","isVideoPlayerSource","createSource","error","tryParseNativeVideoError","exports"],"sourceRoot":"../../../../src","sources":["core/utils/playerFactory.ts"],"mappings":";;;;;;AAAA,IAAAA,wBAAA,GAAAC,OAAA;AAOA,IAAAC,cAAA,GAAAD,OAAA;AACA,IAAAE,WAAA,GAAAF,OAAA;AACA,IAAAG,YAAA,GAAAH,OAAA;AAEA,MAAMI,kBAAkB,GACtBC,qCAAY,CAACC,kBAAkB,CAAqB,oBAAoB,CAAC;;AAE3E;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,YAAY,GACvBC,MAAqD,IACrC;EAChB,IAAI;IACF,IAAI,IAAAC,gCAAmB,EAACD,MAAM,CAAC,EAAE;MAC/B,OAAOJ,kBAAkB,CAACG,YAAY,CAACC,MAAM,CAAC;IAChD;IAEA,OAAOJ,kBAAkB,CAACG,YAAY,CAAC,IAAAG,2BAAY,EAACF,MAAM,CAAC,CAAC;EAC9D,CAAC,CAAC,OAAOG,KAAK,EAAE;IACd,MAAM,IAAAC,oCAAwB,EAACD,KAAK,CAAC;EACvC;AACF,CAAC;AAACE,OAAA,CAAAN,YAAA,GAAAA,YAAA","ignoreList":[]} diff --git a/lib/commonjs/core/utils/sourceFactory.js b/lib/commonjs/core/utils/sourceFactory.js new file mode 100644 index 00000000..d9de7445 --- /dev/null +++ b/lib/commonjs/core/utils/sourceFactory.js @@ -0,0 +1,122 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createSourceFromVideoConfig = exports.createSourceFromUri = exports.createSource = void 0; +var _reactNative = require("react-native"); +var _reactNativeNitroModules = require("react-native-nitro-modules"); +var _VideoError = require("../types/VideoError.js"); +var _sourceUtils = require("./sourceUtils.js"); +const VideoPlayerSourceFactory = _reactNativeNitroModules.NitroModules.createHybridObject('VideoPlayerSourceFactory'); + +/** + * Creates a `VideoPlayerSource` instance from a URI (string). + * + * @param uri - The URI of the video to play + * @returns The `VideoPlayerSource` instance + */ +const createSourceFromUri = uri => { + try { + return VideoPlayerSourceFactory.fromUri(uri); + } catch (error) { + throw (0, _VideoError.tryParseNativeVideoError)(error); + } +}; + +/** + * Creates a `VideoPlayerSource` instance from a `VideoConfig`. + * + * @note The `uri` property is required to be a string. + * + * @param config - The `VideoConfig` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +exports.createSourceFromUri = createSourceFromUri; +const createSourceFromVideoConfig = config => { + if (config.externalSubtitles) { + config.externalSubtitles = parseExternalSubtitles(config.externalSubtitles); + } + + // Ensure platform-based default for DRM type if DRM is provided without a type + if (config.drm && config.drm.type === undefined) { + const defaultDrmType = _reactNative.Platform.select({ + android: 'widevine', + ios: 'fairplay', + default: undefined + }); + if (defaultDrmType) { + config.drm = { + ...config.drm, + type: defaultDrmType + }; + } + } + + // Set default value for initializeOnCreation (true) + if (config.initializeOnCreation === undefined) { + config.initializeOnCreation = true; + } + try { + return VideoPlayerSourceFactory.fromVideoConfig(config); + } catch (error) { + throw (0, _VideoError.tryParseNativeVideoError)(error); + } +}; + +/** + * Parses the external subtitles from the `ExternalSubtitle` to the `NativeExternalSubtitle` format. + * + * @param externalSubtitles - The external subtitles to parse + * @returns The parsed external subtitles + */ +exports.createSourceFromVideoConfig = createSourceFromVideoConfig; +const parseExternalSubtitles = externalSubtitles => { + return externalSubtitles.map(subtitle => ({ + uri: subtitle.uri, + label: subtitle.label, + type: subtitle.type ?? 'auto', + language: subtitle.language ?? 'und' + })); +}; + +/** + * Creates a `VideoPlayerSource` + * + * @param source - The `VideoSource` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +const createSource = source => { + // If source is a VideoPlayerSource, we can directly return it + if ((0, _sourceUtils.isVideoPlayerSource)(source)) { + return source; + } + + // If source is a string, we can directly create the player + if (typeof source === 'string') { + return createSourceFromUri(source); + } + + // If source is a number (asset), we need to resolve the asset source and create the player + if (typeof source === 'number') { + return createSourceFromUri(_reactNative.Image.resolveAssetSource(source).uri); + } + + // If source is an object (VideoConfig) + if (typeof source === 'object' && 'uri' in source) { + if (typeof source.uri === 'string') { + return createSourceFromVideoConfig(source); + } + if (typeof source.uri === 'number') { + const config = { + ...source, + // Resolve the asset source to get the URI + uri: _reactNative.Image.resolveAssetSource(source.uri).uri + }; + return createSourceFromVideoConfig(config); + } + } + throw new Error('RNV: Invalid source type'); +}; +exports.createSource = createSource; +//# sourceMappingURL=sourceFactory.js.map \ No newline at end of file diff --git a/lib/commonjs/core/utils/sourceFactory.js.map b/lib/commonjs/core/utils/sourceFactory.js.map new file mode 100644 index 00000000..9e780f76 --- /dev/null +++ b/lib/commonjs/core/utils/sourceFactory.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_reactNative","require","_reactNativeNitroModules","_VideoError","_sourceUtils","VideoPlayerSourceFactory","NitroModules","createHybridObject","createSourceFromUri","uri","fromUri","error","tryParseNativeVideoError","exports","createSourceFromVideoConfig","config","externalSubtitles","parseExternalSubtitles","drm","type","undefined","defaultDrmType","Platform","select","android","ios","default","initializeOnCreation","fromVideoConfig","map","subtitle","label","language","createSource","source","isVideoPlayerSource","Image","resolveAssetSource","Error"],"sourceRoot":"../../../../src","sources":["core/utils/sourceFactory.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,wBAAA,GAAAD,OAAA;AAYA,IAAAE,WAAA,GAAAF,OAAA;AACA,IAAAG,YAAA,GAAAH,OAAA;AAEA,MAAMI,wBAAwB,GAC5BC,qCAAY,CAACC,kBAAkB,CAC7B,0BACF,CAAC;;AAEH;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,mBAAmB,GAAIC,GAAW,IAAK;EAClD,IAAI;IACF,OAAOJ,wBAAwB,CAACK,OAAO,CAACD,GAAG,CAAC;EAC9C,CAAC,CAAC,OAAOE,KAAK,EAAE;IACd,MAAM,IAAAC,oCAAwB,EAACD,KAAK,CAAC;EACvC;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPAE,OAAA,CAAAL,mBAAA,GAAAA,mBAAA;AAQO,MAAMM,2BAA2B,GACtCC,MAAqC,IAClC;EACH,IAAIA,MAAM,CAACC,iBAAiB,EAAE;IAC5BD,MAAM,CAACC,iBAAiB,GAAGC,sBAAsB,CAACF,MAAM,CAACC,iBAAiB,CAAC;EAC7E;;EAEA;EACA,IAAID,MAAM,CAACG,GAAG,IAAIH,MAAM,CAACG,GAAG,CAACC,IAAI,KAAKC,SAAS,EAAE;IAC/C,MAAMC,cAAc,GAAGC,qBAAQ,CAACC,MAAM,CAAC;MACrCC,OAAO,EAAE,UAAU;MACnBC,GAAG,EAAE,UAAU;MACfC,OAAO,EAAEN;IACX,CAAC,CAAC;IAEF,IAAIC,cAAc,EAAE;MAClBN,MAAM,CAACG,GAAG,GAAG;QACX,GAAGH,MAAM,CAACG,GAAG;QACbC,IAAI,EAAEE;MACR,CAAC;IACH;EACF;;EAEA;EACA,IAAIN,MAAM,CAACY,oBAAoB,KAAKP,SAAS,EAAE;IAC7CL,MAAM,CAACY,oBAAoB,GAAG,IAAI;EACpC;EAEA,IAAI;IACF,OAAOtB,wBAAwB,CAACuB,eAAe,CAC7Cb,MACF,CAAC;EACH,CAAC,CAAC,OAAOJ,KAAK,EAAE;IACd,MAAM,IAAAC,oCAAwB,EAACD,KAAK,CAAC;EACvC;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AALAE,OAAA,CAAAC,2BAAA,GAAAA,2BAAA;AAMA,MAAMG,sBAAsB,GAC1BD,iBAAqC,IACM;EAC3C,OAAOA,iBAAiB,CAACa,GAAG,CAAEC,QAAQ,KAAM;IAC1CrB,GAAG,EAAEqB,QAAQ,CAACrB,GAAG;IACjBsB,KAAK,EAAED,QAAQ,CAACC,KAAK;IACrBZ,IAAI,EAAGW,QAAQ,CAACX,IAAI,IAAI,MAAuB;IAC/Ca,QAAQ,EAAEF,QAAQ,CAACE,QAAQ,IAAI;EACjC,CAAC,CAAC,CAAC;AACL,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,YAAY,GACvBC,MAAqD,IAC/B;EACtB;EACA,IAAI,IAAAC,gCAAmB,EAACD,MAAM,CAAC,EAAE;IAC/B,OAAOA,MAAM;EACf;;EAEA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IAC9B,OAAO1B,mBAAmB,CAAC0B,MAAM,CAAC;EACpC;;EAEA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IAC9B,OAAO1B,mBAAmB,CAAC4B,kBAAK,CAACC,kBAAkB,CAACH,MAAM,CAAC,CAACzB,GAAG,CAAC;EAClE;;EAEA;EACA,IAAI,OAAOyB,MAAM,KAAK,QAAQ,IAAI,KAAK,IAAIA,MAAM,EAAE;IACjD,IAAI,OAAOA,MAAM,CAACzB,GAAG,KAAK,QAAQ,EAAE;MAClC,OAAOK,2BAA2B,CAChCoB,MACF,CAAC;IACH;IAEA,IAAI,OAAOA,MAAM,CAACzB,GAAG,KAAK,QAAQ,EAAE;MAClC,MAAMM,MAAM,GAAG;QACb,GAAGmB,MAAM;QACT;QACAzB,GAAG,EAAE2B,kBAAK,CAACC,kBAAkB,CAACH,MAAM,CAACzB,GAAG,CAAC,CAACA;MAC5C,CAAC;MAED,OAAOK,2BAA2B,CAACC,MAAM,CAAC;IAC5C;EACF;EAEA,MAAM,IAAIuB,KAAK,CAAC,0BAA0B,CAAC;AAC7C,CAAC;AAACzB,OAAA,CAAAoB,YAAA,GAAAA,YAAA","ignoreList":[]} diff --git a/lib/commonjs/core/utils/sourceUtils.js b/lib/commonjs/core/utils/sourceUtils.js new file mode 100644 index 00000000..efacf4d2 --- /dev/null +++ b/lib/commonjs/core/utils/sourceUtils.js @@ -0,0 +1,18 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isVideoPlayerSource = void 0; +const isVideoPlayerSource = obj => { + return obj && + // obj is not null + typeof obj === 'object' && + // obj is an object + 'name' in obj && + // obj has a name property + obj.name === 'VideoPlayerSource' // obj.name is 'VideoPlayerSource' + ; +}; +exports.isVideoPlayerSource = isVideoPlayerSource; +//# sourceMappingURL=sourceUtils.js.map \ No newline at end of file diff --git a/lib/commonjs/core/utils/sourceUtils.js.map b/lib/commonjs/core/utils/sourceUtils.js.map new file mode 100644 index 00000000..27c3c4c0 --- /dev/null +++ b/lib/commonjs/core/utils/sourceUtils.js.map @@ -0,0 +1 @@ +{"version":3,"names":["isVideoPlayerSource","obj","name","exports"],"sourceRoot":"../../../../src","sources":["core/utils/sourceUtils.ts"],"mappings":";;;;;;AAEO,MAAMA,mBAAmB,GAAIC,GAAQ,IAA+B;EACzE,OACEA,GAAG;EAAI;EACP,OAAOA,GAAG,KAAK,QAAQ;EAAI;EAC3B,MAAM,IAAIA,GAAG;EAAI;EACjBA,GAAG,CAACC,IAAI,KAAK,mBAAmB,CAAC;EAAA;AAErC,CAAC;AAACC,OAAA,CAAAH,mBAAA,GAAAA,mBAAA","ignoreList":[]} diff --git a/lib/commonjs/core/video-view/NativeVideoView.js b/lib/commonjs/core/video-view/NativeVideoView.js new file mode 100644 index 00000000..d050230e --- /dev/null +++ b/lib/commonjs/core/video-view/NativeVideoView.js @@ -0,0 +1,18 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.NativeVideoView = void 0; +var _reactNative = require("react-native"); +var _VideoViewNativeComponent = _interopRequireDefault(require("../../spec/fabric/VideoViewNativeComponent")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +const LINKING_ERROR = `The package 'react-native-video' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({ + ios: "- You have run 'pod install'\n", + default: '' +}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n'; +const ComponentName = 'VideoView'; +const NativeVideoView = exports.NativeVideoView = _reactNative.UIManager.hasViewManagerConfig(ComponentName) != null ? _VideoViewNativeComponent.default : () => { + throw new Error(LINKING_ERROR); +}; +//# sourceMappingURL=NativeVideoView.js.map \ No newline at end of file diff --git a/lib/commonjs/core/video-view/NativeVideoView.js.map b/lib/commonjs/core/video-view/NativeVideoView.js.map new file mode 100644 index 00000000..49e2ee16 --- /dev/null +++ b/lib/commonjs/core/video-view/NativeVideoView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_reactNative","require","_VideoViewNativeComponent","_interopRequireDefault","e","__esModule","default","LINKING_ERROR","Platform","select","ios","ComponentName","NativeVideoView","exports","UIManager","hasViewManagerConfig","VideoViewNativeComponent","Error"],"sourceRoot":"../../../../src","sources":["core/video-view/NativeVideoView.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,yBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAAkF,SAAAE,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAElF,MAAMG,aAAa,GACjB,6EAA6E,GAC7EC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEJ,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMK,aAAa,GAAG,WAAW;AAE1B,MAAMC,eAAe,GAAAC,OAAA,CAAAD,eAAA,GAC1BE,sBAAS,CAACC,oBAAoB,CAACJ,aAAa,CAAC,IAAI,IAAI,GACjDK,iCAAwB,GACxB,MAAM;EACJ,MAAM,IAAIC,KAAK,CAACV,aAAa,CAAC;AAChC,CAAC","ignoreList":[]} diff --git a/lib/commonjs/core/video-view/VideoView.js b/lib/commonjs/core/video-view/VideoView.js new file mode 100644 index 00000000..903d894a --- /dev/null +++ b/lib/commonjs/core/video-view/VideoView.js @@ -0,0 +1,139 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var React = _interopRequireWildcard(require("react")); +var _reactNativeNitroModules = require("react-native-nitro-modules"); +var _VideoError = require("../types/VideoError.js"); +var _NativeVideoView = require("./NativeVideoView.js"); +var _jsxRuntime = require("react/jsx-runtime"); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } +let nitroIdCounter = 1; +const VideoViewViewManagerFactory = _reactNativeNitroModules.NitroModules.createHybridObject('VideoViewViewManagerFactory'); +const wrapNativeViewManagerFunction = (manager, func) => { + try { + if (manager === null) { + throw new _VideoError.VideoError('view/not-found', 'View manager not found'); + } + return func(manager); + } catch (error) { + throw (0, _VideoError.tryParseNativeVideoError)(error); + } +}; +const updateProps = (manager, props) => { + manager.player = props.player.__getNativePlayer(); + manager.controls = props.controls ?? false; + manager.pictureInPicture = props.pictureInPicture ?? false; + manager.autoEnterPictureInPicture = props.autoEnterPictureInPicture ?? false; + manager.resizeMode = props.resizeMode ?? 'none'; + manager.onPictureInPictureChange = props.onPictureInPictureChange; + manager.onFullscreenChange = props.onFullscreenChange; + manager.willEnterFullscreen = props.willEnterFullscreen; + manager.willExitFullscreen = props.willExitFullscreen; + manager.willEnterPictureInPicture = props.willEnterPictureInPicture; + manager.willExitPictureInPicture = props.willExitPictureInPicture; + manager.keepScreenAwake = props.keepScreenAwake ?? true; + manager.surfaceType = props.surfaceType ?? 'surface'; +}; + +/** + * VideoView is a component that allows you to display a video from a {@link VideoPlayer}. + * + * @param player - The player to play the video - {@link VideoPlayer} + * @param controls - Whether to show the controls. Defaults to false. + * @param style - The style of the video view - {@link ViewStyle} + * @param pictureInPicture - Whether to show the picture in picture button. Defaults to false. + * @param autoEnterPictureInPicture - Whether to automatically enter picture in picture mode + * when the video is playing. Defaults to false. + * @param resizeMode - How the video should be resized to fit the view. Defaults to 'none'. + */ +const VideoView = /*#__PURE__*/React.forwardRef(({ + player, + controls = false, + pictureInPicture = false, + autoEnterPictureInPicture = false, + resizeMode = 'none', + ...props +}, ref) => { + const nitroId = React.useMemo(() => nitroIdCounter++, []); + const nitroViewManager = React.useRef(null); + const setupViewManager = React.useCallback(id => { + try { + if (nitroViewManager.current === null) { + nitroViewManager.current = VideoViewViewManagerFactory.createViewManager(id); + + // Should never happen + if (!nitroViewManager.current) { + throw new _VideoError.VideoError('view/not-found', 'Failed to create View Manager'); + } + } + + // Updates props to native view + updateProps(nitroViewManager.current, { + ...props, + player: player, + controls: controls, + pictureInPicture: pictureInPicture, + autoEnterPictureInPicture: autoEnterPictureInPicture, + resizeMode: resizeMode + }); + } catch (error) { + throw (0, _VideoError.tryParseNativeVideoError)(error); + } + }, [props, player, controls, pictureInPicture, autoEnterPictureInPicture, resizeMode]); + const onNitroIdChange = React.useCallback(event => { + setupViewManager(event.nativeEvent.nitroId); + }, [setupViewManager]); + React.useImperativeHandle(ref, () => ({ + enterFullscreen: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.enterFullscreen(); + }); + }, + exitFullscreen: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.exitFullscreen(); + }); + }, + enterPictureInPicture: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.enterPictureInPicture(); + }); + }, + exitPictureInPicture: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.exitPictureInPicture(); + }); + }, + canEnterPictureInPicture: () => { + return wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + return manager.canEnterPictureInPicture(); + }); + } + }), []); + React.useEffect(() => { + if (!nitroViewManager.current) { + return; + } + + // Updates props to native view + updateProps(nitroViewManager.current, { + ...props, + player: player, + controls: controls, + pictureInPicture: pictureInPicture, + autoEnterPictureInPicture: autoEnterPictureInPicture, + resizeMode: resizeMode + }); + }, [player, controls, pictureInPicture, autoEnterPictureInPicture, resizeMode, props]); + return /*#__PURE__*/(0, _jsxRuntime.jsx)(_NativeVideoView.NativeVideoView, { + nitroId: nitroId, + onNitroIdChange: onNitroIdChange, + ...props + }); +}); +VideoView.displayName = 'VideoView'; +var _default = exports.default = /*#__PURE__*/React.memo(VideoView); +//# sourceMappingURL=VideoView.js.map \ No newline at end of file diff --git a/lib/commonjs/core/video-view/VideoView.js.map b/lib/commonjs/core/video-view/VideoView.js.map new file mode 100644 index 00000000..8329b863 --- /dev/null +++ b/lib/commonjs/core/video-view/VideoView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["React","_interopRequireWildcard","require","_reactNativeNitroModules","_VideoError","_NativeVideoView","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","nitroIdCounter","VideoViewViewManagerFactory","NitroModules","createHybridObject","wrapNativeViewManagerFunction","manager","func","VideoError","error","tryParseNativeVideoError","updateProps","props","player","__getNativePlayer","controls","pictureInPicture","autoEnterPictureInPicture","resizeMode","onPictureInPictureChange","onFullscreenChange","willEnterFullscreen","willExitFullscreen","willEnterPictureInPicture","willExitPictureInPicture","keepScreenAwake","surfaceType","VideoView","forwardRef","ref","nitroId","useMemo","nitroViewManager","useRef","setupViewManager","useCallback","id","current","createViewManager","onNitroIdChange","event","nativeEvent","useImperativeHandle","enterFullscreen","exitFullscreen","enterPictureInPicture","exitPictureInPicture","canEnterPictureInPicture","useEffect","jsx","NativeVideoView","displayName","_default","exports","memo"],"sourceRoot":"../../../../src","sources":["core/video-view/VideoView.tsx"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AAEA,IAAAC,wBAAA,GAAAD,OAAA;AAKA,IAAAE,WAAA,GAAAF,OAAA;AAEA,IAAAG,gBAAA,GAAAH,OAAA;AAAoD,IAAAI,WAAA,GAAAJ,OAAA;AAAA,SAAAD,wBAAAM,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAR,uBAAA,YAAAA,CAAAM,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAGpD,IAAIkB,cAAc,GAAG,CAAC;AACtB,MAAMC,2BAA2B,GAC/BC,qCAAY,CAACC,kBAAkB,CAC7B,6BACF,CAAC;AAEH,MAAMC,6BAA6B,GAAGA,CACpCC,OAAoC,EACpCC,IAA0C,KACvC;EACH,IAAI;IACF,IAAID,OAAO,KAAK,IAAI,EAAE;MACpB,MAAM,IAAIE,sBAAU,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;IAClE;IAEA,OAAOD,IAAI,CAACD,OAAO,CAAC;EACtB,CAAC,CAAC,OAAOG,KAAK,EAAE;IACd,MAAM,IAAAC,oCAAwB,EAACD,KAAK,CAAC;EACvC;AACF,CAAC;AAED,MAAME,WAAW,GAAGA,CAACL,OAA6B,EAAEM,KAAqB,KAAK;EAC5EN,OAAO,CAACO,MAAM,GAAGD,KAAK,CAACC,MAAM,CAACC,iBAAiB,CAAC,CAAC;EACjDR,OAAO,CAACS,QAAQ,GAAGH,KAAK,CAACG,QAAQ,IAAI,KAAK;EAC1CT,OAAO,CAACU,gBAAgB,GAAGJ,KAAK,CAACI,gBAAgB,IAAI,KAAK;EAC1DV,OAAO,CAACW,yBAAyB,GAAGL,KAAK,CAACK,yBAAyB,IAAI,KAAK;EAC5EX,OAAO,CAACY,UAAU,GAAGN,KAAK,CAACM,UAAU,IAAI,MAAM;EAC/CZ,OAAO,CAACa,wBAAwB,GAAGP,KAAK,CAACO,wBAAwB;EACjEb,OAAO,CAACc,kBAAkB,GAAGR,KAAK,CAACQ,kBAAkB;EACrDd,OAAO,CAACe,mBAAmB,GAAGT,KAAK,CAACS,mBAAmB;EACvDf,OAAO,CAACgB,kBAAkB,GAAGV,KAAK,CAACU,kBAAkB;EACrDhB,OAAO,CAACiB,yBAAyB,GAAGX,KAAK,CAACW,yBAAyB;EACnEjB,OAAO,CAACkB,wBAAwB,GAAGZ,KAAK,CAACY,wBAAwB;EACjElB,OAAO,CAACmB,eAAe,GAAGb,KAAK,CAACa,eAAe,IAAI,IAAI;EACvDnB,OAAO,CAACoB,WAAW,GAAGd,KAAK,CAACc,WAAW,IAAI,SAAS;AACtD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,SAAS,gBAAGpD,KAAK,CAACqD,UAAU,CAChC,CACE;EACEf,MAAM;EACNE,QAAQ,GAAG,KAAK;EAChBC,gBAAgB,GAAG,KAAK;EACxBC,yBAAyB,GAAG,KAAK;EACjCC,UAAU,GAAG,MAAM;EACnB,GAAGN;AACL,CAAC,EACDiB,GAAG,KACA;EACH,MAAMC,OAAO,GAAGvD,KAAK,CAACwD,OAAO,CAAC,MAAM9B,cAAc,EAAE,EAAE,EAAE,CAAC;EACzD,MAAM+B,gBAAgB,GAAGzD,KAAK,CAAC0D,MAAM,CAA8B,IAAI,CAAC;EAExE,MAAMC,gBAAgB,GAAG3D,KAAK,CAAC4D,WAAW,CACvCC,EAAU,IAAK;IACd,IAAI;MACF,IAAIJ,gBAAgB,CAACK,OAAO,KAAK,IAAI,EAAE;QACrCL,gBAAgB,CAACK,OAAO,GACtBnC,2BAA2B,CAACoC,iBAAiB,CAACF,EAAE,CAAC;;QAEnD;QACA,IAAI,CAACJ,gBAAgB,CAACK,OAAO,EAAE;UAC7B,MAAM,IAAI7B,sBAAU,CAClB,gBAAgB,EAChB,+BACF,CAAC;QACH;MACF;;MAEA;MACAG,WAAW,CAACqB,gBAAgB,CAACK,OAAO,EAAE;QACpC,GAAGzB,KAAK;QACRC,MAAM,EAAEA,MAAM;QACdE,QAAQ,EAAEA,QAAQ;QAClBC,gBAAgB,EAAEA,gBAAgB;QAClCC,yBAAyB,EAAEA,yBAAyB;QACpDC,UAAU,EAAEA;MACd,CAAC,CAAC;IACJ,CAAC,CAAC,OAAOT,KAAK,EAAE;MACd,MAAM,IAAAC,oCAAwB,EAACD,KAAK,CAAC;IACvC;EACF,CAAC,EACD,CACEG,KAAK,EACLC,MAAM,EACNE,QAAQ,EACRC,gBAAgB,EAChBC,yBAAyB,EACzBC,UAAU,CAEd,CAAC;EAED,MAAMqB,eAAe,GAAGhE,KAAK,CAAC4D,WAAW,CACtCK,KAA2C,IAAK;IAC/CN,gBAAgB,CAACM,KAAK,CAACC,WAAW,CAACX,OAAO,CAAC;EAC7C,CAAC,EACD,CAACI,gBAAgB,CACnB,CAAC;EAED3D,KAAK,CAACmE,mBAAmB,CACvBb,GAAG,EACH,OAAO;IACLc,eAAe,EAAEA,CAAA,KAAM;MACrBtC,6BAA6B,CAAC2B,gBAAgB,CAACK,OAAO,EAAG/B,OAAO,IAAK;QACnEA,OAAO,CAACqC,eAAe,CAAC,CAAC;MAC3B,CAAC,CAAC;IACJ,CAAC;IACDC,cAAc,EAAEA,CAAA,KAAM;MACpBvC,6BAA6B,CAAC2B,gBAAgB,CAACK,OAAO,EAAG/B,OAAO,IAAK;QACnEA,OAAO,CAACsC,cAAc,CAAC,CAAC;MAC1B,CAAC,CAAC;IACJ,CAAC;IACDC,qBAAqB,EAAEA,CAAA,KAAM;MAC3BxC,6BAA6B,CAAC2B,gBAAgB,CAACK,OAAO,EAAG/B,OAAO,IAAK;QACnEA,OAAO,CAACuC,qBAAqB,CAAC,CAAC;MACjC,CAAC,CAAC;IACJ,CAAC;IACDC,oBAAoB,EAAEA,CAAA,KAAM;MAC1BzC,6BAA6B,CAAC2B,gBAAgB,CAACK,OAAO,EAAG/B,OAAO,IAAK;QACnEA,OAAO,CAACwC,oBAAoB,CAAC,CAAC;MAChC,CAAC,CAAC;IACJ,CAAC;IACDC,wBAAwB,EAAEA,CAAA,KAAM;MAC9B,OAAO1C,6BAA6B,CAClC2B,gBAAgB,CAACK,OAAO,EACvB/B,OAAO,IAAK;QACX,OAAOA,OAAO,CAACyC,wBAAwB,CAAC,CAAC;MAC3C,CACF,CAAC;IACH;EACF,CAAC,CAAC,EACF,EACF,CAAC;EAEDxE,KAAK,CAACyE,SAAS,CAAC,MAAM;IACpB,IAAI,CAAChB,gBAAgB,CAACK,OAAO,EAAE;MAC7B;IACF;;IAEA;IACA1B,WAAW,CAACqB,gBAAgB,CAACK,OAAO,EAAE;MACpC,GAAGzB,KAAK;MACRC,MAAM,EAAEA,MAAM;MACdE,QAAQ,EAAEA,QAAQ;MAClBC,gBAAgB,EAAEA,gBAAgB;MAClCC,yBAAyB,EAAEA,yBAAyB;MACpDC,UAAU,EAAEA;IACd,CAAC,CAAC;EACJ,CAAC,EAAE,CACDL,MAAM,EACNE,QAAQ,EACRC,gBAAgB,EAChBC,yBAAyB,EACzBC,UAAU,EACVN,KAAK,CACN,CAAC;EAEF,oBACE,IAAA/B,WAAA,CAAAoE,GAAA,EAACrE,gBAAA,CAAAsE,eAAe;IACdpB,OAAO,EAAEA,OAAQ;IACjBS,eAAe,EAAEA,eAAgB;IAAA,GAC7B3B;EAAK,CACV,CAAC;AAEN,CACF,CAAC;AAEDe,SAAS,CAACwB,WAAW,GAAG,WAAW;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAA7D,OAAA,gBAErBjB,KAAK,CAAC+E,IAAI,CAAC3B,SAAS,CAAC","ignoreList":[]} diff --git a/lib/commonjs/core/video-view/VideoView.web.js b/lib/commonjs/core/video-view/VideoView.web.js new file mode 100644 index 00000000..c0fe9fb6 --- /dev/null +++ b/lib/commonjs/core/video-view/VideoView.web.js @@ -0,0 +1,72 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _react = require("react"); +var _reactNative = require("react-native"); +var _jsxRuntime = require("react/jsx-runtime"); +/** + * VideoView is a component that allows you to display a video from a {@link VideoPlayer}. + * + * @param player - The player to play the video - {@link VideoPlayer} + * @param controls - Whether to show the controls. Defaults to false. + * @param style - The style of the video view - {@link ViewStyle} + * @param pictureInPicture - Whether to show the picture in picture button. Defaults to false. + * @param autoEnterPictureInPicture - Whether to automatically enter picture in picture mode + * when the video is playing. Defaults to false. + * @param resizeMode - How the video should be resized to fit the view. Defaults to 'none'. + */ +const VideoView = /*#__PURE__*/(0, _react.forwardRef)(({ + player: nPlayer, + controls = false, + resizeMode = "none", + // auto pip is unsupported + pictureInPicture = false, + autoEnterPictureInPicture = false, + keepScreenAwake = true, + ...props +}, ref) => { + const player = nPlayer; + const vRef = (0, _react.useRef)(null); + (0, _react.useEffect)(() => { + const videoElement = player.__getNativeRef(); + vRef.current?.appendChild(videoElement); + return () => { + vRef.current?.removeChild(videoElement); + }; + }, [player]); + (0, _react.useImperativeHandle)(ref, () => ({ + enterFullscreen: () => { + player.__getNativeRef().requestFullscreen({ + navigationUI: "hide" + }); + }, + exitFullscreen: () => { + document.exitFullscreen(); + }, + enterPictureInPicture: () => { + player.__getNativeRef().requestPictureInPicture(); + }, + exitPictureInPicture: () => { + document.exitPictureInPicture(); + }, + canEnterPictureInPicture: () => document.pictureInPictureEnabled + }), [player]); + (0, _react.useEffect)(() => { + player.__getNativeRef().controls = controls; + }, [player, controls]); + return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { + ...props, + children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { + ref: vRef, + style: { + objectFit: resizeMode === "stretch" ? "fill" : resizeMode + } + }) + }); +}); +VideoView.displayName = "VideoView"; +var _default = exports.default = /*#__PURE__*/(0, _react.memo)(VideoView); +//# sourceMappingURL=VideoView.web.js.map \ No newline at end of file diff --git a/lib/commonjs/core/video-view/VideoView.web.js.map b/lib/commonjs/core/video-view/VideoView.web.js.map new file mode 100644 index 00000000..c0216284 --- /dev/null +++ b/lib/commonjs/core/video-view/VideoView.web.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_react","require","_reactNative","_jsxRuntime","VideoView","forwardRef","player","nPlayer","controls","resizeMode","pictureInPicture","autoEnterPictureInPicture","keepScreenAwake","props","ref","vRef","useRef","useEffect","videoElement","__getNativeRef","current","appendChild","removeChild","useImperativeHandle","enterFullscreen","requestFullscreen","navigationUI","exitFullscreen","document","enterPictureInPicture","requestPictureInPicture","exitPictureInPicture","canEnterPictureInPicture","pictureInPictureEnabled","jsx","View","children","style","objectFit","displayName","_default","exports","default","memo"],"sourceRoot":"../../../../src","sources":["core/video-view/VideoView.web.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAOA,IAAAC,YAAA,GAAAD,OAAA;AAAoD,IAAAE,WAAA,GAAAF,OAAA;AAIpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMG,SAAS,gBAAG,IAAAC,iBAAU,EAC1B,CACE;EACEC,MAAM,EAAEC,OAAO;EACfC,QAAQ,GAAG,KAAK;EAChBC,UAAU,GAAG,MAAM;EACnB;EACAC,gBAAgB,GAAG,KAAK;EACxBC,yBAAyB,GAAG,KAAK;EACjCC,eAAe,GAAG,IAAI;EACtB,GAAGC;AACL,CAAC,EACDC,GAAG,KACA;EACH,MAAMR,MAAM,GAAGC,OAAiC;EAChD,MAAMQ,IAAI,GAAG,IAAAC,aAAM,EAAiB,IAAI,CAAC;EACzC,IAAAC,gBAAS,EAAC,MAAM;IACd,MAAMC,YAAY,GAAGZ,MAAM,CAACa,cAAc,CAAC,CAAC;IAC5CJ,IAAI,CAACK,OAAO,EAAEC,WAAW,CAACH,YAAY,CAAC;IACvC,OAAO,MAAM;MACXH,IAAI,CAACK,OAAO,EAAEE,WAAW,CAACJ,YAAY,CAAC;IACzC,CAAC;EACH,CAAC,EAAE,CAACZ,MAAM,CAAC,CAAC;EAEZ,IAAAiB,0BAAmB,EACjBT,GAAG,EACH,OAAO;IACLU,eAAe,EAAEA,CAAA,KAAM;MACrBlB,MAAM,CAACa,cAAc,CAAC,CAAC,CAACM,iBAAiB,CAAC;QAAEC,YAAY,EAAE;MAAO,CAAC,CAAC;IACrE,CAAC;IACDC,cAAc,EAAEA,CAAA,KAAM;MACpBC,QAAQ,CAACD,cAAc,CAAC,CAAC;IAC3B,CAAC;IACDE,qBAAqB,EAAEA,CAAA,KAAM;MAC3BvB,MAAM,CAACa,cAAc,CAAC,CAAC,CAACW,uBAAuB,CAAC,CAAC;IACnD,CAAC;IACDC,oBAAoB,EAAEA,CAAA,KAAM;MAC1BH,QAAQ,CAACG,oBAAoB,CAAC,CAAC;IACjC,CAAC;IACDC,wBAAwB,EAAEA,CAAA,KAAMJ,QAAQ,CAACK;EAC3C,CAAC,CAAC,EACF,CAAC3B,MAAM,CACT,CAAC;EAED,IAAAW,gBAAS,EAAC,MAAM;IACdX,MAAM,CAACa,cAAc,CAAC,CAAC,CAACX,QAAQ,GAAGA,QAAQ;EAC7C,CAAC,EAAE,CAACF,MAAM,EAAEE,QAAQ,CAAC,CAAC;EAEtB,oBACE,IAAAL,WAAA,CAAA+B,GAAA,EAAChC,YAAA,CAAAiC,IAAI;IAAA,GAAKtB,KAAK;IAAAuB,QAAA,eACb,IAAAjC,WAAA,CAAA+B,GAAA;MACEpB,GAAG,EAAEC,IAAK;MACVsB,KAAK,EAAE;QAAEC,SAAS,EAAE7B,UAAU,KAAK,SAAS,GAAG,MAAM,GAAGA;MAAW;IAAE,CACtE;EAAC,CACE,CAAC;AAEX,CACF,CAAC;AAEDL,SAAS,CAACmC,WAAW,GAAG,WAAW;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,gBAErB,IAAAC,WAAI,EAACvC,SAAS,CAAC","ignoreList":[]} diff --git a/lib/commonjs/core/video-view/ViewViewProps.js b/lib/commonjs/core/video-view/ViewViewProps.js new file mode 100644 index 00000000..7f11b32a --- /dev/null +++ b/lib/commonjs/core/video-view/ViewViewProps.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=ViewViewProps.js.map \ No newline at end of file diff --git a/lib/commonjs/core/video-view/ViewViewProps.js.map b/lib/commonjs/core/video-view/ViewViewProps.js.map new file mode 100644 index 00000000..77749fcc --- /dev/null +++ b/lib/commonjs/core/video-view/ViewViewProps.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/video-view/ViewViewProps.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/@types.js b/lib/commonjs/expo-plugins/@types.js new file mode 100644 index 00000000..389ea6fe --- /dev/null +++ b/lib/commonjs/expo-plugins/@types.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=@types.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/@types.js.map b/lib/commonjs/expo-plugins/@types.js.map new file mode 100644 index 00000000..7c3cec95 --- /dev/null +++ b/lib/commonjs/expo-plugins/@types.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../src","sources":["expo-plugins/@types.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/getPackageInfo.js b/lib/commonjs/expo-plugins/getPackageInfo.js new file mode 100644 index 00000000..052b0ede --- /dev/null +++ b/lib/commonjs/expo-plugins/getPackageInfo.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getPackageInfo = getPackageInfo; +function getPackageInfo() { + // src/expo-plugins/getPackageInfo.ts + try { + const packageJson = require('../../package.json'); + return { + name: packageJson.name, + version: packageJson.version + }; + } catch (_) {} + + // lib/commonjs/expo-plugins/getPackageInfo.js + try { + const packageJson = require('../../../package.json'); + return { + name: packageJson.name, + version: packageJson.version + }; + } catch (_) {} + throw new Error('Failed to get (react-native-video) package info'); +} +//# sourceMappingURL=getPackageInfo.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/getPackageInfo.js.map b/lib/commonjs/expo-plugins/getPackageInfo.js.map new file mode 100644 index 00000000..077f50e7 --- /dev/null +++ b/lib/commonjs/expo-plugins/getPackageInfo.js.map @@ -0,0 +1 @@ +{"version":3,"names":["getPackageInfo","packageJson","require","name","version","_","Error"],"sourceRoot":"../../../src","sources":["expo-plugins/getPackageInfo.ts"],"mappings":";;;;;;AAAO,SAASA,cAAcA,CAAA,EAAsC;EAClE;EACA,IAAI;IACF,MAAMC,WAAW,GAAGC,OAAO,CAAC,oBAAoB,CAAC;IAEjD,OAAO;MACLC,IAAI,EAAEF,WAAW,CAACE,IAAI;MACtBC,OAAO,EAAEH,WAAW,CAACG;IACvB,CAAC;EACH,CAAC,CAAC,OAAOC,CAAC,EAAE,CAAC;;EAEb;EACA,IAAI;IACF,MAAMJ,WAAW,GAAGC,OAAO,CAAC,uBAAuB,CAAC;IAEpD,OAAO;MACLC,IAAI,EAAEF,WAAW,CAACE,IAAI;MACtBC,OAAO,EAAEH,WAAW,CAACG;IACvB,CAAC;EACH,CAAC,CAAC,OAAOC,CAAC,EAAE,CAAC;EAEb,MAAM,IAAIC,KAAK,CAAC,iDAAiD,CAAC;AACpE","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/withAndroidExtensions.js b/lib/commonjs/expo-plugins/withAndroidExtensions.js new file mode 100644 index 00000000..ce38e1b9 --- /dev/null +++ b/lib/commonjs/expo-plugins/withAndroidExtensions.js @@ -0,0 +1,40 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.withAndroidExtensions = void 0; +var _configPlugins = require("@expo/config-plugins"); +/** + * Sets the Android extensions for ExoPlayer in `gradle.properties`. + * You can choose which extensions to include in order to reduce the size of the app. + */ +const withAndroidExtensions = (c, androidExtensions) => { + const keys = ['RNVideo_useExoplayerDash', 'RNVideo_useExoplayerHls']; + if (!androidExtensions) { + androidExtensions = { + useExoplayerDash: true, + useExoplayerHls: true + }; + } + return (0, _configPlugins.withGradleProperties)(c, config => { + config.modResults = config.modResults.filter(item => { + if (item.type === 'property' && keys.includes(item.key)) { + return false; + } + return true; + }); + for (const key of keys) { + const valueKey = key.replace('RNVideo_', ''); + const value = androidExtensions ? androidExtensions[valueKey] ?? false : false; + config.modResults.push({ + type: 'property', + key, + value: value.toString() + }); + } + return config; + }); +}; +exports.withAndroidExtensions = withAndroidExtensions; +//# sourceMappingURL=withAndroidExtensions.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/withAndroidExtensions.js.map b/lib/commonjs/expo-plugins/withAndroidExtensions.js.map new file mode 100644 index 00000000..ba6fe760 --- /dev/null +++ b/lib/commonjs/expo-plugins/withAndroidExtensions.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_configPlugins","require","withAndroidExtensions","c","androidExtensions","keys","useExoplayerDash","useExoplayerHls","withGradleProperties","config","modResults","filter","item","type","includes","key","valueKey","replace","value","push","toString","exports"],"sourceRoot":"../../../src","sources":["expo-plugins/withAndroidExtensions.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAGA;AACA;AACA;AACA;AACO,MAAMC,qBAEZ,GAAGA,CAACC,CAAC,EAAEC,iBAAiB,KAAK;EAC5B,MAAMC,IAAI,GAAG,CAAC,0BAA0B,EAAE,yBAAyB,CAAC;EAEpE,IAAI,CAACD,iBAAiB,EAAE;IACtBA,iBAAiB,GAAG;MAClBE,gBAAgB,EAAE,IAAI;MACtBC,eAAe,EAAE;IACnB,CAAC;EACH;EAEA,OAAO,IAAAC,mCAAoB,EAACL,CAAC,EAAGM,MAAM,IAAK;IACzCA,MAAM,CAACC,UAAU,GAAGD,MAAM,CAACC,UAAU,CAACC,MAAM,CAAEC,IAAI,IAAK;MACrD,IAAIA,IAAI,CAACC,IAAI,KAAK,UAAU,IAAIR,IAAI,CAACS,QAAQ,CAACF,IAAI,CAACG,GAAG,CAAC,EAAE;QACvD,OAAO,KAAK;MACd;MACA,OAAO,IAAI;IACb,CAAC,CAAC;IAEF,KAAK,MAAMA,GAAG,IAAIV,IAAI,EAAE;MACtB,MAAMW,QAAQ,GAAGD,GAAG,CAACE,OAAO,CAC1B,UAAU,EACV,EACF,CAAmC;MACnC,MAAMC,KAAK,GAAGd,iBAAiB,GAC1BA,iBAAiB,CAACY,QAAQ,CAAC,IAAI,KAAK,GACrC,KAAK;MAETP,MAAM,CAACC,UAAU,CAACS,IAAI,CAAC;QACrBN,IAAI,EAAE,UAAU;QAChBE,GAAG;QACHG,KAAK,EAAEA,KAAK,CAACE,QAAQ,CAAC;MACxB,CAAC,CAAC;IACJ;IAEA,OAAOX,MAAM;EACf,CAAC,CAAC;AACJ,CAAC;AAACY,OAAA,CAAAnB,qBAAA,GAAAA,qBAAA","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js b/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js new file mode 100644 index 00000000..ba9a2e26 --- /dev/null +++ b/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.withAndroidPictureInPicture = void 0; +var _configPlugins = require("@expo/config-plugins"); +const withAndroidPictureInPicture = (config, enableAndroidPictureInPicture) => { + return (0, _configPlugins.withAndroidManifest)(config, _config => { + if (!enableAndroidPictureInPicture) { + return _config; + } + const mainActivity = _configPlugins.AndroidConfig.Manifest.getMainActivity(_config.modResults); + if (!mainActivity) { + console.warn('AndroidManifest.xml is missing an element - skipping adding Picture-In-Picture related config.'); + return _config; + } + mainActivity.$['android:supportsPictureInPicture'] = 'true'; + return _config; + }); +}; +exports.withAndroidPictureInPicture = withAndroidPictureInPicture; +//# sourceMappingURL=withAndroidPictureInPicture.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js.map b/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js.map new file mode 100644 index 00000000..f8af4179 --- /dev/null +++ b/lib/commonjs/expo-plugins/withAndroidPictureInPicture.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_configPlugins","require","withAndroidPictureInPicture","config","enableAndroidPictureInPicture","withAndroidManifest","_config","mainActivity","AndroidConfig","Manifest","getMainActivity","modResults","console","warn","$","exports"],"sourceRoot":"../../../src","sources":["expo-plugins/withAndroidPictureInPicture.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAMO,MAAMC,2BAAkD,GAAGA,CAChEC,MAAM,EACNC,6BAA6B,KAC1B;EACH,OAAO,IAAAC,kCAAmB,EAACF,MAAM,EAAGG,OAAO,IAAK;IAC9C,IAAI,CAACF,6BAA6B,EAAE;MAClC,OAAOE,OAAO;IAChB;IAEA,MAAMC,YAAY,GAAGC,4BAAa,CAACC,QAAQ,CAACC,eAAe,CACzDJ,OAAO,CAACK,UACV,CAAC;IAED,IAAI,CAACJ,YAAY,EAAE;MACjBK,OAAO,CAACC,IAAI,CACV,0IACF,CAAC;MACD,OAAOP,OAAO;IAChB;IAEAC,YAAY,CAACO,CAAC,CAAC,kCAAkC,CAAC,GAAG,MAAM;IAE3D,OAAOR,OAAO;EAChB,CAAC,CAAC;AACJ,CAAC;AAACS,OAAA,CAAAb,2BAAA,GAAAA,2BAAA","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/withBackgroundAudio.js b/lib/commonjs/expo-plugins/withBackgroundAudio.js new file mode 100644 index 00000000..a6db4d49 --- /dev/null +++ b/lib/commonjs/expo-plugins/withBackgroundAudio.js @@ -0,0 +1,26 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.withBackgroundAudio = void 0; +var _configPlugins = require("@expo/config-plugins"); +/** + * Sets `UIBackgroundModes` in `Info.plist` to enable background audio on Apple platforms. + * This is required for audio to continue playing when the app is in the background. + */ +const withBackgroundAudio = (c, enableBackgroundAudio) => { + return (0, _configPlugins.withInfoPlist)(c, config => { + const modes = config.modResults.UIBackgroundModes || []; + if (enableBackgroundAudio) { + if (!modes.includes('audio')) { + config.modResults.UIBackgroundModes = [...modes, 'audio']; + } + } else { + config.modResults.UIBackgroundModes = modes.filter(mode => mode !== 'audio'); + } + return config; + }); +}; +exports.withBackgroundAudio = withBackgroundAudio; +//# sourceMappingURL=withBackgroundAudio.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/withBackgroundAudio.js.map b/lib/commonjs/expo-plugins/withBackgroundAudio.js.map new file mode 100644 index 00000000..e0d86b08 --- /dev/null +++ b/lib/commonjs/expo-plugins/withBackgroundAudio.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_configPlugins","require","withBackgroundAudio","c","enableBackgroundAudio","withInfoPlist","config","modes","modResults","UIBackgroundModes","includes","filter","mode","exports"],"sourceRoot":"../../../src","sources":["expo-plugins/withBackgroundAudio.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACO,MAAMC,mBAA0C,GAAGA,CACxDC,CAAC,EACDC,qBAAqB,KAClB;EACH,OAAO,IAAAC,4BAAa,EAACF,CAAC,EAAGG,MAAM,IAAK;IAClC,MAAMC,KAAK,GAAGD,MAAM,CAACE,UAAU,CAACC,iBAAiB,IAAI,EAAE;IAEvD,IAAIL,qBAAqB,EAAE;MACzB,IAAI,CAACG,KAAK,CAACG,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC5BJ,MAAM,CAACE,UAAU,CAACC,iBAAiB,GAAG,CAAC,GAAGF,KAAK,EAAE,OAAO,CAAC;MAC3D;IACF,CAAC,MAAM;MACLD,MAAM,CAACE,UAAU,CAACC,iBAAiB,GAAGF,KAAK,CAACI,MAAM,CAC/CC,IAAY,IAAKA,IAAI,KAAK,OAC7B,CAAC;IACH;IAEA,OAAON,MAAM;EACf,CAAC,CAAC;AACJ,CAAC;AAACO,OAAA,CAAAX,mBAAA,GAAAA,mBAAA","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/withReactNativeVideo.js b/lib/commonjs/expo-plugins/withReactNativeVideo.js new file mode 100644 index 00000000..0cb1adc9 --- /dev/null +++ b/lib/commonjs/expo-plugins/withReactNativeVideo.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _configPlugins = require("@expo/config-plugins"); +var _getPackageInfo = require("./getPackageInfo.js"); +var _withAndroidExtensions = require("./withAndroidExtensions.js"); +var _withAndroidPictureInPicture = require("./withAndroidPictureInPicture.js"); +var _withBackgroundAudio = require("./withBackgroundAudio.js"); +const withRNVideo = (config, props = {}) => { + if (props.enableAndroidPictureInPicture) { + config = (0, _withAndroidPictureInPicture.withAndroidPictureInPicture)(config, props.enableAndroidPictureInPicture); + } + if (props.androidExtensions != null) { + config = (0, _withAndroidExtensions.withAndroidExtensions)(config, props.androidExtensions); + } + if (props.enableBackgroundAudio) { + config = (0, _withBackgroundAudio.withBackgroundAudio)(config, props.enableBackgroundAudio); + } + return config; +}; +const { + name, + version +} = (0, _getPackageInfo.getPackageInfo)(); +var _default = exports.default = (0, _configPlugins.createRunOncePlugin)(withRNVideo, name, version); +//# sourceMappingURL=withReactNativeVideo.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/withReactNativeVideo.js.map b/lib/commonjs/expo-plugins/withReactNativeVideo.js.map new file mode 100644 index 00000000..5a53870a --- /dev/null +++ b/lib/commonjs/expo-plugins/withReactNativeVideo.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_configPlugins","require","_getPackageInfo","_withAndroidExtensions","_withAndroidPictureInPicture","_withBackgroundAudio","withRNVideo","config","props","enableAndroidPictureInPicture","withAndroidPictureInPicture","androidExtensions","withAndroidExtensions","enableBackgroundAudio","withBackgroundAudio","name","version","getPackageInfo","_default","exports","default","createRunOncePlugin"],"sourceRoot":"../../../src","sources":["expo-plugins/withReactNativeVideo.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAEA,IAAAC,eAAA,GAAAD,OAAA;AACA,IAAAE,sBAAA,GAAAF,OAAA;AACA,IAAAG,4BAAA,GAAAH,OAAA;AACA,IAAAI,oBAAA,GAAAJ,OAAA;AAEA,MAAMK,WAAsC,GAAGA,CAACC,MAAM,EAAEC,KAAK,GAAG,CAAC,CAAC,KAAK;EACrE,IAAIA,KAAK,CAACC,6BAA6B,EAAE;IACvCF,MAAM,GAAG,IAAAG,wDAA2B,EAClCH,MAAM,EACNC,KAAK,CAACC,6BACR,CAAC;EACH;EAEA,IAAID,KAAK,CAACG,iBAAiB,IAAI,IAAI,EAAE;IACnCJ,MAAM,GAAG,IAAAK,4CAAqB,EAACL,MAAM,EAAEC,KAAK,CAACG,iBAAiB,CAAC;EACjE;EAEA,IAAIH,KAAK,CAACK,qBAAqB,EAAE;IAC/BN,MAAM,GAAG,IAAAO,wCAAmB,EAACP,MAAM,EAAEC,KAAK,CAACK,qBAAqB,CAAC;EACnE;EAEA,OAAON,MAAM;AACf,CAAC;AAED,MAAM;EAAEQ,IAAI;EAAEC;AAAQ,CAAC,GAAG,IAAAC,8BAAc,EAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAE5B,IAAAC,kCAAmB,EAACf,WAAW,EAAES,IAAI,EAAEC,OAAO,CAAC","ignoreList":[]} diff --git a/lib/commonjs/expo-plugins/writeToPodfile.js b/lib/commonjs/expo-plugins/writeToPodfile.js new file mode 100644 index 00000000..c25fb765 --- /dev/null +++ b/lib/commonjs/expo-plugins/writeToPodfile.js @@ -0,0 +1,59 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.writeToPodfile = void 0; +var _generateCode = require("@expo/config-plugins/build/utils/generateCode"); +var _fs = _interopRequireDefault(require("fs")); +var _path = _interopRequireDefault(require("path")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +const writeToPodfile = (projectRoot, key, value, testApp = false) => { + const podfilePath = _path.default.join(projectRoot, 'ios', 'Podfile'); + const podfileContent = _fs.default.readFileSync(podfilePath, 'utf8'); + if (podfileContent.includes(`$${key} =`)) { + console.warn(`RNV - Podfile already contains a definition for "$${key}". Skipping...`); + return; + } + if (testApp) { + mergeTestAppPodfile(podfileContent, podfilePath, key, value); + } else { + mergeExpoPodfile(podfileContent, podfilePath, key, value); + } +}; +exports.writeToPodfile = writeToPodfile; +const mergeTestAppPodfile = (podfileContent, podfilePath, key, value) => { + // We will try to inject the variable definition above the `use_test_app!` call in the Podfile. + const newPodfileContent = (0, _generateCode.mergeContents)({ + tag: `rn-video-set-${key.toLowerCase()}`, + src: podfileContent, + newSrc: `$${key} = ${value}`, + anchor: /use_test_app!/, + offset: -1, + // Insert the key-value pair just above the `use_test_app!` call. + comment: '#' + }); + + // Write to Podfile only if the merge was successful + if (newPodfileContent.didMerge) { + _fs.default.writeFileSync(podfilePath, newPodfileContent.contents); + } else { + console.warn(`RNV - Failed to write "$${key} = ${value}" to Test App Podfile`); + } +}; +const mergeExpoPodfile = (podfileContent, podfilePath, key, value) => { + const newPodfileContent = (0, _generateCode.mergeContents)({ + tag: `rn-video-set-${key.toLowerCase()}`, + src: podfileContent, + newSrc: `$${key} = ${value}`, + anchor: /platform :ios/, + offset: 0, + comment: '#' + }); + if (newPodfileContent.didMerge) { + _fs.default.writeFileSync(podfilePath, newPodfileContent.contents); + } else { + console.warn(`RNV - Failed to write "$${key} = ${value}" to Podfile`); + } +}; +//# sourceMappingURL=writeToPodfile.js.map \ No newline at end of file diff --git a/lib/commonjs/expo-plugins/writeToPodfile.js.map b/lib/commonjs/expo-plugins/writeToPodfile.js.map new file mode 100644 index 00000000..11f15b00 --- /dev/null +++ b/lib/commonjs/expo-plugins/writeToPodfile.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_generateCode","require","_fs","_interopRequireDefault","_path","e","__esModule","default","writeToPodfile","projectRoot","key","value","testApp","podfilePath","path","join","podfileContent","fs","readFileSync","includes","console","warn","mergeTestAppPodfile","mergeExpoPodfile","exports","newPodfileContent","mergeContents","tag","toLowerCase","src","newSrc","anchor","offset","comment","didMerge","writeFileSync","contents"],"sourceRoot":"../../../src","sources":["expo-plugins/writeToPodfile.ts"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,GAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,KAAA,GAAAD,sBAAA,CAAAF,OAAA;AAAwB,SAAAE,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEjB,MAAMG,cAAc,GAAGA,CAC5BC,WAAmB,EACnBC,GAAW,EACXC,KAAa,EACbC,OAAgB,GAAG,KAAK,KACrB;EACH,MAAMC,WAAW,GAAGC,aAAI,CAACC,IAAI,CAACN,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC;EAC5D,MAAMO,cAAc,GAAGC,WAAE,CAACC,YAAY,CAACL,WAAW,EAAE,MAAM,CAAC;EAE3D,IAAIG,cAAc,CAACG,QAAQ,CAAC,IAAIT,GAAG,IAAI,CAAC,EAAE;IACxCU,OAAO,CAACC,IAAI,CACV,qDAAqDX,GAAG,gBAC1D,CAAC;IACD;EACF;EAEA,IAAIE,OAAO,EAAE;IACXU,mBAAmB,CAACN,cAAc,EAAEH,WAAW,EAAEH,GAAG,EAAEC,KAAK,CAAC;EAC9D,CAAC,MAAM;IACLY,gBAAgB,CAACP,cAAc,EAAEH,WAAW,EAAEH,GAAG,EAAEC,KAAK,CAAC;EAC3D;AACF,CAAC;AAACa,OAAA,CAAAhB,cAAA,GAAAA,cAAA;AAEF,MAAMc,mBAAmB,GAAGA,CAC1BN,cAAsB,EACtBH,WAAmB,EACnBH,GAAW,EACXC,KAAa,KACV;EACH;EACA,MAAMc,iBAAiB,GAAG,IAAAC,2BAAa,EAAC;IACtCC,GAAG,EAAE,gBAAgBjB,GAAG,CAACkB,WAAW,CAAC,CAAC,EAAE;IACxCC,GAAG,EAAEb,cAAc;IACnBc,MAAM,EAAE,IAAIpB,GAAG,MAAMC,KAAK,EAAE;IAC5BoB,MAAM,EAAE,eAAe;IACvBC,MAAM,EAAE,CAAC,CAAC;IAAE;IACZC,OAAO,EAAE;EACX,CAAC,CAAC;;EAEF;EACA,IAAIR,iBAAiB,CAACS,QAAQ,EAAE;IAC9BjB,WAAE,CAACkB,aAAa,CAACtB,WAAW,EAAEY,iBAAiB,CAACW,QAAQ,CAAC;EAC3D,CAAC,MAAM;IACLhB,OAAO,CAACC,IAAI,CACV,2BAA2BX,GAAG,MAAMC,KAAK,uBAC3C,CAAC;EACH;AACF,CAAC;AAED,MAAMY,gBAAgB,GAAGA,CACvBP,cAAsB,EACtBH,WAAmB,EACnBH,GAAW,EACXC,KAAa,KACV;EACH,MAAMc,iBAAiB,GAAG,IAAAC,2BAAa,EAAC;IACtCC,GAAG,EAAE,gBAAgBjB,GAAG,CAACkB,WAAW,CAAC,CAAC,EAAE;IACxCC,GAAG,EAAEb,cAAc;IACnBc,MAAM,EAAE,IAAIpB,GAAG,MAAMC,KAAK,EAAE;IAC5BoB,MAAM,EAAE,eAAe;IACvBC,MAAM,EAAE,CAAC;IACTC,OAAO,EAAE;EACX,CAAC,CAAC;EAEF,IAAIR,iBAAiB,CAACS,QAAQ,EAAE;IAC9BjB,WAAE,CAACkB,aAAa,CAACtB,WAAW,EAAEY,iBAAiB,CAACW,QAAQ,CAAC;EAC3D,CAAC,MAAM;IACLhB,OAAO,CAACC,IAAI,CAAC,2BAA2BX,GAAG,MAAMC,KAAK,cAAc,CAAC;EACvE;AACF,CAAC","ignoreList":[]} diff --git a/lib/commonjs/index.js b/lib/commonjs/index.js new file mode 100644 index 00000000..ce426034 --- /dev/null +++ b/lib/commonjs/index.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "VideoPlayer", { + enumerable: true, + get: function () { + return _VideoPlayer.VideoPlayer; + } +}); +Object.defineProperty(exports, "VideoView", { + enumerable: true, + get: function () { + return _VideoView.default; + } +}); +Object.defineProperty(exports, "useEvent", { + enumerable: true, + get: function () { + return _useEvent.useEvent; + } +}); +Object.defineProperty(exports, "useVideoPlayer", { + enumerable: true, + get: function () { + return _useVideoPlayer.useVideoPlayer; + } +}); +var _useEvent = require("./core/hooks/useEvent.js"); +var _useVideoPlayer = require("./core/hooks/useVideoPlayer.js"); +var _VideoPlayer = require("./core/VideoPlayer"); +var _VideoView = _interopRequireDefault(require("./core/video-view/VideoView")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/commonjs/index.js.map b/lib/commonjs/index.js.map new file mode 100644 index 00000000..a8a4d875 --- /dev/null +++ b/lib/commonjs/index.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_useEvent","require","_useVideoPlayer","_VideoPlayer","_VideoView","_interopRequireDefault","e","__esModule","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,SAAA,GAAAC,OAAA;AACA,IAAAC,eAAA,GAAAD,OAAA;AAoBA,IAAAE,YAAA,GAAAF,OAAA;AACA,IAAAG,UAAA,GAAAC,sBAAA,CAAAJ,OAAA;AAAmE,SAAAI,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]} diff --git a/lib/commonjs/package.json b/lib/commonjs/package.json new file mode 100644 index 00000000..729ac4d9 --- /dev/null +++ b/lib/commonjs/package.json @@ -0,0 +1 @@ +{"type":"commonjs"} diff --git a/lib/commonjs/spec/fabric/VideoViewNativeComponent.ts b/lib/commonjs/spec/fabric/VideoViewNativeComponent.ts new file mode 100644 index 00000000..41a83d37 --- /dev/null +++ b/lib/commonjs/spec/fabric/VideoViewNativeComponent.ts @@ -0,0 +1,17 @@ +import type { ViewProps } from 'react-native'; +import type { + DirectEventHandler, + Int32, +} from 'react-native/Libraries/Types/CodegenTypes'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +type OnNitroIdChangeEvent = Readonly<{ + nitroId: Int32; +}>; + +export interface ViewViewNativeProps extends ViewProps { + nitroId: Int32; + onNitroIdChange?: DirectEventHandler; +} + +export default codegenNativeComponent('RNCVideoView'); diff --git a/lib/commonjs/spec/nitro/VideoPlayer.nitro.js b/lib/commonjs/spec/nitro/VideoPlayer.nitro.js new file mode 100644 index 00000000..69b0f599 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayer.nitro.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoPlayer.nitro.js.map \ No newline at end of file diff --git a/lib/commonjs/spec/nitro/VideoPlayer.nitro.js.map b/lib/commonjs/spec/nitro/VideoPlayer.nitro.js.map new file mode 100644 index 00000000..f974a4e3 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayer.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayer.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js b/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js new file mode 100644 index 00000000..ba7e687e --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoPlayerEventEmitter.nitro.js.map \ No newline at end of file diff --git a/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js.map b/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js.map new file mode 100644 index 00000000..7250c716 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayerEventEmitter.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayerEventEmitter.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js b/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js new file mode 100644 index 00000000..3242e8c7 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoPlayerSource.nitro.js.map \ No newline at end of file diff --git a/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js.map b/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js.map new file mode 100644 index 00000000..0717839d --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoPlayerSource.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayerSource.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js b/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js new file mode 100644 index 00000000..8afe0187 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js @@ -0,0 +1,6 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//# sourceMappingURL=VideoViewViewManager.nitro.js.map \ No newline at end of file diff --git a/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js.map b/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js.map new file mode 100644 index 00000000..102a6896 --- /dev/null +++ b/lib/commonjs/spec/nitro/VideoViewViewManager.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoViewViewManager.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/VideoPlayer.js b/lib/module/core/VideoPlayer.js new file mode 100644 index 00000000..f73234fc --- /dev/null +++ b/lib/module/core/VideoPlayer.js @@ -0,0 +1,237 @@ +"use strict"; + +import { Platform } from 'react-native'; +import { NitroModules } from 'react-native-nitro-modules'; +import { tryParseNativeVideoError, VideoRuntimeError } from "./types/VideoError.js"; +import { createPlayer } from "./utils/playerFactory.js"; +import { createSource } from "./utils/sourceFactory.js"; +import { VideoPlayerEvents } from "./VideoPlayerEvents.js"; +class VideoPlayer extends VideoPlayerEvents { + constructor(source) { + const hybridSource = createSource(source); + const player = createPlayer(hybridSource); + + // Initialize events + super(player.eventEmitter); + this.player = player; + } + + /** + * Cleans up player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * @internal + */ + __destroy() { + this.clearAllEvents(); + this.player.dispose(); + } + + /** + * Returns the native (hybrid) player instance. + * Should not be used outside of the module. + * @internal + */ + __getNativePlayer() { + return this.player; + } + + /** + * Handles parsing native errors to VideoRuntimeError and calling onError if provided + * @internal + */ + throwError(error) { + const parsedError = tryParseNativeVideoError(error); + if (parsedError instanceof VideoRuntimeError && this.triggerEvent('onError', parsedError)) { + // We don't throw errors if onError is provided + return; + } + throw parsedError; + } + + /** + * Wraps a promise to try parsing native errors to VideoRuntimeError + * @internal + */ + wrapPromise(promise) { + return new Promise((resolve, reject) => { + promise.then(resolve).catch(error => { + reject(this.throwError(error)); + }); + }); + } + + // Source + get source() { + return this.player.source; + } + + // Status + get status() { + return this.player.status; + } + + // Duration + get duration() { + return this.player.duration; + } + + // Volume + get volume() { + return this.player.volume; + } + set volume(value) { + this.player.volume = value; + } + + // Current Time + get currentTime() { + return this.player.currentTime; + } + set currentTime(value) { + this.player.currentTime = value; + } + + // Muted + get muted() { + return this.player.muted; + } + set muted(value) { + this.player.muted = value; + } + + // Loop + get loop() { + return this.player.loop; + } + set loop(value) { + this.player.loop = value; + } + + // Rate + get rate() { + return this.player.rate; + } + set rate(value) { + this.player.rate = value; + } + + // Mix Audio Mode + get mixAudioMode() { + return this.player.mixAudioMode; + } + set mixAudioMode(value) { + this.player.mixAudioMode = value; + } + + // Ignore Silent Switch Mode + get ignoreSilentSwitchMode() { + return this.player.ignoreSilentSwitchMode; + } + set ignoreSilentSwitchMode(value) { + if (__DEV__ && !['ios'].includes(Platform.OS)) { + console.warn('ignoreSilentSwitchMode is not supported on this platform, it wont have any effect'); + } + this.player.ignoreSilentSwitchMode = value; + } + + // Play In Background + get playInBackground() { + return this.player.playInBackground; + } + set playInBackground(value) { + this.player.playInBackground = value; + } + + // Play When Inactive + get playWhenInactive() { + return this.player.playWhenInactive; + } + set playWhenInactive(value) { + this.player.playWhenInactive = value; + } + + // Is Playing + get isPlaying() { + return this.player.isPlaying; + } + get showNotificationControls() { + return this.player.showNotificationControls; + } + set showNotificationControls(value) { + this.player.showNotificationControls = value; + } + async initialize() { + await this.wrapPromise(this.player.initialize()); + NitroModules.updateMemorySize(this.player); + } + async preload() { + await this.wrapPromise(this.player.preload()); + NitroModules.updateMemorySize(this.player); + } + + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release() { + this.__destroy(); + } + play() { + try { + this.player.play(); + } catch (error) { + this.throwError(error); + } + } + pause() { + try { + this.player.pause(); + } catch (error) { + this.throwError(error); + } + } + seekBy(time) { + try { + this.player.seekBy(time); + } catch (error) { + this.throwError(error); + } + } + seekTo(time) { + try { + this.player.seekTo(time); + } catch (error) { + this.throwError(error); + } + } + async replaceSourceAsync(source) { + await this.wrapPromise(this.player.replaceSourceAsync(source === null ? null : createSource(source))); + NitroModules.updateMemorySize(this.player); + } + + // Text Track Management + getAvailableTextTracks() { + try { + return this.player.getAvailableTextTracks(); + } catch (error) { + this.throwError(error); + return []; + } + } + selectTextTrack(textTrack) { + try { + this.player.selectTextTrack(textTrack); + } catch (error) { + this.throwError(error); + } + } + + // Selected Text Track + get selectedTrack() { + return this.player.selectedTrack; + } +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.js.map \ No newline at end of file diff --git a/lib/module/core/VideoPlayer.js.map b/lib/module/core/VideoPlayer.js.map new file mode 100644 index 00000000..6f9f13c3 --- /dev/null +++ b/lib/module/core/VideoPlayer.js.map @@ -0,0 +1 @@ +{"version":3,"names":["Platform","NitroModules","tryParseNativeVideoError","VideoRuntimeError","createPlayer","createSource","VideoPlayerEvents","VideoPlayer","constructor","source","hybridSource","player","eventEmitter","__destroy","clearAllEvents","dispose","__getNativePlayer","throwError","error","parsedError","triggerEvent","wrapPromise","promise","Promise","resolve","reject","then","catch","status","duration","volume","value","currentTime","muted","loop","rate","mixAudioMode","ignoreSilentSwitchMode","__DEV__","includes","OS","console","warn","playInBackground","playWhenInactive","isPlaying","showNotificationControls","initialize","updateMemorySize","preload","release","play","pause","seekBy","time","seekTo","replaceSourceAsync","getAvailableTextTracks","selectTextTrack","textTrack","selectedTrack"],"sourceRoot":"../../../src","sources":["core/VideoPlayer.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AACvC,SAASC,YAAY,QAAQ,4BAA4B;AAQzD,SACEC,wBAAwB,EACxBC,iBAAiB,QACZ,uBAAoB;AAG3B,SAASC,YAAY,QAAQ,0BAAuB;AACpD,SAASC,YAAY,QAAQ,0BAAuB;AACpD,SAASC,iBAAiB,QAAQ,wBAAqB;AAEvD,MAAMC,WAAW,SAASD,iBAAiB,CAA4B;EAGrEE,WAAWA,CAACC,MAAqD,EAAE;IACjE,MAAMC,YAAY,GAAGL,YAAY,CAACI,MAAM,CAAC;IACzC,MAAME,MAAM,GAAGP,YAAY,CAACM,YAAY,CAAC;;IAEzC;IACA,KAAK,CAACC,MAAM,CAACC,YAAY,CAAC;IAC1B,IAAI,CAACD,MAAM,GAAGA,MAAM;EACtB;;EAEA;AACF;AACA;AACA;AACA;EACEE,SAASA,CAAA,EAAG;IACV,IAAI,CAACC,cAAc,CAAC,CAAC;IACrB,IAAI,CAACH,MAAM,CAACI,OAAO,CAAC,CAAC;EACvB;;EAEA;AACF;AACA;AACA;AACA;EACEC,iBAAiBA,CAAA,EAAG;IAClB,OAAO,IAAI,CAACL,MAAM;EACpB;;EAEA;AACF;AACA;AACA;EACUM,UAAUA,CAACC,KAAc,EAAE;IACjC,MAAMC,WAAW,GAAGjB,wBAAwB,CAACgB,KAAK,CAAC;IAEnD,IACEC,WAAW,YAAYhB,iBAAiB,IACxC,IAAI,CAACiB,YAAY,CAAC,SAAS,EAAED,WAAW,CAAC,EACzC;MACA;MACA;IACF;IAEA,MAAMA,WAAW;EACnB;;EAEA;AACF;AACA;AACA;EACUE,WAAWA,CAAIC,OAAmB,EAAE;IAC1C,OAAO,IAAIC,OAAO,CAAI,CAACC,OAAO,EAAEC,MAAM,KAAK;MACzCH,OAAO,CAACI,IAAI,CAACF,OAAO,CAAC,CAACG,KAAK,CAAET,KAAK,IAAK;QACrCO,MAAM,CAAC,IAAI,CAACR,UAAU,CAACC,KAAK,CAAC,CAAC;MAChC,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ;;EAEA;EACA,IAAIT,MAAMA,CAAA,EAAsB;IAC9B,OAAO,IAAI,CAACE,MAAM,CAACF,MAAM;EAC3B;;EAEA;EACA,IAAImB,MAAMA,CAAA,EAAsB;IAC9B,OAAO,IAAI,CAACjB,MAAM,CAACiB,MAAM;EAC3B;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAAClB,MAAM,CAACkB,QAAQ;EAC7B;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAW;IACnB,OAAO,IAAI,CAACnB,MAAM,CAACmB,MAAM;EAC3B;EAEA,IAAIA,MAAMA,CAACC,KAAa,EAAE;IACxB,IAAI,CAACpB,MAAM,CAACmB,MAAM,GAAGC,KAAK;EAC5B;;EAEA;EACA,IAAIC,WAAWA,CAAA,EAAW;IACxB,OAAO,IAAI,CAACrB,MAAM,CAACqB,WAAW;EAChC;EAEA,IAAIA,WAAWA,CAACD,KAAa,EAAE;IAC7B,IAAI,CAACpB,MAAM,CAACqB,WAAW,GAAGD,KAAK;EACjC;;EAEA;EACA,IAAIE,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAACtB,MAAM,CAACsB,KAAK;EAC1B;EAEA,IAAIA,KAAKA,CAACF,KAAc,EAAE;IACxB,IAAI,CAACpB,MAAM,CAACsB,KAAK,GAAGF,KAAK;EAC3B;;EAEA;EACA,IAAIG,IAAIA,CAAA,EAAY;IAClB,OAAO,IAAI,CAACvB,MAAM,CAACuB,IAAI;EACzB;EAEA,IAAIA,IAAIA,CAACH,KAAc,EAAE;IACvB,IAAI,CAACpB,MAAM,CAACuB,IAAI,GAAGH,KAAK;EAC1B;;EAEA;EACA,IAAII,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAACxB,MAAM,CAACwB,IAAI;EACzB;EAEA,IAAIA,IAAIA,CAACJ,KAAa,EAAE;IACtB,IAAI,CAACpB,MAAM,CAACwB,IAAI,GAAGJ,KAAK;EAC1B;;EAEA;EACA,IAAIK,YAAYA,CAAA,EAAiB;IAC/B,OAAO,IAAI,CAACzB,MAAM,CAACyB,YAAY;EACjC;EAEA,IAAIA,YAAYA,CAACL,KAAmB,EAAE;IACpC,IAAI,CAACpB,MAAM,CAACyB,YAAY,GAAGL,KAAK;EAClC;;EAEA;EACA,IAAIM,sBAAsBA,CAAA,EAA2B;IACnD,OAAO,IAAI,CAAC1B,MAAM,CAAC0B,sBAAsB;EAC3C;EAEA,IAAIA,sBAAsBA,CAACN,KAA6B,EAAE;IACxD,IAAIO,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,CAACC,QAAQ,CAACvC,QAAQ,CAACwC,EAAE,CAAC,EAAE;MAC7CC,OAAO,CAACC,IAAI,CACV,mFACF,CAAC;IACH;IAEA,IAAI,CAAC/B,MAAM,CAAC0B,sBAAsB,GAAGN,KAAK;EAC5C;;EAEA;EACA,IAAIY,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI,CAAChC,MAAM,CAACgC,gBAAgB;EACrC;EAEA,IAAIA,gBAAgBA,CAACZ,KAAc,EAAE;IACnC,IAAI,CAACpB,MAAM,CAACgC,gBAAgB,GAAGZ,KAAK;EACtC;;EAEA;EACA,IAAIa,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI,CAACjC,MAAM,CAACiC,gBAAgB;EACrC;EAEA,IAAIA,gBAAgBA,CAACb,KAAc,EAAE;IACnC,IAAI,CAACpB,MAAM,CAACiC,gBAAgB,GAAGb,KAAK;EACtC;;EAEA;EACA,IAAIc,SAASA,CAAA,EAAY;IACvB,OAAO,IAAI,CAAClC,MAAM,CAACkC,SAAS;EAC9B;EAEA,IAAIC,wBAAwBA,CAAA,EAAY;IACtC,OAAO,IAAI,CAACnC,MAAM,CAACmC,wBAAwB;EAC7C;EAEA,IAAIA,wBAAwBA,CAACf,KAAc,EAAE;IAC3C,IAAI,CAACpB,MAAM,CAACmC,wBAAwB,GAAGf,KAAK;EAC9C;EAEA,MAAMgB,UAAUA,CAAA,EAAkB;IAChC,MAAM,IAAI,CAAC1B,WAAW,CAAC,IAAI,CAACV,MAAM,CAACoC,UAAU,CAAC,CAAC,CAAC;IAEhD9C,YAAY,CAAC+C,gBAAgB,CAAC,IAAI,CAACrC,MAAM,CAAC;EAC5C;EAEA,MAAMsC,OAAOA,CAAA,EAAkB;IAC7B,MAAM,IAAI,CAAC5B,WAAW,CAAC,IAAI,CAACV,MAAM,CAACsC,OAAO,CAAC,CAAC,CAAC;IAE7ChD,YAAY,CAAC+C,gBAAgB,CAAC,IAAI,CAACrC,MAAM,CAAC;EAC5C;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEuC,OAAOA,CAAA,EAAS;IACd,IAAI,CAACrC,SAAS,CAAC,CAAC;EAClB;EAEAsC,IAAIA,CAAA,EAAS;IACX,IAAI;MACF,IAAI,CAACxC,MAAM,CAACwC,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,OAAOjC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAkC,KAAKA,CAAA,EAAS;IACZ,IAAI;MACF,IAAI,CAACzC,MAAM,CAACyC,KAAK,CAAC,CAAC;IACrB,CAAC,CAAC,OAAOlC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAmC,MAAMA,CAACC,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAAC3C,MAAM,CAAC0C,MAAM,CAACC,IAAI,CAAC;IAC1B,CAAC,CAAC,OAAOpC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAqC,MAAMA,CAACD,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAAC3C,MAAM,CAAC4C,MAAM,CAACD,IAAI,CAAC;IAC1B,CAAC,CAAC,OAAOpC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEA,MAAMsC,kBAAkBA,CACtB/C,MAA4E,EAC7D;IACf,MAAM,IAAI,CAACY,WAAW,CACpB,IAAI,CAACV,MAAM,CAAC6C,kBAAkB,CAC5B/C,MAAM,KAAK,IAAI,GAAG,IAAI,GAAGJ,YAAY,CAACI,MAAM,CAC9C,CACF,CAAC;IAEDR,YAAY,CAAC+C,gBAAgB,CAAC,IAAI,CAACrC,MAAM,CAAC;EAC5C;;EAEA;EACA8C,sBAAsBA,CAAA,EAAgB;IACpC,IAAI;MACF,OAAO,IAAI,CAAC9C,MAAM,CAAC8C,sBAAsB,CAAC,CAAC;IAC7C,CAAC,CAAC,OAAOvC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;MACtB,OAAO,EAAE;IACX;EACF;EAEAwC,eAAeA,CAACC,SAA2B,EAAQ;IACjD,IAAI;MACF,IAAI,CAAChD,MAAM,CAAC+C,eAAe,CAACC,SAAS,CAAC;IACxC,CAAC,CAAC,OAAOzC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;;EAEA;EACA,IAAI0C,aAAaA,CAAA,EAA0B;IACzC,OAAO,IAAI,CAACjD,MAAM,CAACiD,aAAa;EAClC;AACF;AAEA,SAASrD,WAAW","ignoreList":[]} diff --git a/lib/module/core/VideoPlayer.web.js b/lib/module/core/VideoPlayer.web.js new file mode 100644 index 00000000..b79419ed --- /dev/null +++ b/lib/module/core/VideoPlayer.web.js @@ -0,0 +1,236 @@ +"use strict"; + +import shaka from "shaka-player"; +import { tryParseNativeVideoError, VideoRuntimeError } from "./types/VideoError.js"; +import { VideoPlayerEvents } from "./VideoPlayerEvents.js"; +import { WebEventEmiter } from "./WebEventEmiter.js"; +class VideoPlayer extends VideoPlayerEvents { + player = new shaka.Player(); + headers = {}; + constructor(source) { + const video = document.createElement("video"); + super(new WebEventEmiter(video)); + this.video = video; + this.player.attach(this.video); + this.player.getNetworkingEngine().registerRequestFilter((_type, request) => { + request.headers = this.headers; + }); + this.replaceSourceAsync(source); + } + + /** + * Cleans up player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * @internal + */ + __destroy() { + this.player.destroy(); + } + __getNativeRef() { + return this.video; + } + + /** + * Handles parsing native errors to VideoRuntimeError and calling onError if provided + * @internal + */ + throwError(error) { + const parsedError = tryParseNativeVideoError(error); + if (parsedError instanceof VideoRuntimeError && this.triggerEvent("onError", parsedError)) { + // We don't throw errors if onError is provided + return; + } + throw parsedError; + } + + // Source + get source() { + // TODO: properly implement this + return { + uri: this.player.getAssetUri(), + config: {} + }; + } + + // Status + get status() { + if (this.video.error) return "error"; + if (this.video.readyState === HTMLMediaElement.HAVE_NOTHING) return "idle"; + if (this.video.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA || this.video.readyState === HTMLMediaElement.HAVE_FUTURE_DATA) return "readyToPlay"; + return "loading"; + } + + // Duration + get duration() { + return this.video.duration; + } + + // Volume + get volume() { + return this.video.volume; + } + set volume(value) { + this.video.volume = value; + } + + // Current Time + get currentTime() { + return this.video.currentTime; + } + set currentTime(value) { + this.video.currentTime = value; + } + + // Muted + get muted() { + return this.video.muted; + } + set muted(value) { + this.video.muted = value; + } + + // Loop + get loop() { + return this.video.loop; + } + set loop(value) { + this.video.loop = value; + } + + // Rate + get rate() { + return this.video.playbackRate; + } + set rate(value) { + this.video.playbackRate = value; + } + + // Mix Audio Mode + get mixAudioMode() { + return "auto"; + } + set mixAudioMode(_) { + if (__DEV__) { + console.warn("mixAudioMode is not supported on this platform, it wont have any effect"); + } + } + + // Ignore Silent Switch Mode + get ignoreSilentSwitchMode() { + return "auto"; + } + set ignoreSilentSwitchMode(_) { + if (__DEV__) { + console.warn("ignoreSilentSwitchMode is not supported on this platform, it wont have any effect"); + } + } + + // Play In Background + get playInBackground() { + return true; + } + set playInBackground(_) { + if (__DEV__) { + console.warn("playInBackground is not supported on this platform, it wont have any effect"); + } + } + + // Play When Inactive + get playWhenInactive() { + return true; + } + set playWhenInactive(_) { + if (__DEV__) { + console.warn("playWhenInactive is not supported on this platform, it wont have any effect"); + } + } + + // Is Playing + get isPlaying() { + return this.status === "readyToPlay" && !this.video.paused; + } + async initialize() { + // noop on web + } + async preload() { + // we start loading when initializing the source. + } + + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release() { + this.__destroy(); + } + play() { + try { + this.video.play(); + } catch (error) { + this.throwError(error); + } + } + pause() { + try { + this.video.pause(); + } catch (error) { + this.throwError(error); + } + } + seekBy(time) { + try { + this.video.currentTime += time; + } catch (error) { + this.throwError(error); + } + } + seekTo(time) { + try { + this.video.currentTime = time; + } catch (error) { + this.throwError(error); + } + } + async replaceSourceAsync(source) { + const src = typeof source === "object" && source && "uri" in source ? source.uri : source; + if (typeof src === "number") { + console.error("A source uri must be a string. Numbers are only supported on native."); + return; + } + // TODO: handle start time + this.player.load(src); + if (typeof source !== "object") return; + this.headers = source?.headers ?? {}; + // this.player.configure({ + // drm: undefined, + // streaming: { + // bufferingGoal: source?.bufferConfig?.maxBufferMs, + // }, + // } satisfies Partial); + } + + // Text Track Management + getAvailableTextTracks() { + return this.player.getTextTracks().map(x => ({ + id: x.id.toString(), + label: x.label ?? "", + language: x.language, + selected: x.active + })); + } + selectTextTrack(textTrack) { + this.player.setTextTrackVisibility(textTrack !== null); + if (!textTrack) return; + const track = this.player.getTextTracks().find(x => x.id === Number(textTrack.id)); + if (track) this.player.selectTextTrack(track); + } + + // Selected Text Track + get selectedTrack() { + return this.getAvailableTextTracks().find(x => x.selected); + } +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.web.js.map \ No newline at end of file diff --git a/lib/module/core/VideoPlayer.web.js.map b/lib/module/core/VideoPlayer.web.js.map new file mode 100644 index 00000000..f7f05690 --- /dev/null +++ b/lib/module/core/VideoPlayer.web.js.map @@ -0,0 +1 @@ +{"version":3,"names":["shaka","tryParseNativeVideoError","VideoRuntimeError","VideoPlayerEvents","WebEventEmiter","VideoPlayer","player","Player","headers","constructor","source","video","document","createElement","attach","getNetworkingEngine","registerRequestFilter","_type","request","replaceSourceAsync","__destroy","destroy","__getNativeRef","throwError","error","parsedError","triggerEvent","uri","getAssetUri","config","status","readyState","HTMLMediaElement","HAVE_NOTHING","HAVE_ENOUGH_DATA","HAVE_FUTURE_DATA","duration","volume","value","currentTime","muted","loop","rate","playbackRate","mixAudioMode","_","__DEV__","console","warn","ignoreSilentSwitchMode","playInBackground","playWhenInactive","isPlaying","paused","initialize","preload","release","play","pause","seekBy","time","seekTo","src","load","getAvailableTextTracks","getTextTracks","map","x","id","toString","label","language","selected","active","selectTextTrack","textTrack","setTextTrackVisibility","track","find","Number","selectedTrack"],"sourceRoot":"../../../src","sources":["core/VideoPlayer.web.ts"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,cAAc;AAOhC,SACEC,wBAAwB,EACxBC,iBAAiB,QACZ,uBAAoB;AAG3B,SAASC,iBAAiB,QAAQ,wBAAqB;AACvD,SAASC,cAAc,QAAQ,qBAAkB;AAEjD,MAAMC,WAAW,SAASF,iBAAiB,CAA4B;EAC3DG,MAAM,GAAG,IAAIN,KAAK,CAACO,MAAM,CAAC,CAAC;EAE3BC,OAAO,GAA2B,CAAC,CAAC;EAE9CC,WAAWA,CAACC,MAAqD,EAAE;IACjE,MAAMC,KAAK,GAAGC,QAAQ,CAACC,aAAa,CAAC,OAAO,CAAC;IAC7C,KAAK,CAAC,IAAIT,cAAc,CAACO,KAAK,CAAC,CAAC;IAChC,IAAI,CAACA,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACL,MAAM,CAACQ,MAAM,CAAC,IAAI,CAACH,KAAK,CAAC;IAC9B,IAAI,CAACL,MAAM,CAACS,mBAAmB,CAAC,CAAC,CAAEC,qBAAqB,CAAC,CAACC,KAAK,EAAEC,OAAO,KAAK;MAC3EA,OAAO,CAACV,OAAO,GAAG,IAAI,CAACA,OAAO;IAChC,CAAC,CAAC;IACF,IAAI,CAACW,kBAAkB,CAACT,MAAM,CAAC;EACjC;;EAEA;AACF;AACA;AACA;AACA;EACEU,SAASA,CAAA,EAAG;IACV,IAAI,CAACd,MAAM,CAACe,OAAO,CAAC,CAAC;EACvB;EAEAC,cAAcA,CAAA,EAAG;IACf,OAAO,IAAI,CAACX,KAAK;EACnB;;EAEA;AACF;AACA;AACA;EACUY,UAAUA,CAACC,KAAc,EAAE;IACjC,MAAMC,WAAW,GAAGxB,wBAAwB,CAACuB,KAAK,CAAC;IAEnD,IACEC,WAAW,YAAYvB,iBAAiB,IACxC,IAAI,CAACwB,YAAY,CAAC,SAAS,EAAED,WAAW,CAAC,EACzC;MACA;MACA;IACF;IAEA,MAAMA,WAAW;EACnB;;EAEA;EACA,IAAIf,MAAMA,CAAA,EAAsB;IAC9B;IACA,OAAO;MACLiB,GAAG,EAAE,IAAI,CAACrB,MAAM,CAACsB,WAAW,CAAC,CAAE;MAC/BC,MAAM,EAAE,CAAC;IACX,CAAC;EACH;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAsB;IAC9B,IAAI,IAAI,CAACnB,KAAK,CAACa,KAAK,EAAE,OAAO,OAAO;IACpC,IAAI,IAAI,CAACb,KAAK,CAACoB,UAAU,KAAKC,gBAAgB,CAACC,YAAY,EAAE,OAAO,MAAM;IAC1E,IACE,IAAI,CAACtB,KAAK,CAACoB,UAAU,KAAKC,gBAAgB,CAACE,gBAAgB,IAC3D,IAAI,CAACvB,KAAK,CAACoB,UAAU,KAAKC,gBAAgB,CAACG,gBAAgB,EAE3D,OAAO,aAAa;IACtB,OAAO,SAAS;EAClB;;EAEA;EACA,IAAIC,QAAQA,CAAA,EAAW;IACrB,OAAO,IAAI,CAACzB,KAAK,CAACyB,QAAQ;EAC5B;;EAEA;EACA,IAAIC,MAAMA,CAAA,EAAW;IACnB,OAAO,IAAI,CAAC1B,KAAK,CAAC0B,MAAM;EAC1B;EAEA,IAAIA,MAAMA,CAACC,KAAa,EAAE;IACxB,IAAI,CAAC3B,KAAK,CAAC0B,MAAM,GAAGC,KAAK;EAC3B;;EAEA;EACA,IAAIC,WAAWA,CAAA,EAAW;IACxB,OAAO,IAAI,CAAC5B,KAAK,CAAC4B,WAAW;EAC/B;EAEA,IAAIA,WAAWA,CAACD,KAAa,EAAE;IAC7B,IAAI,CAAC3B,KAAK,CAAC4B,WAAW,GAAGD,KAAK;EAChC;;EAEA;EACA,IAAIE,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAAC7B,KAAK,CAAC6B,KAAK;EACzB;EAEA,IAAIA,KAAKA,CAACF,KAAc,EAAE;IACxB,IAAI,CAAC3B,KAAK,CAAC6B,KAAK,GAAGF,KAAK;EAC1B;;EAEA;EACA,IAAIG,IAAIA,CAAA,EAAY;IAClB,OAAO,IAAI,CAAC9B,KAAK,CAAC8B,IAAI;EACxB;EAEA,IAAIA,IAAIA,CAACH,KAAc,EAAE;IACvB,IAAI,CAAC3B,KAAK,CAAC8B,IAAI,GAAGH,KAAK;EACzB;;EAEA;EACA,IAAII,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAAC/B,KAAK,CAACgC,YAAY;EAChC;EAEA,IAAID,IAAIA,CAACJ,KAAa,EAAE;IACtB,IAAI,CAAC3B,KAAK,CAACgC,YAAY,GAAGL,KAAK;EACjC;;EAEA;EACA,IAAIM,YAAYA,CAAA,EAAiB;IAC/B,OAAO,MAAM;EACf;EAEA,IAAIA,YAAYA,CAACC,CAAe,EAAE;IAChC,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,yEACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIC,sBAAsBA,CAAA,EAA2B;IACnD,OAAO,MAAM;EACf;EAEA,IAAIA,sBAAsBA,CAACJ,CAAyB,EAAE;IACpD,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,mFACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIE,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI;EACb;EAEA,IAAIA,gBAAgBA,CAACL,CAAU,EAAE;IAC/B,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,6EACF,CAAC;IACH;EACF;;EAEA;EACA,IAAIG,gBAAgBA,CAAA,EAAY;IAC9B,OAAO,IAAI;EACb;EAEA,IAAIA,gBAAgBA,CAACN,CAAU,EAAE;IAC/B,IAAIC,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CACV,6EACF,CAAC;IACH;EACF;;EAEA;EACA,IAAII,SAASA,CAAA,EAAY;IACvB,OAAO,IAAI,CAACtB,MAAM,KAAK,aAAa,IAAI,CAAC,IAAI,CAACnB,KAAK,CAAC0C,MAAM;EAC5D;EAEA,MAAMC,UAAUA,CAAA,EAAkB;IAChC;EAAA;EAGF,MAAMC,OAAOA,CAAA,EAAkB;IAC7B;EAAA;;EAGF;AACF;AACA;AACA;AACA;AACA;EACEC,OAAOA,CAAA,EAAS;IACd,IAAI,CAACpC,SAAS,CAAC,CAAC;EAClB;EAEAqC,IAAIA,CAAA,EAAS;IACX,IAAI;MACF,IAAI,CAAC9C,KAAK,CAAC8C,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC,OAAOjC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAkC,KAAKA,CAAA,EAAS;IACZ,IAAI;MACF,IAAI,CAAC/C,KAAK,CAAC+C,KAAK,CAAC,CAAC;IACpB,CAAC,CAAC,OAAOlC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAmC,MAAMA,CAACC,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAACjD,KAAK,CAAC4B,WAAW,IAAIqB,IAAI;IAChC,CAAC,CAAC,OAAOpC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEAqC,MAAMA,CAACD,IAAY,EAAQ;IACzB,IAAI;MACF,IAAI,CAACjD,KAAK,CAAC4B,WAAW,GAAGqB,IAAI;IAC/B,CAAC,CAAC,OAAOpC,KAAK,EAAE;MACd,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACxB;EACF;EAEA,MAAML,kBAAkBA,CACtBT,MAIQ,EACO;IACf,MAAMoD,GAAG,GACP,OAAOpD,MAAM,KAAK,QAAQ,IAAIA,MAAM,IAAI,KAAK,IAAIA,MAAM,GACnDA,MAAM,CAACiB,GAAG,GACVjB,MAAM;IACZ,IAAI,OAAOoD,GAAG,KAAK,QAAQ,EAAE;MAC3Bf,OAAO,CAACvB,KAAK,CAAC,sEAAsE,CAAC;MACrF;IACF;IACA;IACA,IAAI,CAAClB,MAAM,CAACyD,IAAI,CAACD,GAAG,CAAC;IACrB,IAAI,OAAOpD,MAAM,KAAK,QAAQ,EAAE;IAEhC,IAAI,CAACF,OAAO,GAAGE,MAAM,EAAEF,OAAO,IAAI,CAAC,CAAC;IACtC;IACA;IACA;IACA;IACA;IACA;EACA;;EAEA;EACAwD,sBAAsBA,CAAA,EAAgB;IACpC,OAAO,IAAI,CAAC1D,MAAM,CAAC2D,aAAa,CAAC,CAAC,CAACC,GAAG,CAACC,CAAC,KAAK;MAC3CC,EAAE,EAAED,CAAC,CAACC,EAAE,CAACC,QAAQ,CAAC,CAAC;MACnBC,KAAK,EAAEH,CAAC,CAACG,KAAK,IAAI,EAAE;MACpBC,QAAQ,EAAEJ,CAAC,CAACI,QAAQ;MACpBC,QAAQ,EAAEL,CAAC,CAACM;IACd,CAAC,CAAC,CAAC;EACL;EAEAC,eAAeA,CAACC,SAA2B,EAAQ;IACjD,IAAI,CAACrE,MAAM,CAACsE,sBAAsB,CAACD,SAAS,KAAK,IAAI,CAAC;IACtD,IAAI,CAACA,SAAS,EAAE;IAChB,MAAME,KAAK,GAAG,IAAI,CAACvE,MAAM,CACtB2D,aAAa,CAAC,CAAC,CACfa,IAAI,CAAEX,CAAC,IAAKA,CAAC,CAACC,EAAE,KAAKW,MAAM,CAACJ,SAAS,CAACP,EAAE,CAAC,CAAC;IAC7C,IAAIS,KAAK,EAAE,IAAI,CAACvE,MAAM,CAACoE,eAAe,CAACG,KAAK,CAAC;EAC/C;;EAEA;EACA,IAAIG,aAAaA,CAAA,EAA0B;IACzC,OAAO,IAAI,CAAChB,sBAAsB,CAAC,CAAC,CAACc,IAAI,CAACX,CAAC,IAAIA,CAAC,CAACK,QAAQ,CAAC;EAC5D;AACF;AAEA,SAASnE,WAAW","ignoreList":[]} diff --git a/lib/module/core/VideoPlayerEvents.js b/lib/module/core/VideoPlayerEvents.js new file mode 100644 index 00000000..abd75e6f --- /dev/null +++ b/lib/module/core/VideoPlayerEvents.js @@ -0,0 +1,46 @@ +"use strict"; + +import { ALL_PLAYER_EVENTS } from "./types/Events.js"; +export class VideoPlayerEvents { + eventListeners = {}; + supportedEvents = ALL_PLAYER_EVENTS; + constructor(eventEmitter) { + this.eventEmitter = eventEmitter; + for (const event of this.supportedEvents) { + // @ts-expect-error we narrow the type of the event + this.eventEmitter[event] = this.triggerEvent.bind(this, event); + } + } + triggerEvent(event, ...params) { + if (!this.eventListeners[event]?.size) return false; + for (const fn of this.eventListeners[event]) { + fn(...params); + } + return true; + } + addEventListener(event, callback) { + this.eventListeners[event] ??= new Set(); + this.eventListeners[event].add(callback); + } + removeEventListener(event, callback) { + this.eventListeners[event]?.delete(callback); + } + + /** + * Clears all events from the event emitter. + */ + clearAllEvents() { + this.supportedEvents.forEach(event => { + this.clearEvent(event); + }); + } + + /** + * Clears a specific event from the event emitter. + * @param event - The name of the event to clear. + */ + clearEvent(event) { + this.eventListeners[event]?.clear(); + } +} +//# sourceMappingURL=VideoPlayerEvents.js.map \ No newline at end of file diff --git a/lib/module/core/VideoPlayerEvents.js.map b/lib/module/core/VideoPlayerEvents.js.map new file mode 100644 index 00000000..fdae3222 --- /dev/null +++ b/lib/module/core/VideoPlayerEvents.js.map @@ -0,0 +1 @@ +{"version":3,"names":["ALL_PLAYER_EVENTS","VideoPlayerEvents","eventListeners","supportedEvents","constructor","eventEmitter","event","triggerEvent","bind","params","size","fn","addEventListener","callback","Set","add","removeEventListener","delete","clearAllEvents","forEach","clearEvent","clear"],"sourceRoot":"../../../src","sources":["core/VideoPlayerEvents.ts"],"mappings":";;AAAA,SACEA,iBAAiB,QAGZ,mBAAgB;AAEvB,OAAO,MAAMC,iBAAiB,CAAC;EAEnBC,cAAc,GAEpB,CAAC,CAAC;EAEaC,eAAe,GAChCH,iBAAiB;EAEnBI,WAAWA,CAACC,YAAgC,EAAE;IAC5C,IAAI,CAACA,YAAY,GAAGA,YAAY;IAChC,KAAK,MAAMC,KAAK,IAAI,IAAI,CAACH,eAAe,EAAE;MACxC;MACA,IAAI,CAACE,YAAY,CAACC,KAAK,CAAC,GAAG,IAAI,CAACC,YAAY,CAACC,IAAI,CAAC,IAAI,EAAEF,KAAK,CAAC;IAChE;EACF;EAEUC,YAAYA,CACpBD,KAAY,EACZ,GAAGG,MAAuC,EACjC;IACT,IAAI,CAAC,IAAI,CAACP,cAAc,CAACI,KAAK,CAAC,EAAEI,IAAI,EAAE,OAAO,KAAK;IACnD,KAAK,MAAMC,EAAE,IAAI,IAAI,CAACT,cAAc,CAACI,KAAK,CAAC,EAAE;MAC3CK,EAAE,CAAC,GAAGF,MAAM,CAAC;IACf;IACA,OAAO,IAAI;EACb;EAEAG,gBAAgBA,CACdN,KAAY,EACZO,QAA6B,EAC7B;IACA,IAAI,CAACX,cAAc,CAACI,KAAK,CAAC,KAAK,IAAIQ,GAAG,CAAsB,CAAC;IAC7D,IAAI,CAACZ,cAAc,CAACI,KAAK,CAAC,CAACS,GAAG,CAACF,QAAQ,CAAC;EAC1C;EAEAG,mBAAmBA,CACjBV,KAAY,EACZO,QAA6B,EAC7B;IACA,IAAI,CAACX,cAAc,CAACI,KAAK,CAAC,EAAEW,MAAM,CAACJ,QAAQ,CAAC;EAC9C;;EAEA;AACF;AACA;EACEK,cAAcA,CAAA,EAAG;IACf,IAAI,CAACf,eAAe,CAACgB,OAAO,CAAEb,KAAK,IAAK;MACtC,IAAI,CAACc,UAAU,CAACd,KAAK,CAAC;IACxB,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;EACEc,UAAUA,CAACd,KAAyB,EAAE;IACpC,IAAI,CAACJ,cAAc,CAACI,KAAK,CAAC,EAAEe,KAAK,CAAC,CAAC;EACrC;AACF","ignoreList":[]} diff --git a/lib/module/core/WebEventEmiter.js b/lib/module/core/WebEventEmiter.js new file mode 100644 index 00000000..03d5afc6 --- /dev/null +++ b/lib/module/core/WebEventEmiter.js @@ -0,0 +1,176 @@ +"use strict"; + +export class WebEventEmiter { + _isBuferring = false; + constructor(video) { + this.video = video; + // TODO: add `onBandwithUpdate` + + // on buffer + this._onCanPlay = this._onCanPlay.bind(this); + this._onWaiting = this._onWaiting.bind(this); + this.video.addEventListener("canplay", this._onCanPlay); + this.video.addEventListener("waiting", this._onWaiting); + + // on end + this._onEnded = this._onEnded.bind(this); + this.video.addEventListener("ended", this._onEnded); + + // on load + this._onDurationChange = this._onDurationChange.bind(this); + this.video.addEventListener("durationchange", this._onDurationChange); + + // on load start + this._onLoadStart = this._onLoadStart.bind(this); + this.video.addEventListener("loadstart", this._onLoadStart); + + // on playback state change + this._onPlay = this._onPlay.bind(this); + this._onPause = this._onPause.bind(this); + this.video.addEventListener("play", this._onPlay); + this.video.addEventListener("pause", this._onPause); + + // on playback rate change + this._onRateChange = this._onRateChange.bind(this); + this.video.addEventListener("ratechange", this._onRateChange); + + // on progress + this._onTimeUpdate = this._onTimeUpdate.bind(this); + this.video.addEventListener("timeupdate", this._onTimeUpdate); + + // on ready to play + this._onLoadedData = this._onLoadedData.bind(this); + this.video.addEventListener("loadeddata", this._onLoadedData); + + // on seek + this._onSeeked = this._onSeeked.bind(this); + this.video.addEventListener("seeked", this._onSeeked); + + // on volume change + this._onVolumeChange = this._onVolumeChange.bind(this); + this.video.addEventListener("volumechange", this._onVolumeChange); + + // on status change + this._onError = this._onError.bind(this); + this.video.addEventListener("error", this._onError); + } + destroy() { + this.video.removeEventListener("canplay", this._onCanPlay); + this.video.removeEventListener("waiting", this._onWaiting); + this.video.removeEventListener("ended", this._onEnded); + this.video.removeEventListener("durationchange", this._onDurationChange); + this.video.removeEventListener("play", this._onPlay); + this.video.removeEventListener("pause", this._onPause); + this.video.removeEventListener("ratechange", this._onRateChange); + this.video.removeEventListener("timeupdate", this._onTimeUpdate); + this.video.removeEventListener("loadeddata", this._onLoadedData); + this.video.removeEventListener("seeked", this._onSeeked); + this.video.removeEventListener("volumechange", this._onVolumeChange); + this.video.removeEventListener("error", this._onError); + } + _onTimeUpdate() { + this.onProgress({ + currentTime: this.video.currentTime, + bufferDuration: this.video.buffered.length ? this.video.buffered.end(this.video.buffered.length - 1) : 0 + }); + } + _onCanPlay() { + this._isBuferring = false; + this.onBuffer(false); + this.onStatusChange("readyToPlay"); + } + _onWaiting() { + this._isBuferring = true; + this.onBuffer(true); + this.onStatusChange("loading"); + } + _onDurationChange() { + this.onLoad({ + currentTime: this.video.currentTime, + duration: this.video.duration, + width: this.video.width, + height: this.video.height, + orientation: "unknown" + }); + } + _onEnded() { + this.onEnd(); + this.onStatusChange("idle"); + } + _onLoadStart() { + this.onLoadStart({ + sourceType: "network", + source: { + uri: this.video.currentSrc, + config: { + uri: this.video.currentSrc, + externalSubtitles: [] + }, + getAssetInformationAsync: async () => { + return { + duration: BigInt(this.video.duration), + height: this.video.height, + width: this.video.width, + orientation: "unknown", + bitrate: NaN, + fileSize: BigInt(NaN), + isHDR: false, + isLive: false + }; + } + } + }); + } + _onPlay() { + this.onPlaybackStateChange({ + isPlaying: true, + isBuffering: this._isBuferring + }); + } + _onPause() { + this.onPlaybackStateChange({ + isPlaying: false, + isBuffering: this._isBuferring + }); + } + _onRateChange() { + this.onPlaybackRateChange(this.video.playbackRate); + } + _onLoadedData() { + this.onReadyToDisplay(); + } + _onSeeked() { + this.onSeek(this.video.currentTime); + } + _onVolumeChange() { + this.onVolumeChange({ + muted: this.video.muted, + volume: this.video.volume + }); + } + _onError() { + this.onStatusChange("error"); + } + NOOP = () => {}; + onError = this.NOOP; + onAudioBecomingNoisy = this.NOOP; + onAudioFocusChange = this.NOOP; + onBandwidthUpdate = this.NOOP; + onBuffer = this.NOOP; + onControlsVisibleChange = this.NOOP; + onEnd = this.NOOP; + onExternalPlaybackChange = this.NOOP; + onLoad = this.NOOP; + onLoadStart = this.NOOP; + onPlaybackStateChange = this.NOOP; + onPlaybackRateChange = this.NOOP; + onProgress = this.NOOP; + onReadyToDisplay = this.NOOP; + onSeek = this.NOOP; + onTimedMetadata = this.NOOP; + onTextTrackDataChanged = this.NOOP; + onTrackChange = this.NOOP; + onVolumeChange = this.NOOP; + onStatusChange = this.NOOP; +} +//# sourceMappingURL=WebEventEmiter.js.map \ No newline at end of file diff --git a/lib/module/core/WebEventEmiter.js.map b/lib/module/core/WebEventEmiter.js.map new file mode 100644 index 00000000..6f52e8ec --- /dev/null +++ b/lib/module/core/WebEventEmiter.js.map @@ -0,0 +1 @@ +{"version":3,"names":["WebEventEmiter","_isBuferring","constructor","video","_onCanPlay","bind","_onWaiting","addEventListener","_onEnded","_onDurationChange","_onLoadStart","_onPlay","_onPause","_onRateChange","_onTimeUpdate","_onLoadedData","_onSeeked","_onVolumeChange","_onError","destroy","removeEventListener","onProgress","currentTime","bufferDuration","buffered","length","end","onBuffer","onStatusChange","onLoad","duration","width","height","orientation","onEnd","onLoadStart","sourceType","source","uri","currentSrc","config","externalSubtitles","getAssetInformationAsync","BigInt","bitrate","NaN","fileSize","isHDR","isLive","onPlaybackStateChange","isPlaying","isBuffering","onPlaybackRateChange","playbackRate","onReadyToDisplay","onSeek","onVolumeChange","muted","volume","NOOP","onError","onAudioBecomingNoisy","onAudioFocusChange","onBandwidthUpdate","onControlsVisibleChange","onExternalPlaybackChange","onTimedMetadata","onTextTrackDataChanged","onTrackChange"],"sourceRoot":"../../../src","sources":["core/WebEventEmiter.ts"],"mappings":";;AAcA,OAAO,MAAMA,cAAc,CAAyB;EAC1CC,YAAY,GAAG,KAAK;EAE5BC,WAAWA,CAASC,KAAuB,EAAE;IAAA,KAAzBA,KAAuB,GAAvBA,KAAuB;IACzC;;IAEA;IACA,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAACC,IAAI,CAAC,IAAI,CAAC;IAC5C,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAACD,IAAI,CAAC,IAAI,CAAC;IAC5C,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAACH,UAAU,CAAC;IACvD,IAAI,CAACD,KAAK,CAACI,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAACD,UAAU,CAAC;;IAEvD;IACA,IAAI,CAACE,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACH,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,QAAQ,CAAC;;IAEnD;IACA,IAAI,CAACC,iBAAiB,GAAG,IAAI,CAACA,iBAAiB,CAACJ,IAAI,CAAC,IAAI,CAAC;IAC1D,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAACE,iBAAiB,CAAC;;IAErE;IACA,IAAI,CAACC,YAAY,GAAG,IAAI,CAACA,YAAY,CAACL,IAAI,CAAC,IAAI,CAAC;IAChD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAACG,YAAY,CAAC;;IAE3D;IACA,IAAI,CAACC,OAAO,GAAG,IAAI,CAACA,OAAO,CAACN,IAAI,CAAC,IAAI,CAAC;IACtC,IAAI,CAACO,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACP,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAACI,OAAO,CAAC;IACjD,IAAI,CAACR,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACK,QAAQ,CAAC;;IAEnD;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACR,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACM,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACT,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACO,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,aAAa,GAAG,IAAI,CAACA,aAAa,CAACV,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAACQ,aAAa,CAAC;;IAE7D;IACA,IAAI,CAACC,SAAS,GAAG,IAAI,CAACA,SAAS,CAACX,IAAI,CAAC,IAAI,CAAC;IAC1C,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAACS,SAAS,CAAC;;IAErD;IACA,IAAI,CAACC,eAAe,GAAG,IAAI,CAACA,eAAe,CAACZ,IAAI,CAAC,IAAI,CAAC;IACtD,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAACU,eAAe,CAAC;;IAEjE;IACA,IAAI,CAACC,QAAQ,GAAG,IAAI,CAACA,QAAQ,CAACb,IAAI,CAAC,IAAI,CAAC;IACxC,IAAI,CAACF,KAAK,CAACI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACW,QAAQ,CAAC;EACrD;EAEAC,OAAOA,CAAA,EAAG;IACR,IAAI,CAAChB,KAAK,CAACiB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAChB,UAAU,CAAC;IAC1D,IAAI,CAACD,KAAK,CAACiB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAACd,UAAU,CAAC;IAE1D,IAAI,CAACH,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACZ,QAAQ,CAAC;IAEtD,IAAI,CAACL,KAAK,CAACiB,mBAAmB,CAAC,gBAAgB,EAAE,IAAI,CAACX,iBAAiB,CAAC;IAExE,IAAI,CAACN,KAAK,CAACiB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAACT,OAAO,CAAC;IACpD,IAAI,CAACR,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACR,QAAQ,CAAC;IAEtD,IAAI,CAACT,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACP,aAAa,CAAC;IAEhE,IAAI,CAACV,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACN,aAAa,CAAC;IAEhE,IAAI,CAACX,KAAK,CAACiB,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAACL,aAAa,CAAC;IAEhE,IAAI,CAACZ,KAAK,CAACiB,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAACJ,SAAS,CAAC;IAExD,IAAI,CAACb,KAAK,CAACiB,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAACH,eAAe,CAAC;IAEpE,IAAI,CAACd,KAAK,CAACiB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAACF,QAAQ,CAAC;EACxD;EAEAJ,aAAaA,CAAA,EAAG;IACd,IAAI,CAACO,UAAU,CAAC;MACdC,WAAW,EAAE,IAAI,CAACnB,KAAK,CAACmB,WAAW;MACnCC,cAAc,EAAE,IAAI,CAACpB,KAAK,CAACqB,QAAQ,CAACC,MAAM,GACtC,IAAI,CAACtB,KAAK,CAACqB,QAAQ,CAACE,GAAG,CAAC,IAAI,CAACvB,KAAK,CAACqB,QAAQ,CAACC,MAAM,GAAG,CAAC,CAAC,GACvD;IACN,CAAC,CAAC;EACJ;EAEArB,UAAUA,CAAA,EAAG;IACX,IAAI,CAACH,YAAY,GAAG,KAAK;IACzB,IAAI,CAAC0B,QAAQ,CAAC,KAAK,CAAC;IACpB,IAAI,CAACC,cAAc,CAAC,aAAa,CAAC;EACpC;EACAtB,UAAUA,CAAA,EAAG;IACX,IAAI,CAACL,YAAY,GAAG,IAAI;IACxB,IAAI,CAAC0B,QAAQ,CAAC,IAAI,CAAC;IACnB,IAAI,CAACC,cAAc,CAAC,SAAS,CAAC;EAChC;EAEAnB,iBAAiBA,CAAA,EAAG;IAClB,IAAI,CAACoB,MAAM,CAAC;MACVP,WAAW,EAAE,IAAI,CAACnB,KAAK,CAACmB,WAAW;MACnCQ,QAAQ,EAAE,IAAI,CAAC3B,KAAK,CAAC2B,QAAQ;MAC7BC,KAAK,EAAE,IAAI,CAAC5B,KAAK,CAAC4B,KAAK;MACvBC,MAAM,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,MAAM;MACzBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ;EAEAzB,QAAQA,CAAA,EAAG;IACT,IAAI,CAAC0B,KAAK,CAAC,CAAC;IACZ,IAAI,CAACN,cAAc,CAAC,MAAM,CAAC;EAC7B;EAEAlB,YAAYA,CAAA,EAAG;IACb,IAAI,CAACyB,WAAW,CAAC;MACfC,UAAU,EAAE,SAAS;MACrBC,MAAM,EAAE;QACNC,GAAG,EAAE,IAAI,CAACnC,KAAK,CAACoC,UAAU;QAC1BC,MAAM,EAAE;UACNF,GAAG,EAAE,IAAI,CAACnC,KAAK,CAACoC,UAAU;UAC1BE,iBAAiB,EAAE;QACrB,CAAC;QACDC,wBAAwB,EAAE,MAAAA,CAAA,KAAY;UACpC,OAAO;YACLZ,QAAQ,EAAEa,MAAM,CAAC,IAAI,CAACxC,KAAK,CAAC2B,QAAQ,CAAC;YACrCE,MAAM,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,MAAM;YACzBD,KAAK,EAAE,IAAI,CAAC5B,KAAK,CAAC4B,KAAK;YACvBE,WAAW,EAAE,SAAS;YACtBW,OAAO,EAAEC,GAAG;YACZC,QAAQ,EAAEH,MAAM,CAACE,GAAG,CAAC;YACrBE,KAAK,EAAE,KAAK;YACZC,MAAM,EAAE;UACV,CAAC;QACH;MACF;IACF,CAAC,CAAC;EACJ;EAEArC,OAAOA,CAAA,EAAG;IACR,IAAI,CAACsC,qBAAqB,CAAC;MACzBC,SAAS,EAAE,IAAI;MACfC,WAAW,EAAE,IAAI,CAAClD;IACpB,CAAC,CAAC;EACJ;EAEAW,QAAQA,CAAA,EAAG;IACT,IAAI,CAACqC,qBAAqB,CAAC;MACzBC,SAAS,EAAE,KAAK;MAChBC,WAAW,EAAE,IAAI,CAAClD;IACpB,CAAC,CAAC;EACJ;EAEAY,aAAaA,CAAA,EAAG;IACd,IAAI,CAACuC,oBAAoB,CAAC,IAAI,CAACjD,KAAK,CAACkD,YAAY,CAAC;EACpD;EAEAtC,aAAaA,CAAA,EAAG;IACd,IAAI,CAACuC,gBAAgB,CAAC,CAAC;EACzB;EAEAtC,SAASA,CAAA,EAAG;IACV,IAAI,CAACuC,MAAM,CAAC,IAAI,CAACpD,KAAK,CAACmB,WAAW,CAAC;EACrC;EAEAL,eAAeA,CAAA,EAAG;IAChB,IAAI,CAACuC,cAAc,CAAC;MAAEC,KAAK,EAAE,IAAI,CAACtD,KAAK,CAACsD,KAAK;MAAEC,MAAM,EAAE,IAAI,CAACvD,KAAK,CAACuD;IAAO,CAAC,CAAC;EAC7E;EAEAxC,QAAQA,CAAA,EAAG;IACT,IAAI,CAACU,cAAc,CAAC,OAAO,CAAC;EAC9B;EAEA+B,IAAI,GAAGA,CAAA,KAAM,CAAC,CAAC;EAEfC,OAAO,GAAuC,IAAI,CAACD,IAAI;EACvDE,oBAAoB,GAAe,IAAI,CAACF,IAAI;EAC5CG,kBAAkB,GAAqC,IAAI,CAACH,IAAI;EAChEI,iBAAiB,GAAkC,IAAI,CAACJ,IAAI;EAC5DhC,QAAQ,GAAiC,IAAI,CAACgC,IAAI;EAClDK,uBAAuB,GAA+B,IAAI,CAACL,IAAI;EAC/DzB,KAAK,GAAe,IAAI,CAACyB,IAAI;EAC7BM,wBAAwB,GACtB,IAAI,CAACN,IAAI;EACX9B,MAAM,GAA+B,IAAI,CAAC8B,IAAI;EAC9CxB,WAAW,GAAoC,IAAI,CAACwB,IAAI;EACxDV,qBAAqB,GAA8C,IAAI,CAACU,IAAI;EAC5EP,oBAAoB,GAA2B,IAAI,CAACO,IAAI;EACxDtC,UAAU,GAAmC,IAAI,CAACsC,IAAI;EACtDL,gBAAgB,GAAe,IAAI,CAACK,IAAI;EACxCJ,MAAM,GAA+B,IAAI,CAACI,IAAI;EAC9CO,eAAe,GAAsC,IAAI,CAACP,IAAI;EAC9DQ,sBAAsB,GAA8B,IAAI,CAACR,IAAI;EAC7DS,aAAa,GAAsC,IAAI,CAACT,IAAI;EAC5DH,cAAc,GAAuC,IAAI,CAACG,IAAI;EAC9D/B,cAAc,GAAwC,IAAI,CAAC+B,IAAI;AACjE","ignoreList":[]} diff --git a/lib/module/core/hooks/useEvent.js b/lib/module/core/hooks/useEvent.js new file mode 100644 index 00000000..f843d466 --- /dev/null +++ b/lib/module/core/hooks/useEvent.js @@ -0,0 +1,17 @@ +"use strict"; + +import { useEffect } from 'react'; +/** + * Attaches an event listener to a `VideoPlayer` instance for a specified event. + * + * @param player - The player to attach the event to + * @param event - The name of the event to attach the callback to + * @param callback - The callback for the event + */ +export const useEvent = (player, event, callback) => { + useEffect(() => { + player.addEventListener(event, callback); + return () => player.removeEventListener(event, callback); + }, [player, event, callback]); +}; +//# sourceMappingURL=useEvent.js.map \ No newline at end of file diff --git a/lib/module/core/hooks/useEvent.js.map b/lib/module/core/hooks/useEvent.js.map new file mode 100644 index 00000000..c273fad1 --- /dev/null +++ b/lib/module/core/hooks/useEvent.js.map @@ -0,0 +1 @@ +{"version":3,"names":["useEffect","useEvent","player","event","callback","addEventListener","removeEventListener"],"sourceRoot":"../../../../src","sources":["core/hooks/useEvent.ts"],"mappings":";;AAAA,SAASA,SAAS,QAAQ,OAAO;AAIjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,QAAQ,GAAGA,CACtBC,MAAmB,EACnBC,KAAQ,EACRC,QAA4B,KACzB;EACHJ,SAAS,CAAC,MAAM;IACdE,MAAM,CAACG,gBAAgB,CAACF,KAAK,EAAEC,QAAQ,CAAC;IAExC,OAAO,MAAMF,MAAM,CAACI,mBAAmB,CAACH,KAAK,EAAEC,QAAQ,CAAC;EAC1D,CAAC,EAAE,CAACF,MAAM,EAAEC,KAAK,EAAEC,QAAQ,CAAC,CAAC;AAC/B,CAAC","ignoreList":[]} diff --git a/lib/module/core/hooks/useManagedInstance.js b/lib/module/core/hooks/useManagedInstance.js new file mode 100644 index 00000000..195fd68f --- /dev/null +++ b/lib/module/core/hooks/useManagedInstance.js @@ -0,0 +1,75 @@ +"use strict"; + +import { useEffect, useMemo, useRef, useState } from 'react'; + +/** + * @internal + * A hook that helps to manage the lifecycle of a native instance in a React component. + * It allows instance to be recreated when dependencies change, but not when the component is hot reloaded. + * + * @param config.factory - The factory function that creates the instance. + * @param config.cleanup - The cleanup function that destroys the instance. + * @param config.dependenciesEqualFn - The function that compares the dependencies. + * + * @param dependencies - The dependencies array. + * @returns The managed instance. + */ +export const useManagedInstance = (config, dependencies) => { + const { + factory, + cleanup, + dependenciesEqualFn + } = config; + const objectRef = useRef(null); + const isFastRefresh = useRef(false); + const previousDependencies = useRef(dependencies); + + // Wee need to force a "re-render" to recalculate the object + const [released, setReleased] = useState(false); + if (objectRef.current == null) { + objectRef.current = factory(); + } + const object = useMemo(() => { + let newObject = objectRef.current; + const dependenciesChanged = previousDependencies.current?.length === dependencies.length && dependencies.every((value, index) => dependenciesEqualFn?.(value, previousDependencies.current[index]) ?? value === previousDependencies.current[index]); + if (!newObject || !dependenciesChanged || released) { + // Destroy the old object + if (objectRef.current) { + cleanup(objectRef.current); + objectRef.current = null; + } + + // Create a new object + newObject = factory(); + objectRef.current = newObject; + setReleased(false); + + // Update the previous dependencies + previousDependencies.current = dependencies; + } else { + // If useMemo is re-evaluated, but dependencies are the same + // and object is still the same, we can assume that that + // the component is being hot reloaded + isFastRefresh.current = true; + } + return newObject; + + // factory and cleanup are stable, so we don't need to re-evaluate + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [...dependencies, released]); + useEffect(() => { + isFastRefresh.current = false; + return () => { + if (!isFastRefresh.current && objectRef.current) { + cleanup(objectRef.current); + objectRef.current = null; + setReleased(true); + } + }; + + // factory and cleanup are stable, so we don't need to re-evaluate + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return object; +}; +//# sourceMappingURL=useManagedInstance.js.map \ No newline at end of file diff --git a/lib/module/core/hooks/useManagedInstance.js.map b/lib/module/core/hooks/useManagedInstance.js.map new file mode 100644 index 00000000..b8a51f2e --- /dev/null +++ b/lib/module/core/hooks/useManagedInstance.js.map @@ -0,0 +1 @@ +{"version":3,"names":["useEffect","useMemo","useRef","useState","useManagedInstance","config","dependencies","factory","cleanup","dependenciesEqualFn","objectRef","isFastRefresh","previousDependencies","released","setReleased","current","object","newObject","dependenciesChanged","length","every","value","index"],"sourceRoot":"../../../../src","sources":["core/hooks/useManagedInstance.ts"],"mappings":";;AAAA,SACEA,SAAS,EACTC,OAAO,EACPC,MAAM,EACNC,QAAQ,QAEH,OAAO;;AAEd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,kBAAkB,GAAGA,CAChCC,MAIC,EACDC,YAAiB,KACX;EACN,MAAM;IAAEC,OAAO;IAAEC,OAAO;IAAEC;EAAoB,CAAC,GAAGJ,MAAM;EAExD,MAAMK,SAAS,GAAGR,MAAM,CAAW,IAAI,CAAC;EACxC,MAAMS,aAAa,GAAGT,MAAM,CAAC,KAAK,CAAC;EACnC,MAAMU,oBAAoB,GAAGV,MAAM,CAACI,YAAY,CAAC;;EAEjD;EACA,MAAM,CAACO,QAAQ,EAAEC,WAAW,CAAC,GAAGX,QAAQ,CAAC,KAAK,CAAC;EAE/C,IAAIO,SAAS,CAACK,OAAO,IAAI,IAAI,EAAE;IAC7BL,SAAS,CAACK,OAAO,GAAGR,OAAO,CAAC,CAAC;EAC/B;EAEA,MAAMS,MAAM,GAAGf,OAAO,CAAC,MAAM;IAC3B,IAAIgB,SAAS,GAAGP,SAAS,CAACK,OAAO;IAEjC,MAAMG,mBAAmB,GACvBN,oBAAoB,CAACG,OAAO,EAAEI,MAAM,KAAKb,YAAY,CAACa,MAAM,IAC5Db,YAAY,CAACc,KAAK,CAChB,CAACC,KAAK,EAAEC,KAAK,KACXb,mBAAmB,GAAGY,KAAK,EAAET,oBAAoB,CAACG,OAAO,CAACO,KAAK,CAAC,CAAC,IACjED,KAAK,KAAKT,oBAAoB,CAACG,OAAO,CAACO,KAAK,CAChD,CAAC;IAEH,IAAI,CAACL,SAAS,IAAI,CAACC,mBAAmB,IAAIL,QAAQ,EAAE;MAClD;MACA,IAAIH,SAAS,CAACK,OAAO,EAAE;QACrBP,OAAO,CAACE,SAAS,CAACK,OAAO,CAAC;QAC1BL,SAAS,CAACK,OAAO,GAAG,IAAI;MAC1B;;MAEA;MACAE,SAAS,GAAGV,OAAO,CAAC,CAAC;MACrBG,SAAS,CAACK,OAAO,GAAGE,SAAS;MAC7BH,WAAW,CAAC,KAAK,CAAC;;MAElB;MACAF,oBAAoB,CAACG,OAAO,GAAGT,YAAY;IAC7C,CAAC,MAAM;MACL;MACA;MACA;MACAK,aAAa,CAACI,OAAO,GAAG,IAAI;IAC9B;IAEA,OAAOE,SAAS;;IAEhB;IACA;EACF,CAAC,EAAE,CAAC,GAAGX,YAAY,EAAEO,QAAQ,CAAC,CAAC;EAE/Bb,SAAS,CAAC,MAAM;IACdW,aAAa,CAACI,OAAO,GAAG,KAAK;IAE7B,OAAO,MAAM;MACX,IAAI,CAACJ,aAAa,CAACI,OAAO,IAAIL,SAAS,CAACK,OAAO,EAAE;QAC/CP,OAAO,CAACE,SAAS,CAACK,OAAO,CAAC;QAC1BL,SAAS,CAACK,OAAO,GAAG,IAAI;QACxBD,WAAW,CAAC,IAAI,CAAC;MACnB;IACF,CAAC;;IAED;IACA;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOE,MAAM;AACf,CAAC","ignoreList":[]} diff --git a/lib/module/core/hooks/useVideoPlayer.js b/lib/module/core/hooks/useVideoPlayer.js new file mode 100644 index 00000000..8a451670 --- /dev/null +++ b/lib/module/core/hooks/useVideoPlayer.js @@ -0,0 +1,33 @@ +"use strict"; + +import { isVideoPlayerSource } from "../utils/sourceUtils.js"; +import { VideoPlayer } from '../VideoPlayer'; +import { useManagedInstance } from "./useManagedInstance.js"; +const sourceEqual = (a, b) => { + if (isVideoPlayerSource(a) && isVideoPlayerSource(b)) { + return a.equals(b); + } + return JSON.stringify(a) === JSON.stringify(b); +}; + +/** + * Creates a `VideoPlayer` instance and manages its lifecycle. + * + * @param source - The source of the video to play + * @param setup - A function to setup the player + * @returns The `VideoPlayer` instance + */ +export const useVideoPlayer = (source, setup) => { + return useManagedInstance({ + factory: () => { + const player = new VideoPlayer(source); + setup?.(player); + return player; + }, + cleanup: player => { + player.__destroy(); + }, + dependenciesEqualFn: sourceEqual + }, [JSON.stringify(source)]); +}; +//# sourceMappingURL=useVideoPlayer.js.map \ No newline at end of file diff --git a/lib/module/core/hooks/useVideoPlayer.js.map b/lib/module/core/hooks/useVideoPlayer.js.map new file mode 100644 index 00000000..524bd817 --- /dev/null +++ b/lib/module/core/hooks/useVideoPlayer.js.map @@ -0,0 +1 @@ +{"version":3,"names":["isVideoPlayerSource","VideoPlayer","useManagedInstance","sourceEqual","a","b","equals","JSON","stringify","useVideoPlayer","source","setup","factory","player","cleanup","__destroy","dependenciesEqualFn"],"sourceRoot":"../../../../src","sources":["core/hooks/useVideoPlayer.ts"],"mappings":";;AAGA,SAASA,mBAAmB,QAAQ,yBAAsB;AAC1D,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SAASC,kBAAkB,QAAQ,yBAAsB;AAEzD,MAAMC,WAAW,GAAGA,CAClBC,CAAI,EACJC,CAAK,KACF;EACH,IAAIL,mBAAmB,CAACI,CAAC,CAAC,IAAIJ,mBAAmB,CAACK,CAAC,CAAC,EAAE;IACpD,OAAOD,CAAC,CAACE,MAAM,CAACD,CAAC,CAAC;EACpB;EAEA,OAAOE,IAAI,CAACC,SAAS,CAACJ,CAAC,CAAC,KAAKG,IAAI,CAACC,SAAS,CAACH,CAAC,CAAC;AAChD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMI,cAAc,GAAGA,CAC5BC,MAAqE,EACrEC,KAAqC,KAClC;EACH,OAAOT,kBAAkB,CACvB;IACEU,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMC,MAAM,GAAG,IAAIZ,WAAW,CAACS,MAAM,CAAC;MACtCC,KAAK,GAAGE,MAAM,CAAC;MACf,OAAOA,MAAM;IACf,CAAC;IACDC,OAAO,EAAGD,MAAM,IAAK;MACnBA,MAAM,CAACE,SAAS,CAAC,CAAC;IACpB,CAAC;IACDC,mBAAmB,EAAEb;EACvB,CAAC,EACD,CAACI,IAAI,CAACC,SAAS,CAACE,MAAM,CAAC,CACzB,CAAC;AACH,CAAC","ignoreList":[]} diff --git a/lib/module/core/shaka.d.js b/lib/module/core/shaka.d.js new file mode 100644 index 00000000..42a8a048 --- /dev/null +++ b/lib/module/core/shaka.d.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=shaka.d.js.map \ No newline at end of file diff --git a/lib/module/core/shaka.d.js.map b/lib/module/core/shaka.d.js.map new file mode 100644 index 00000000..bcdbf28a --- /dev/null +++ b/lib/module/core/shaka.d.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../src","sources":["core/shaka.d.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/BufferConfig.js b/lib/module/core/types/BufferConfig.js new file mode 100644 index 00000000..04aece6c --- /dev/null +++ b/lib/module/core/types/BufferConfig.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=BufferConfig.js.map \ No newline at end of file diff --git a/lib/module/core/types/BufferConfig.js.map b/lib/module/core/types/BufferConfig.js.map new file mode 100644 index 00000000..475dae06 --- /dev/null +++ b/lib/module/core/types/BufferConfig.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/BufferConfig.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/DrmParams.js b/lib/module/core/types/DrmParams.js new file mode 100644 index 00000000..cd36ce84 --- /dev/null +++ b/lib/module/core/types/DrmParams.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=DrmParams.js.map \ No newline at end of file diff --git a/lib/module/core/types/DrmParams.js.map b/lib/module/core/types/DrmParams.js.map new file mode 100644 index 00000000..378982d5 --- /dev/null +++ b/lib/module/core/types/DrmParams.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/DrmParams.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/Events.js b/lib/module/core/types/Events.js new file mode 100644 index 00000000..bdcd2c0b --- /dev/null +++ b/lib/module/core/types/Events.js @@ -0,0 +1,9 @@ +"use strict"; + +function allKeysOf() { + return (...arr) => { + return arr; + }; +} +export const ALL_PLAYER_EVENTS = allKeysOf()('onAudioBecomingNoisy', 'onAudioFocusChange', 'onBandwidthUpdate', 'onBuffer', 'onControlsVisibleChange', 'onEnd', 'onError', 'onExternalPlaybackChange', 'onLoad', 'onLoadStart', 'onPlaybackStateChange', 'onPlaybackRateChange', 'onProgress', 'onReadyToDisplay', 'onSeek', 'onTimedMetadata', 'onTextTrackDataChanged', 'onTrackChange', 'onVolumeChange', 'onStatusChange'); +//# sourceMappingURL=Events.js.map \ No newline at end of file diff --git a/lib/module/core/types/Events.js.map b/lib/module/core/types/Events.js.map new file mode 100644 index 00000000..a56cab77 --- /dev/null +++ b/lib/module/core/types/Events.js.map @@ -0,0 +1 @@ +{"version":3,"names":["allKeysOf","arr","ALL_PLAYER_EVENTS"],"sourceRoot":"../../../../src","sources":["core/types/Events.ts"],"mappings":";;AAiPA,SAASA,SAASA,CAAA,EAAM;EACtB,OAAO,CAAiC,GAAGC,GAAM,KAA4B;IAC3E,OAAOA,GAAG;EACZ,CAAC;AACH;AAEA,OAAO,MAAMC,iBAA4C,GACvDF,SAAS,CAAkB,CAAC,CAC1B,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,yBAAyB,EACzB,OAAO,EACP,SAAS,EACT,0BAA0B,EAC1B,QAAQ,EACR,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,gBACF,CAAC","ignoreList":[]} diff --git a/lib/module/core/types/IgnoreSilentSwitchMode.js b/lib/module/core/types/IgnoreSilentSwitchMode.js new file mode 100644 index 00000000..36aad76d --- /dev/null +++ b/lib/module/core/types/IgnoreSilentSwitchMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=IgnoreSilentSwitchMode.js.map \ No newline at end of file diff --git a/lib/module/core/types/IgnoreSilentSwitchMode.js.map b/lib/module/core/types/IgnoreSilentSwitchMode.js.map new file mode 100644 index 00000000..5e9f8609 --- /dev/null +++ b/lib/module/core/types/IgnoreSilentSwitchMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/IgnoreSilentSwitchMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/MixAudioMode.js b/lib/module/core/types/MixAudioMode.js new file mode 100644 index 00000000..3558637e --- /dev/null +++ b/lib/module/core/types/MixAudioMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=MixAudioMode.js.map \ No newline at end of file diff --git a/lib/module/core/types/MixAudioMode.js.map b/lib/module/core/types/MixAudioMode.js.map new file mode 100644 index 00000000..2c7a41f3 --- /dev/null +++ b/lib/module/core/types/MixAudioMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/MixAudioMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/ResizeMode.js b/lib/module/core/types/ResizeMode.js new file mode 100644 index 00000000..38e4fbec --- /dev/null +++ b/lib/module/core/types/ResizeMode.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=ResizeMode.js.map \ No newline at end of file diff --git a/lib/module/core/types/ResizeMode.js.map b/lib/module/core/types/ResizeMode.js.map new file mode 100644 index 00000000..900bbe3a --- /dev/null +++ b/lib/module/core/types/ResizeMode.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/ResizeMode.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/TextTrack.js b/lib/module/core/types/TextTrack.js new file mode 100644 index 00000000..c4369731 --- /dev/null +++ b/lib/module/core/types/TextTrack.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=TextTrack.js.map \ No newline at end of file diff --git a/lib/module/core/types/TextTrack.js.map b/lib/module/core/types/TextTrack.js.map new file mode 100644 index 00000000..2e92273f --- /dev/null +++ b/lib/module/core/types/TextTrack.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/TextTrack.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/Utils.js b/lib/module/core/types/Utils.js new file mode 100644 index 00000000..49c9c084 --- /dev/null +++ b/lib/module/core/types/Utils.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=Utils.js.map \ No newline at end of file diff --git a/lib/module/core/types/Utils.js.map b/lib/module/core/types/Utils.js.map new file mode 100644 index 00000000..2a9f052a --- /dev/null +++ b/lib/module/core/types/Utils.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/Utils.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoConfig.js b/lib/module/core/types/VideoConfig.js new file mode 100644 index 00000000..c6d9b2eb --- /dev/null +++ b/lib/module/core/types/VideoConfig.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoConfig.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoConfig.js.map b/lib/module/core/types/VideoConfig.js.map new file mode 100644 index 00000000..c894f838 --- /dev/null +++ b/lib/module/core/types/VideoConfig.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoConfig.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoError.js b/lib/module/core/types/VideoError.js new file mode 100644 index 00000000..857e28e2 --- /dev/null +++ b/lib/module/core/types/VideoError.js @@ -0,0 +1,100 @@ +"use strict"; + +export class VideoError extends Error { + get code() { + return this._code; + } + get message() { + return this._message; + } + get stack() { + return this._stack; + } + + /** + * @internal + */ + constructor(code, message, stack) { + super(`[${code}]: ${message}`); + super.name = `[ReactNativeVideo] ${code}`; + super.message = message; + super.stack = stack; + this._code = code; + this._message = message; + this._stack = stack; + } + toString() { + let string = `[${this.code}]: ${this.message}`; + return string; + } +} +export class VideoComponentError extends VideoError {} +export class VideoRuntimeError extends VideoError {} + +/** + * Check if the message contains code and message + */ +const getCodeAndMessage = message => { + // (...){%@(match[1])::(match[2]);@%}(...) + const regex = /\{%@([^:]+)::([^@]+)@%\}/; + const match = message.match(regex); + if (match && match.length === 3 && typeof match[1] === 'string' && typeof match[2] === 'string') { + return { + code: match[1], + message: match[2] + }; + } + return null; +}; + +/** + * Check if the error has a stack property + * If it does, it will try to parse the error message in the stack trace + * and replace it with the proper code and message + */ +const maybeFixErrorStack = error => { + if ('stack' in error && typeof error.stack === 'string') { + const stack = error.stack; + + // (...){%@(match[1])::(match[2]);@%}(...) + const regex = /\{%@([^:]+)::([^@]+)@%\}/; + const match = stack.match(regex); + if (match && match.length === 3 && typeof match[1] === 'string' && typeof match[2] === 'string') { + error.stack = error.stack.replace(regex, `[${match[1]}]: ${match[2]}`); + } + } +}; +const isVideoError = error => typeof error === 'object' && error != null && +// @ts-expect-error error is still unknown +typeof error.message === 'string' && +// @ts-expect-error error is still unknown +getCodeAndMessage(error.message) != null; +const hasStack = error => typeof error === 'object' && error != null && 'stack' in error && typeof error.stack === 'string'; + +/** + * Tries to parse an error coming from native to a typed JS video error. + * @param {VideoError} nativeError The native error instance. This is a JSON in the legacy native module architecture. + * @returns A {@linkcode VideoRuntimeError} or {@linkcode VideoComponentError}, or the `nativeError` itself if it's not parsable + * @method + */ +export const tryParseNativeVideoError = nativeError => { + if (isVideoError(nativeError)) { + const result = getCodeAndMessage(nativeError.message); + if (result == null) { + return nativeError; + } + const { + code, + message + } = result; + maybeFixErrorStack(nativeError); + if (code.startsWith('view')) { + return new VideoComponentError(code, message, hasStack(nativeError) ? nativeError.stack : undefined); + } + return new VideoRuntimeError( + // @ts-expect-error the code is string, we narrow it down to TS union. + code, message, hasStack(nativeError) ? nativeError.stack : undefined); + } + return nativeError; +}; +//# sourceMappingURL=VideoError.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoError.js.map b/lib/module/core/types/VideoError.js.map new file mode 100644 index 00000000..c6157d67 --- /dev/null +++ b/lib/module/core/types/VideoError.js.map @@ -0,0 +1 @@ +{"version":3,"names":["VideoError","Error","code","_code","message","_message","stack","_stack","constructor","name","toString","string","VideoComponentError","VideoRuntimeError","getCodeAndMessage","regex","match","length","maybeFixErrorStack","error","replace","isVideoError","hasStack","tryParseNativeVideoError","nativeError","result","startsWith","undefined"],"sourceRoot":"../../../../src","sources":["core/types/VideoError.ts"],"mappings":";;AA+BA,OAAO,MAAMA,UAAU,SAAuCC,KAAK,CAAC;EAKlE,IAAWC,IAAIA,CAAA,EAAU;IACvB,OAAO,IAAI,CAACC,KAAK;EACnB;EACA,IAAWC,OAAOA,CAAA,EAAW;IAC3B,OAAO,IAAI,CAACC,QAAQ;EACtB;EAEA,IAAWC,KAAKA,CAAA,EAAuB;IACrC,OAAO,IAAI,CAACC,MAAM;EACpB;;EAEA;AACF;AACA;EACEC,WAAWA,CAACN,IAAW,EAAEE,OAAe,EAAEE,KAAc,EAAE;IACxD,KAAK,CAAC,IAAIJ,IAAI,MAAME,OAAO,EAAE,CAAC;IAC9B,KAAK,CAACK,IAAI,GAAG,sBAAsBP,IAAI,EAAE;IACzC,KAAK,CAACE,OAAO,GAAGA,OAAO;IACvB,KAAK,CAACE,KAAK,GAAGA,KAAK;IACnB,IAAI,CAACH,KAAK,GAAGD,IAAI;IACjB,IAAI,CAACG,QAAQ,GAAGD,OAAO;IACvB,IAAI,CAACG,MAAM,GAAGD,KAAK;EACrB;EAEOI,QAAQA,CAAA,EAAW;IACxB,IAAIC,MAAM,GAAG,IAAI,IAAI,CAACT,IAAI,MAAM,IAAI,CAACE,OAAO,EAAE;IAC9C,OAAOO,MAAM;EACf;AACF;AAEA,OAAO,MAAMC,mBAAmB,SAASZ,UAAU,CAAiB;AAEpE,OAAO,MAAMa,iBAAiB,SAASb,UAAU,CAE/C;;AAEF;AACA;AACA;AACA,MAAMc,iBAAiB,GACrBV,OAAe,IAC8B;EAC7C;EACA,MAAMW,KAAK,GAAG,0BAA0B;EACxC,MAAMC,KAAK,GAAGZ,OAAO,CAACY,KAAK,CAACD,KAAK,CAAC;EAElC,IACEC,KAAK,IACLA,KAAK,CAACC,MAAM,KAAK,CAAC,IAClB,OAAOD,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAC5B,OAAOA,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAC5B;IACA,OAAO;MACLd,IAAI,EAAEc,KAAK,CAAC,CAAC,CAAC;MACdZ,OAAO,EAAEY,KAAK,CAAC,CAAC;IAClB,CAAC;EACH;EACA,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,MAAME,kBAAkB,GAAIC,KAAa,IAAK;EAC5C,IAAI,OAAO,IAAIA,KAAK,IAAI,OAAOA,KAAK,CAACb,KAAK,KAAK,QAAQ,EAAE;IACvD,MAAMA,KAAK,GAAGa,KAAK,CAACb,KAAK;;IAEzB;IACA,MAAMS,KAAK,GAAG,0BAA0B;IACxC,MAAMC,KAAK,GAAGV,KAAK,CAACU,KAAK,CAACD,KAAK,CAAC;IAEhC,IACEC,KAAK,IACLA,KAAK,CAACC,MAAM,KAAK,CAAC,IAClB,OAAOD,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAC5B,OAAOA,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAC5B;MACAG,KAAK,CAACb,KAAK,GAAGa,KAAK,CAACb,KAAK,CAACc,OAAO,CAACL,KAAK,EAAE,IAAIC,KAAK,CAAC,CAAC,CAAC,MAAMA,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE;EACF;AACF,CAAC;AAED,MAAMK,YAAY,GAChBF,KAAc,IAEd,OAAOA,KAAK,KAAK,QAAQ,IACzBA,KAAK,IAAI,IAAI;AACb;AACA,OAAOA,KAAK,CAACf,OAAO,KAAK,QAAQ;AACjC;AACAU,iBAAiB,CAACK,KAAK,CAACf,OAAO,CAAC,IAAI,IAAI;AAE1C,MAAMkB,QAAQ,GAAIH,KAAc,IAC9B,OAAOA,KAAK,KAAK,QAAQ,IACzBA,KAAK,IAAI,IAAI,IACb,OAAO,IAAIA,KAAK,IAChB,OAAOA,KAAK,CAACb,KAAK,KAAK,QAAQ;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMiB,wBAAwB,GACnCC,WAAc,IACoC;EAClD,IAAIH,YAAY,CAACG,WAAW,CAAC,EAAE;IAC7B,MAAMC,MAAM,GAAGX,iBAAiB,CAACU,WAAW,CAACpB,OAAO,CAAC;IAErD,IAAIqB,MAAM,IAAI,IAAI,EAAE;MAClB,OAAOD,WAAW;IACpB;IAEA,MAAM;MAAEtB,IAAI;MAAEE;IAAQ,CAAC,GAAGqB,MAAM;IAEhCP,kBAAkB,CAACM,WAAW,CAAC;IAE/B,IAAItB,IAAI,CAACwB,UAAU,CAAC,MAAM,CAAC,EAAE;MAC3B,OAAO,IAAId,mBAAmB,CAC5BV,IAAI,EACJE,OAAO,EACPkB,QAAQ,CAACE,WAAW,CAAC,GAAGA,WAAW,CAAClB,KAAK,GAAGqB,SAC9C,CAAC;IACH;IAEA,OAAO,IAAId,iBAAiB;IAC1B;IACAX,IAAI,EACJE,OAAO,EACPkB,QAAQ,CAACE,WAAW,CAAC,GAAGA,WAAW,CAAClB,KAAK,GAAGqB,SAC9C,CAAC;EACH;EAEA,OAAOH,WAAW;AACpB,CAAC","ignoreList":[]} diff --git a/lib/module/core/types/VideoInformation.js b/lib/module/core/types/VideoInformation.js new file mode 100644 index 00000000..a7a04640 --- /dev/null +++ b/lib/module/core/types/VideoInformation.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoInformation.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoInformation.js.map b/lib/module/core/types/VideoInformation.js.map new file mode 100644 index 00000000..8c9c9dcf --- /dev/null +++ b/lib/module/core/types/VideoInformation.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoInformation.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoOrientation.js b/lib/module/core/types/VideoOrientation.js new file mode 100644 index 00000000..494f91d8 --- /dev/null +++ b/lib/module/core/types/VideoOrientation.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=VideoOrientation.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoOrientation.js.map b/lib/module/core/types/VideoOrientation.js.map new file mode 100644 index 00000000..e2ddd0b6 --- /dev/null +++ b/lib/module/core/types/VideoOrientation.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoOrientation.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoPlayerBase.js b/lib/module/core/types/VideoPlayerBase.js new file mode 100644 index 00000000..c93e47e6 --- /dev/null +++ b/lib/module/core/types/VideoPlayerBase.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoPlayerBase.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoPlayerBase.js.map b/lib/module/core/types/VideoPlayerBase.js.map new file mode 100644 index 00000000..b84fa188 --- /dev/null +++ b/lib/module/core/types/VideoPlayerBase.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerBase.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoPlayerSourceBase.js b/lib/module/core/types/VideoPlayerSourceBase.js new file mode 100644 index 00000000..10164c8d --- /dev/null +++ b/lib/module/core/types/VideoPlayerSourceBase.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoPlayerSourceBase.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoPlayerSourceBase.js.map b/lib/module/core/types/VideoPlayerSourceBase.js.map new file mode 100644 index 00000000..405a67e8 --- /dev/null +++ b/lib/module/core/types/VideoPlayerSourceBase.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerSourceBase.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/types/VideoPlayerStatus.js b/lib/module/core/types/VideoPlayerStatus.js new file mode 100644 index 00000000..4bea2aef --- /dev/null +++ b/lib/module/core/types/VideoPlayerStatus.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=VideoPlayerStatus.js.map \ No newline at end of file diff --git a/lib/module/core/types/VideoPlayerStatus.js.map b/lib/module/core/types/VideoPlayerStatus.js.map new file mode 100644 index 00000000..26429e64 --- /dev/null +++ b/lib/module/core/types/VideoPlayerStatus.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/types/VideoPlayerStatus.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/core/utils/playerFactory.js b/lib/module/core/utils/playerFactory.js new file mode 100644 index 00000000..7c80a0eb --- /dev/null +++ b/lib/module/core/utils/playerFactory.js @@ -0,0 +1,26 @@ +"use strict"; + +import { NitroModules } from 'react-native-nitro-modules'; +import { createSource } from "./sourceFactory.js"; +import { tryParseNativeVideoError } from "../types/VideoError.js"; +import { isVideoPlayerSource } from "./sourceUtils.js"; +const VideoPlayerFactory = NitroModules.createHybridObject('VideoPlayerFactory'); + +/** + * @internal + * Creates a Native VideoPlayer instance. + * + * @param source - The source of the video to play + * @returns The Native VideoPlayer instance + */ +export const createPlayer = source => { + try { + if (isVideoPlayerSource(source)) { + return VideoPlayerFactory.createPlayer(source); + } + return VideoPlayerFactory.createPlayer(createSource(source)); + } catch (error) { + throw tryParseNativeVideoError(error); + } +}; +//# sourceMappingURL=playerFactory.js.map \ No newline at end of file diff --git a/lib/module/core/utils/playerFactory.js.map b/lib/module/core/utils/playerFactory.js.map new file mode 100644 index 00000000..1848e380 --- /dev/null +++ b/lib/module/core/utils/playerFactory.js.map @@ -0,0 +1 @@ +{"version":3,"names":["NitroModules","createSource","tryParseNativeVideoError","isVideoPlayerSource","VideoPlayerFactory","createHybridObject","createPlayer","source","error"],"sourceRoot":"../../../../src","sources":["core/utils/playerFactory.ts"],"mappings":";;AAAA,SAASA,YAAY,QAAQ,4BAA4B;AAOzD,SAASC,YAAY,QAAQ,oBAAiB;AAC9C,SAASC,wBAAwB,QAAQ,wBAAqB;AAC9D,SAASC,mBAAmB,QAAQ,kBAAe;AAEnD,MAAMC,kBAAkB,GACtBJ,YAAY,CAACK,kBAAkB,CAAqB,oBAAoB,CAAC;;AAE3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,YAAY,GACvBC,MAAqD,IACrC;EAChB,IAAI;IACF,IAAIJ,mBAAmB,CAACI,MAAM,CAAC,EAAE;MAC/B,OAAOH,kBAAkB,CAACE,YAAY,CAACC,MAAM,CAAC;IAChD;IAEA,OAAOH,kBAAkB,CAACE,YAAY,CAACL,YAAY,CAACM,MAAM,CAAC,CAAC;EAC9D,CAAC,CAAC,OAAOC,KAAK,EAAE;IACd,MAAMN,wBAAwB,CAACM,KAAK,CAAC;EACvC;AACF,CAAC","ignoreList":[]} diff --git a/lib/module/core/utils/sourceFactory.js b/lib/module/core/utils/sourceFactory.js new file mode 100644 index 00000000..45ba6f1c --- /dev/null +++ b/lib/module/core/utils/sourceFactory.js @@ -0,0 +1,115 @@ +"use strict"; + +import { Image, Platform } from 'react-native'; +import { NitroModules } from 'react-native-nitro-modules'; +import { tryParseNativeVideoError } from "../types/VideoError.js"; +import { isVideoPlayerSource } from "./sourceUtils.js"; +const VideoPlayerSourceFactory = NitroModules.createHybridObject('VideoPlayerSourceFactory'); + +/** + * Creates a `VideoPlayerSource` instance from a URI (string). + * + * @param uri - The URI of the video to play + * @returns The `VideoPlayerSource` instance + */ +export const createSourceFromUri = uri => { + try { + return VideoPlayerSourceFactory.fromUri(uri); + } catch (error) { + throw tryParseNativeVideoError(error); + } +}; + +/** + * Creates a `VideoPlayerSource` instance from a `VideoConfig`. + * + * @note The `uri` property is required to be a string. + * + * @param config - The `VideoConfig` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export const createSourceFromVideoConfig = config => { + if (config.externalSubtitles) { + config.externalSubtitles = parseExternalSubtitles(config.externalSubtitles); + } + + // Ensure platform-based default for DRM type if DRM is provided without a type + if (config.drm && config.drm.type === undefined) { + const defaultDrmType = Platform.select({ + android: 'widevine', + ios: 'fairplay', + default: undefined + }); + if (defaultDrmType) { + config.drm = { + ...config.drm, + type: defaultDrmType + }; + } + } + + // Set default value for initializeOnCreation (true) + if (config.initializeOnCreation === undefined) { + config.initializeOnCreation = true; + } + try { + return VideoPlayerSourceFactory.fromVideoConfig(config); + } catch (error) { + throw tryParseNativeVideoError(error); + } +}; + +/** + * Parses the external subtitles from the `ExternalSubtitle` to the `NativeExternalSubtitle` format. + * + * @param externalSubtitles - The external subtitles to parse + * @returns The parsed external subtitles + */ +const parseExternalSubtitles = externalSubtitles => { + return externalSubtitles.map(subtitle => ({ + uri: subtitle.uri, + label: subtitle.label, + type: subtitle.type ?? 'auto', + language: subtitle.language ?? 'und' + })); +}; + +/** + * Creates a `VideoPlayerSource` + * + * @param source - The `VideoSource` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export const createSource = source => { + // If source is a VideoPlayerSource, we can directly return it + if (isVideoPlayerSource(source)) { + return source; + } + + // If source is a string, we can directly create the player + if (typeof source === 'string') { + return createSourceFromUri(source); + } + + // If source is a number (asset), we need to resolve the asset source and create the player + if (typeof source === 'number') { + return createSourceFromUri(Image.resolveAssetSource(source).uri); + } + + // If source is an object (VideoConfig) + if (typeof source === 'object' && 'uri' in source) { + if (typeof source.uri === 'string') { + return createSourceFromVideoConfig(source); + } + if (typeof source.uri === 'number') { + const config = { + ...source, + // Resolve the asset source to get the URI + uri: Image.resolveAssetSource(source.uri).uri + }; + return createSourceFromVideoConfig(config); + } + } + throw new Error('RNV: Invalid source type'); +}; +//# sourceMappingURL=sourceFactory.js.map \ No newline at end of file diff --git a/lib/module/core/utils/sourceFactory.js.map b/lib/module/core/utils/sourceFactory.js.map new file mode 100644 index 00000000..493f92c5 --- /dev/null +++ b/lib/module/core/utils/sourceFactory.js.map @@ -0,0 +1 @@ +{"version":3,"names":["Image","Platform","NitroModules","tryParseNativeVideoError","isVideoPlayerSource","VideoPlayerSourceFactory","createHybridObject","createSourceFromUri","uri","fromUri","error","createSourceFromVideoConfig","config","externalSubtitles","parseExternalSubtitles","drm","type","undefined","defaultDrmType","select","android","ios","default","initializeOnCreation","fromVideoConfig","map","subtitle","label","language","createSource","source","resolveAssetSource","Error"],"sourceRoot":"../../../../src","sources":["core/utils/sourceFactory.ts"],"mappings":";;AAAA,SAASA,KAAK,EAAEC,QAAQ,QAAQ,cAAc;AAC9C,SAASC,YAAY,QAAQ,4BAA4B;AAYzD,SAASC,wBAAwB,QAAQ,wBAAqB;AAC9D,SAASC,mBAAmB,QAAQ,kBAAe;AAEnD,MAAMC,wBAAwB,GAC5BH,YAAY,CAACI,kBAAkB,CAC7B,0BACF,CAAC;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,mBAAmB,GAAIC,GAAW,IAAK;EAClD,IAAI;IACF,OAAOH,wBAAwB,CAACI,OAAO,CAACD,GAAG,CAAC;EAC9C,CAAC,CAAC,OAAOE,KAAK,EAAE;IACd,MAAMP,wBAAwB,CAACO,KAAK,CAAC;EACvC;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,2BAA2B,GACtCC,MAAqC,IAClC;EACH,IAAIA,MAAM,CAACC,iBAAiB,EAAE;IAC5BD,MAAM,CAACC,iBAAiB,GAAGC,sBAAsB,CAACF,MAAM,CAACC,iBAAiB,CAAC;EAC7E;;EAEA;EACA,IAAID,MAAM,CAACG,GAAG,IAAIH,MAAM,CAACG,GAAG,CAACC,IAAI,KAAKC,SAAS,EAAE;IAC/C,MAAMC,cAAc,GAAGjB,QAAQ,CAACkB,MAAM,CAAC;MACrCC,OAAO,EAAE,UAAU;MACnBC,GAAG,EAAE,UAAU;MACfC,OAAO,EAAEL;IACX,CAAC,CAAC;IAEF,IAAIC,cAAc,EAAE;MAClBN,MAAM,CAACG,GAAG,GAAG;QACX,GAAGH,MAAM,CAACG,GAAG;QACbC,IAAI,EAAEE;MACR,CAAC;IACH;EACF;;EAEA;EACA,IAAIN,MAAM,CAACW,oBAAoB,KAAKN,SAAS,EAAE;IAC7CL,MAAM,CAACW,oBAAoB,GAAG,IAAI;EACpC;EAEA,IAAI;IACF,OAAOlB,wBAAwB,CAACmB,eAAe,CAC7CZ,MACF,CAAC;EACH,CAAC,CAAC,OAAOF,KAAK,EAAE;IACd,MAAMP,wBAAwB,CAACO,KAAK,CAAC;EACvC;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,MAAMI,sBAAsB,GAC1BD,iBAAqC,IACM;EAC3C,OAAOA,iBAAiB,CAACY,GAAG,CAAEC,QAAQ,KAAM;IAC1ClB,GAAG,EAAEkB,QAAQ,CAAClB,GAAG;IACjBmB,KAAK,EAAED,QAAQ,CAACC,KAAK;IACrBX,IAAI,EAAGU,QAAQ,CAACV,IAAI,IAAI,MAAuB;IAC/CY,QAAQ,EAAEF,QAAQ,CAACE,QAAQ,IAAI;EACjC,CAAC,CAAC,CAAC;AACL,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,YAAY,GACvBC,MAAqD,IAC/B;EACtB;EACA,IAAI1B,mBAAmB,CAAC0B,MAAM,CAAC,EAAE;IAC/B,OAAOA,MAAM;EACf;;EAEA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IAC9B,OAAOvB,mBAAmB,CAACuB,MAAM,CAAC;EACpC;;EAEA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IAC9B,OAAOvB,mBAAmB,CAACP,KAAK,CAAC+B,kBAAkB,CAACD,MAAM,CAAC,CAACtB,GAAG,CAAC;EAClE;;EAEA;EACA,IAAI,OAAOsB,MAAM,KAAK,QAAQ,IAAI,KAAK,IAAIA,MAAM,EAAE;IACjD,IAAI,OAAOA,MAAM,CAACtB,GAAG,KAAK,QAAQ,EAAE;MAClC,OAAOG,2BAA2B,CAChCmB,MACF,CAAC;IACH;IAEA,IAAI,OAAOA,MAAM,CAACtB,GAAG,KAAK,QAAQ,EAAE;MAClC,MAAMI,MAAM,GAAG;QACb,GAAGkB,MAAM;QACT;QACAtB,GAAG,EAAER,KAAK,CAAC+B,kBAAkB,CAACD,MAAM,CAACtB,GAAG,CAAC,CAACA;MAC5C,CAAC;MAED,OAAOG,2BAA2B,CAACC,MAAM,CAAC;IAC5C;EACF;EAEA,MAAM,IAAIoB,KAAK,CAAC,0BAA0B,CAAC;AAC7C,CAAC","ignoreList":[]} diff --git a/lib/module/core/utils/sourceUtils.js b/lib/module/core/utils/sourceUtils.js new file mode 100644 index 00000000..6aa34852 --- /dev/null +++ b/lib/module/core/utils/sourceUtils.js @@ -0,0 +1,13 @@ +"use strict"; + +export const isVideoPlayerSource = obj => { + return obj && + // obj is not null + typeof obj === 'object' && + // obj is an object + 'name' in obj && + // obj has a name property + obj.name === 'VideoPlayerSource' // obj.name is 'VideoPlayerSource' + ; +}; +//# sourceMappingURL=sourceUtils.js.map \ No newline at end of file diff --git a/lib/module/core/utils/sourceUtils.js.map b/lib/module/core/utils/sourceUtils.js.map new file mode 100644 index 00000000..80267168 --- /dev/null +++ b/lib/module/core/utils/sourceUtils.js.map @@ -0,0 +1 @@ +{"version":3,"names":["isVideoPlayerSource","obj","name"],"sourceRoot":"../../../../src","sources":["core/utils/sourceUtils.ts"],"mappings":";;AAEA,OAAO,MAAMA,mBAAmB,GAAIC,GAAQ,IAA+B;EACzE,OACEA,GAAG;EAAI;EACP,OAAOA,GAAG,KAAK,QAAQ;EAAI;EAC3B,MAAM,IAAIA,GAAG;EAAI;EACjBA,GAAG,CAACC,IAAI,KAAK,mBAAmB,CAAC;EAAA;AAErC,CAAC","ignoreList":[]} diff --git a/lib/module/core/video-view/NativeVideoView.js b/lib/module/core/video-view/NativeVideoView.js new file mode 100644 index 00000000..ab64d851 --- /dev/null +++ b/lib/module/core/video-view/NativeVideoView.js @@ -0,0 +1,13 @@ +"use strict"; + +import { Platform, UIManager } from 'react-native'; +import VideoViewNativeComponent from '../../spec/fabric/VideoViewNativeComponent'; +const LINKING_ERROR = `The package 'react-native-video' doesn't seem to be linked. Make sure: \n\n` + Platform.select({ + ios: "- You have run 'pod install'\n", + default: '' +}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n'; +const ComponentName = 'VideoView'; +export const NativeVideoView = UIManager.hasViewManagerConfig(ComponentName) != null ? VideoViewNativeComponent : () => { + throw new Error(LINKING_ERROR); +}; +//# sourceMappingURL=NativeVideoView.js.map \ No newline at end of file diff --git a/lib/module/core/video-view/NativeVideoView.js.map b/lib/module/core/video-view/NativeVideoView.js.map new file mode 100644 index 00000000..3424bc49 --- /dev/null +++ b/lib/module/core/video-view/NativeVideoView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["Platform","UIManager","VideoViewNativeComponent","LINKING_ERROR","select","ios","default","ComponentName","NativeVideoView","hasViewManagerConfig","Error"],"sourceRoot":"../../../../src","sources":["core/video-view/NativeVideoView.tsx"],"mappings":";;AAAA,SAASA,QAAQ,EAAEC,SAAS,QAAQ,cAAc;AAElD,OAAOC,wBAAwB,MAAM,4CAA4C;AAEjF,MAAMC,aAAa,GACjB,6EAA6E,GAC7EH,QAAQ,CAACI,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,aAAa,GAAG,WAAW;AAEjC,OAAO,MAAMC,eAAe,GAC1BP,SAAS,CAACQ,oBAAoB,CAACF,aAAa,CAAC,IAAI,IAAI,GACjDL,wBAAwB,GACxB,MAAM;EACJ,MAAM,IAAIQ,KAAK,CAACP,aAAa,CAAC;AAChC,CAAC","ignoreList":[]} diff --git a/lib/module/core/video-view/VideoView.js b/lib/module/core/video-view/VideoView.js new file mode 100644 index 00000000..3c2a7068 --- /dev/null +++ b/lib/module/core/video-view/VideoView.js @@ -0,0 +1,134 @@ +"use strict"; + +import * as React from 'react'; +import { NitroModules } from 'react-native-nitro-modules'; +import { tryParseNativeVideoError, VideoError } from "../types/VideoError.js"; +import { NativeVideoView } from "./NativeVideoView.js"; +import { jsx as _jsx } from "react/jsx-runtime"; +let nitroIdCounter = 1; +const VideoViewViewManagerFactory = NitroModules.createHybridObject('VideoViewViewManagerFactory'); +const wrapNativeViewManagerFunction = (manager, func) => { + try { + if (manager === null) { + throw new VideoError('view/not-found', 'View manager not found'); + } + return func(manager); + } catch (error) { + throw tryParseNativeVideoError(error); + } +}; +const updateProps = (manager, props) => { + manager.player = props.player.__getNativePlayer(); + manager.controls = props.controls ?? false; + manager.pictureInPicture = props.pictureInPicture ?? false; + manager.autoEnterPictureInPicture = props.autoEnterPictureInPicture ?? false; + manager.resizeMode = props.resizeMode ?? 'none'; + manager.onPictureInPictureChange = props.onPictureInPictureChange; + manager.onFullscreenChange = props.onFullscreenChange; + manager.willEnterFullscreen = props.willEnterFullscreen; + manager.willExitFullscreen = props.willExitFullscreen; + manager.willEnterPictureInPicture = props.willEnterPictureInPicture; + manager.willExitPictureInPicture = props.willExitPictureInPicture; + manager.keepScreenAwake = props.keepScreenAwake ?? true; + manager.surfaceType = props.surfaceType ?? 'surface'; +}; + +/** + * VideoView is a component that allows you to display a video from a {@link VideoPlayer}. + * + * @param player - The player to play the video - {@link VideoPlayer} + * @param controls - Whether to show the controls. Defaults to false. + * @param style - The style of the video view - {@link ViewStyle} + * @param pictureInPicture - Whether to show the picture in picture button. Defaults to false. + * @param autoEnterPictureInPicture - Whether to automatically enter picture in picture mode + * when the video is playing. Defaults to false. + * @param resizeMode - How the video should be resized to fit the view. Defaults to 'none'. + */ +const VideoView = /*#__PURE__*/React.forwardRef(({ + player, + controls = false, + pictureInPicture = false, + autoEnterPictureInPicture = false, + resizeMode = 'none', + ...props +}, ref) => { + const nitroId = React.useMemo(() => nitroIdCounter++, []); + const nitroViewManager = React.useRef(null); + const setupViewManager = React.useCallback(id => { + try { + if (nitroViewManager.current === null) { + nitroViewManager.current = VideoViewViewManagerFactory.createViewManager(id); + + // Should never happen + if (!nitroViewManager.current) { + throw new VideoError('view/not-found', 'Failed to create View Manager'); + } + } + + // Updates props to native view + updateProps(nitroViewManager.current, { + ...props, + player: player, + controls: controls, + pictureInPicture: pictureInPicture, + autoEnterPictureInPicture: autoEnterPictureInPicture, + resizeMode: resizeMode + }); + } catch (error) { + throw tryParseNativeVideoError(error); + } + }, [props, player, controls, pictureInPicture, autoEnterPictureInPicture, resizeMode]); + const onNitroIdChange = React.useCallback(event => { + setupViewManager(event.nativeEvent.nitroId); + }, [setupViewManager]); + React.useImperativeHandle(ref, () => ({ + enterFullscreen: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.enterFullscreen(); + }); + }, + exitFullscreen: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.exitFullscreen(); + }); + }, + enterPictureInPicture: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.enterPictureInPicture(); + }); + }, + exitPictureInPicture: () => { + wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + manager.exitPictureInPicture(); + }); + }, + canEnterPictureInPicture: () => { + return wrapNativeViewManagerFunction(nitroViewManager.current, manager => { + return manager.canEnterPictureInPicture(); + }); + } + }), []); + React.useEffect(() => { + if (!nitroViewManager.current) { + return; + } + + // Updates props to native view + updateProps(nitroViewManager.current, { + ...props, + player: player, + controls: controls, + pictureInPicture: pictureInPicture, + autoEnterPictureInPicture: autoEnterPictureInPicture, + resizeMode: resizeMode + }); + }, [player, controls, pictureInPicture, autoEnterPictureInPicture, resizeMode, props]); + return /*#__PURE__*/_jsx(NativeVideoView, { + nitroId: nitroId, + onNitroIdChange: onNitroIdChange, + ...props + }); +}); +VideoView.displayName = 'VideoView'; +export default /*#__PURE__*/React.memo(VideoView); +//# sourceMappingURL=VideoView.js.map \ No newline at end of file diff --git a/lib/module/core/video-view/VideoView.js.map b/lib/module/core/video-view/VideoView.js.map new file mode 100644 index 00000000..4cfe57c1 --- /dev/null +++ b/lib/module/core/video-view/VideoView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["React","NitroModules","tryParseNativeVideoError","VideoError","NativeVideoView","jsx","_jsx","nitroIdCounter","VideoViewViewManagerFactory","createHybridObject","wrapNativeViewManagerFunction","manager","func","error","updateProps","props","player","__getNativePlayer","controls","pictureInPicture","autoEnterPictureInPicture","resizeMode","onPictureInPictureChange","onFullscreenChange","willEnterFullscreen","willExitFullscreen","willEnterPictureInPicture","willExitPictureInPicture","keepScreenAwake","surfaceType","VideoView","forwardRef","ref","nitroId","useMemo","nitroViewManager","useRef","setupViewManager","useCallback","id","current","createViewManager","onNitroIdChange","event","nativeEvent","useImperativeHandle","enterFullscreen","exitFullscreen","enterPictureInPicture","exitPictureInPicture","canEnterPictureInPicture","useEffect","displayName","memo"],"sourceRoot":"../../../../src","sources":["core/video-view/VideoView.tsx"],"mappings":";;AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAASC,YAAY,QAAQ,4BAA4B;AAKzD,SAASC,wBAAwB,EAAEC,UAAU,QAAQ,wBAAqB;AAE1E,SAASC,eAAe,QAAQ,sBAAmB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAGpD,IAAIC,cAAc,GAAG,CAAC;AACtB,MAAMC,2BAA2B,GAC/BP,YAAY,CAACQ,kBAAkB,CAC7B,6BACF,CAAC;AAEH,MAAMC,6BAA6B,GAAGA,CACpCC,OAAoC,EACpCC,IAA0C,KACvC;EACH,IAAI;IACF,IAAID,OAAO,KAAK,IAAI,EAAE;MACpB,MAAM,IAAIR,UAAU,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;IAClE;IAEA,OAAOS,IAAI,CAACD,OAAO,CAAC;EACtB,CAAC,CAAC,OAAOE,KAAK,EAAE;IACd,MAAMX,wBAAwB,CAACW,KAAK,CAAC;EACvC;AACF,CAAC;AAED,MAAMC,WAAW,GAAGA,CAACH,OAA6B,EAAEI,KAAqB,KAAK;EAC5EJ,OAAO,CAACK,MAAM,GAAGD,KAAK,CAACC,MAAM,CAACC,iBAAiB,CAAC,CAAC;EACjDN,OAAO,CAACO,QAAQ,GAAGH,KAAK,CAACG,QAAQ,IAAI,KAAK;EAC1CP,OAAO,CAACQ,gBAAgB,GAAGJ,KAAK,CAACI,gBAAgB,IAAI,KAAK;EAC1DR,OAAO,CAACS,yBAAyB,GAAGL,KAAK,CAACK,yBAAyB,IAAI,KAAK;EAC5ET,OAAO,CAACU,UAAU,GAAGN,KAAK,CAACM,UAAU,IAAI,MAAM;EAC/CV,OAAO,CAACW,wBAAwB,GAAGP,KAAK,CAACO,wBAAwB;EACjEX,OAAO,CAACY,kBAAkB,GAAGR,KAAK,CAACQ,kBAAkB;EACrDZ,OAAO,CAACa,mBAAmB,GAAGT,KAAK,CAACS,mBAAmB;EACvDb,OAAO,CAACc,kBAAkB,GAAGV,KAAK,CAACU,kBAAkB;EACrDd,OAAO,CAACe,yBAAyB,GAAGX,KAAK,CAACW,yBAAyB;EACnEf,OAAO,CAACgB,wBAAwB,GAAGZ,KAAK,CAACY,wBAAwB;EACjEhB,OAAO,CAACiB,eAAe,GAAGb,KAAK,CAACa,eAAe,IAAI,IAAI;EACvDjB,OAAO,CAACkB,WAAW,GAAGd,KAAK,CAACc,WAAW,IAAI,SAAS;AACtD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,SAAS,gBAAG9B,KAAK,CAAC+B,UAAU,CAChC,CACE;EACEf,MAAM;EACNE,QAAQ,GAAG,KAAK;EAChBC,gBAAgB,GAAG,KAAK;EACxBC,yBAAyB,GAAG,KAAK;EACjCC,UAAU,GAAG,MAAM;EACnB,GAAGN;AACL,CAAC,EACDiB,GAAG,KACA;EACH,MAAMC,OAAO,GAAGjC,KAAK,CAACkC,OAAO,CAAC,MAAM3B,cAAc,EAAE,EAAE,EAAE,CAAC;EACzD,MAAM4B,gBAAgB,GAAGnC,KAAK,CAACoC,MAAM,CAA8B,IAAI,CAAC;EAExE,MAAMC,gBAAgB,GAAGrC,KAAK,CAACsC,WAAW,CACvCC,EAAU,IAAK;IACd,IAAI;MACF,IAAIJ,gBAAgB,CAACK,OAAO,KAAK,IAAI,EAAE;QACrCL,gBAAgB,CAACK,OAAO,GACtBhC,2BAA2B,CAACiC,iBAAiB,CAACF,EAAE,CAAC;;QAEnD;QACA,IAAI,CAACJ,gBAAgB,CAACK,OAAO,EAAE;UAC7B,MAAM,IAAIrC,UAAU,CAClB,gBAAgB,EAChB,+BACF,CAAC;QACH;MACF;;MAEA;MACAW,WAAW,CAACqB,gBAAgB,CAACK,OAAO,EAAE;QACpC,GAAGzB,KAAK;QACRC,MAAM,EAAEA,MAAM;QACdE,QAAQ,EAAEA,QAAQ;QAClBC,gBAAgB,EAAEA,gBAAgB;QAClCC,yBAAyB,EAAEA,yBAAyB;QACpDC,UAAU,EAAEA;MACd,CAAC,CAAC;IACJ,CAAC,CAAC,OAAOR,KAAK,EAAE;MACd,MAAMX,wBAAwB,CAACW,KAAK,CAAC;IACvC;EACF,CAAC,EACD,CACEE,KAAK,EACLC,MAAM,EACNE,QAAQ,EACRC,gBAAgB,EAChBC,yBAAyB,EACzBC,UAAU,CAEd,CAAC;EAED,MAAMqB,eAAe,GAAG1C,KAAK,CAACsC,WAAW,CACtCK,KAA2C,IAAK;IAC/CN,gBAAgB,CAACM,KAAK,CAACC,WAAW,CAACX,OAAO,CAAC;EAC7C,CAAC,EACD,CAACI,gBAAgB,CACnB,CAAC;EAEDrC,KAAK,CAAC6C,mBAAmB,CACvBb,GAAG,EACH,OAAO;IACLc,eAAe,EAAEA,CAAA,KAAM;MACrBpC,6BAA6B,CAACyB,gBAAgB,CAACK,OAAO,EAAG7B,OAAO,IAAK;QACnEA,OAAO,CAACmC,eAAe,CAAC,CAAC;MAC3B,CAAC,CAAC;IACJ,CAAC;IACDC,cAAc,EAAEA,CAAA,KAAM;MACpBrC,6BAA6B,CAACyB,gBAAgB,CAACK,OAAO,EAAG7B,OAAO,IAAK;QACnEA,OAAO,CAACoC,cAAc,CAAC,CAAC;MAC1B,CAAC,CAAC;IACJ,CAAC;IACDC,qBAAqB,EAAEA,CAAA,KAAM;MAC3BtC,6BAA6B,CAACyB,gBAAgB,CAACK,OAAO,EAAG7B,OAAO,IAAK;QACnEA,OAAO,CAACqC,qBAAqB,CAAC,CAAC;MACjC,CAAC,CAAC;IACJ,CAAC;IACDC,oBAAoB,EAAEA,CAAA,KAAM;MAC1BvC,6BAA6B,CAACyB,gBAAgB,CAACK,OAAO,EAAG7B,OAAO,IAAK;QACnEA,OAAO,CAACsC,oBAAoB,CAAC,CAAC;MAChC,CAAC,CAAC;IACJ,CAAC;IACDC,wBAAwB,EAAEA,CAAA,KAAM;MAC9B,OAAOxC,6BAA6B,CAClCyB,gBAAgB,CAACK,OAAO,EACvB7B,OAAO,IAAK;QACX,OAAOA,OAAO,CAACuC,wBAAwB,CAAC,CAAC;MAC3C,CACF,CAAC;IACH;EACF,CAAC,CAAC,EACF,EACF,CAAC;EAEDlD,KAAK,CAACmD,SAAS,CAAC,MAAM;IACpB,IAAI,CAAChB,gBAAgB,CAACK,OAAO,EAAE;MAC7B;IACF;;IAEA;IACA1B,WAAW,CAACqB,gBAAgB,CAACK,OAAO,EAAE;MACpC,GAAGzB,KAAK;MACRC,MAAM,EAAEA,MAAM;MACdE,QAAQ,EAAEA,QAAQ;MAClBC,gBAAgB,EAAEA,gBAAgB;MAClCC,yBAAyB,EAAEA,yBAAyB;MACpDC,UAAU,EAAEA;IACd,CAAC,CAAC;EACJ,CAAC,EAAE,CACDL,MAAM,EACNE,QAAQ,EACRC,gBAAgB,EAChBC,yBAAyB,EACzBC,UAAU,EACVN,KAAK,CACN,CAAC;EAEF,oBACET,IAAA,CAACF,eAAe;IACd6B,OAAO,EAAEA,OAAQ;IACjBS,eAAe,EAAEA,eAAgB;IAAA,GAC7B3B;EAAK,CACV,CAAC;AAEN,CACF,CAAC;AAEDe,SAAS,CAACsB,WAAW,GAAG,WAAW;AAEnC,4BAAepD,KAAK,CAACqD,IAAI,CAACvB,SAAS,CAAC","ignoreList":[]} diff --git a/lib/module/core/video-view/VideoView.web.js b/lib/module/core/video-view/VideoView.web.js new file mode 100644 index 00000000..309e9784 --- /dev/null +++ b/lib/module/core/video-view/VideoView.web.js @@ -0,0 +1,68 @@ +"use strict"; + +import { forwardRef, memo, useEffect, useImperativeHandle, useRef } from "react"; +import { View } from "react-native"; +import { jsx as _jsx } from "react/jsx-runtime"; +/** + * VideoView is a component that allows you to display a video from a {@link VideoPlayer}. + * + * @param player - The player to play the video - {@link VideoPlayer} + * @param controls - Whether to show the controls. Defaults to false. + * @param style - The style of the video view - {@link ViewStyle} + * @param pictureInPicture - Whether to show the picture in picture button. Defaults to false. + * @param autoEnterPictureInPicture - Whether to automatically enter picture in picture mode + * when the video is playing. Defaults to false. + * @param resizeMode - How the video should be resized to fit the view. Defaults to 'none'. + */ +const VideoView = /*#__PURE__*/forwardRef(({ + player: nPlayer, + controls = false, + resizeMode = "none", + // auto pip is unsupported + pictureInPicture = false, + autoEnterPictureInPicture = false, + keepScreenAwake = true, + ...props +}, ref) => { + const player = nPlayer; + const vRef = useRef(null); + useEffect(() => { + const videoElement = player.__getNativeRef(); + vRef.current?.appendChild(videoElement); + return () => { + vRef.current?.removeChild(videoElement); + }; + }, [player]); + useImperativeHandle(ref, () => ({ + enterFullscreen: () => { + player.__getNativeRef().requestFullscreen({ + navigationUI: "hide" + }); + }, + exitFullscreen: () => { + document.exitFullscreen(); + }, + enterPictureInPicture: () => { + player.__getNativeRef().requestPictureInPicture(); + }, + exitPictureInPicture: () => { + document.exitPictureInPicture(); + }, + canEnterPictureInPicture: () => document.pictureInPictureEnabled + }), [player]); + useEffect(() => { + player.__getNativeRef().controls = controls; + }, [player, controls]); + return /*#__PURE__*/_jsx(View, { + ...props, + children: /*#__PURE__*/_jsx("div", { + ref: vRef, + style: { + objectFit: resizeMode === "stretch" ? "fill" : resizeMode + } + }) + }); +}); +VideoView.displayName = "VideoView"; +export default /*#__PURE__*/memo(VideoView); +//# sourceMappingURL=VideoView.web.js.map \ No newline at end of file diff --git a/lib/module/core/video-view/VideoView.web.js.map b/lib/module/core/video-view/VideoView.web.js.map new file mode 100644 index 00000000..4b177280 --- /dev/null +++ b/lib/module/core/video-view/VideoView.web.js.map @@ -0,0 +1 @@ +{"version":3,"names":["forwardRef","memo","useEffect","useImperativeHandle","useRef","View","jsx","_jsx","VideoView","player","nPlayer","controls","resizeMode","pictureInPicture","autoEnterPictureInPicture","keepScreenAwake","props","ref","vRef","videoElement","__getNativeRef","current","appendChild","removeChild","enterFullscreen","requestFullscreen","navigationUI","exitFullscreen","document","enterPictureInPicture","requestPictureInPicture","exitPictureInPicture","canEnterPictureInPicture","pictureInPictureEnabled","children","style","objectFit","displayName"],"sourceRoot":"../../../../src","sources":["core/video-view/VideoView.web.tsx"],"mappings":";;AAAA,SACEA,UAAU,EACVC,IAAI,EACJC,SAAS,EACTC,mBAAmB,EACnBC,MAAM,QACD,OAAO;AACd,SAASC,IAAI,QAAwB,cAAc;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAIpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,SAAS,gBAAGR,UAAU,CAC1B,CACE;EACES,MAAM,EAAEC,OAAO;EACfC,QAAQ,GAAG,KAAK;EAChBC,UAAU,GAAG,MAAM;EACnB;EACAC,gBAAgB,GAAG,KAAK;EACxBC,yBAAyB,GAAG,KAAK;EACjCC,eAAe,GAAG,IAAI;EACtB,GAAGC;AACL,CAAC,EACDC,GAAG,KACA;EACH,MAAMR,MAAM,GAAGC,OAAiC;EAChD,MAAMQ,IAAI,GAAGd,MAAM,CAAiB,IAAI,CAAC;EACzCF,SAAS,CAAC,MAAM;IACd,MAAMiB,YAAY,GAAGV,MAAM,CAACW,cAAc,CAAC,CAAC;IAC5CF,IAAI,CAACG,OAAO,EAAEC,WAAW,CAACH,YAAY,CAAC;IACvC,OAAO,MAAM;MACXD,IAAI,CAACG,OAAO,EAAEE,WAAW,CAACJ,YAAY,CAAC;IACzC,CAAC;EACH,CAAC,EAAE,CAACV,MAAM,CAAC,CAAC;EAEZN,mBAAmB,CACjBc,GAAG,EACH,OAAO;IACLO,eAAe,EAAEA,CAAA,KAAM;MACrBf,MAAM,CAACW,cAAc,CAAC,CAAC,CAACK,iBAAiB,CAAC;QAAEC,YAAY,EAAE;MAAO,CAAC,CAAC;IACrE,CAAC;IACDC,cAAc,EAAEA,CAAA,KAAM;MACpBC,QAAQ,CAACD,cAAc,CAAC,CAAC;IAC3B,CAAC;IACDE,qBAAqB,EAAEA,CAAA,KAAM;MAC3BpB,MAAM,CAACW,cAAc,CAAC,CAAC,CAACU,uBAAuB,CAAC,CAAC;IACnD,CAAC;IACDC,oBAAoB,EAAEA,CAAA,KAAM;MAC1BH,QAAQ,CAACG,oBAAoB,CAAC,CAAC;IACjC,CAAC;IACDC,wBAAwB,EAAEA,CAAA,KAAMJ,QAAQ,CAACK;EAC3C,CAAC,CAAC,EACF,CAACxB,MAAM,CACT,CAAC;EAEDP,SAAS,CAAC,MAAM;IACdO,MAAM,CAACW,cAAc,CAAC,CAAC,CAACT,QAAQ,GAAGA,QAAQ;EAC7C,CAAC,EAAE,CAACF,MAAM,EAAEE,QAAQ,CAAC,CAAC;EAEtB,oBACEJ,IAAA,CAACF,IAAI;IAAA,GAAKW,KAAK;IAAAkB,QAAA,eACb3B,IAAA;MACEU,GAAG,EAAEC,IAAK;MACViB,KAAK,EAAE;QAAEC,SAAS,EAAExB,UAAU,KAAK,SAAS,GAAG,MAAM,GAAGA;MAAW;IAAE,CACtE;EAAC,CACE,CAAC;AAEX,CACF,CAAC;AAEDJ,SAAS,CAAC6B,WAAW,GAAG,WAAW;AAEnC,4BAAepC,IAAI,CAACO,SAAS,CAAC","ignoreList":[]} diff --git a/lib/module/core/video-view/ViewViewProps.js b/lib/module/core/video-view/ViewViewProps.js new file mode 100644 index 00000000..9fb147b7 --- /dev/null +++ b/lib/module/core/video-view/ViewViewProps.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=ViewViewProps.js.map \ No newline at end of file diff --git a/lib/module/core/video-view/ViewViewProps.js.map b/lib/module/core/video-view/ViewViewProps.js.map new file mode 100644 index 00000000..77749fcc --- /dev/null +++ b/lib/module/core/video-view/ViewViewProps.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["core/video-view/ViewViewProps.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/expo-plugins/@types.js b/lib/module/expo-plugins/@types.js new file mode 100644 index 00000000..389ea6fe --- /dev/null +++ b/lib/module/expo-plugins/@types.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=@types.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/@types.js.map b/lib/module/expo-plugins/@types.js.map new file mode 100644 index 00000000..7c3cec95 --- /dev/null +++ b/lib/module/expo-plugins/@types.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../src","sources":["expo-plugins/@types.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/expo-plugins/getPackageInfo.js b/lib/module/expo-plugins/getPackageInfo.js new file mode 100644 index 00000000..d03477c0 --- /dev/null +++ b/lib/module/expo-plugins/getPackageInfo.js @@ -0,0 +1,23 @@ +"use strict"; + +export function getPackageInfo() { + // src/expo-plugins/getPackageInfo.ts + try { + const packageJson = require('../../package.json'); + return { + name: packageJson.name, + version: packageJson.version + }; + } catch (_) {} + + // lib/commonjs/expo-plugins/getPackageInfo.js + try { + const packageJson = require('../../../package.json'); + return { + name: packageJson.name, + version: packageJson.version + }; + } catch (_) {} + throw new Error('Failed to get (react-native-video) package info'); +} +//# sourceMappingURL=getPackageInfo.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/getPackageInfo.js.map b/lib/module/expo-plugins/getPackageInfo.js.map new file mode 100644 index 00000000..40bc36f6 --- /dev/null +++ b/lib/module/expo-plugins/getPackageInfo.js.map @@ -0,0 +1 @@ +{"version":3,"names":["getPackageInfo","packageJson","require","name","version","_","Error"],"sourceRoot":"../../../src","sources":["expo-plugins/getPackageInfo.ts"],"mappings":";;AAAA,OAAO,SAASA,cAAcA,CAAA,EAAsC;EAClE;EACA,IAAI;IACF,MAAMC,WAAW,GAAGC,OAAO,CAAC,oBAAoB,CAAC;IAEjD,OAAO;MACLC,IAAI,EAAEF,WAAW,CAACE,IAAI;MACtBC,OAAO,EAAEH,WAAW,CAACG;IACvB,CAAC;EACH,CAAC,CAAC,OAAOC,CAAC,EAAE,CAAC;;EAEb;EACA,IAAI;IACF,MAAMJ,WAAW,GAAGC,OAAO,CAAC,uBAAuB,CAAC;IAEpD,OAAO;MACLC,IAAI,EAAEF,WAAW,CAACE,IAAI;MACtBC,OAAO,EAAEH,WAAW,CAACG;IACvB,CAAC;EACH,CAAC,CAAC,OAAOC,CAAC,EAAE,CAAC;EAEb,MAAM,IAAIC,KAAK,CAAC,iDAAiD,CAAC;AACpE","ignoreList":[]} diff --git a/lib/module/expo-plugins/withAndroidExtensions.js b/lib/module/expo-plugins/withAndroidExtensions.js new file mode 100644 index 00000000..29ea6f0d --- /dev/null +++ b/lib/module/expo-plugins/withAndroidExtensions.js @@ -0,0 +1,35 @@ +"use strict"; + +import { withGradleProperties } from '@expo/config-plugins'; +/** + * Sets the Android extensions for ExoPlayer in `gradle.properties`. + * You can choose which extensions to include in order to reduce the size of the app. + */ +export const withAndroidExtensions = (c, androidExtensions) => { + const keys = ['RNVideo_useExoplayerDash', 'RNVideo_useExoplayerHls']; + if (!androidExtensions) { + androidExtensions = { + useExoplayerDash: true, + useExoplayerHls: true + }; + } + return withGradleProperties(c, config => { + config.modResults = config.modResults.filter(item => { + if (item.type === 'property' && keys.includes(item.key)) { + return false; + } + return true; + }); + for (const key of keys) { + const valueKey = key.replace('RNVideo_', ''); + const value = androidExtensions ? androidExtensions[valueKey] ?? false : false; + config.modResults.push({ + type: 'property', + key, + value: value.toString() + }); + } + return config; + }); +}; +//# sourceMappingURL=withAndroidExtensions.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/withAndroidExtensions.js.map b/lib/module/expo-plugins/withAndroidExtensions.js.map new file mode 100644 index 00000000..8e0c8cc5 --- /dev/null +++ b/lib/module/expo-plugins/withAndroidExtensions.js.map @@ -0,0 +1 @@ +{"version":3,"names":["withGradleProperties","withAndroidExtensions","c","androidExtensions","keys","useExoplayerDash","useExoplayerHls","config","modResults","filter","item","type","includes","key","valueKey","replace","value","push","toString"],"sourceRoot":"../../../src","sources":["expo-plugins/withAndroidExtensions.ts"],"mappings":";;AAAA,SAASA,oBAAoB,QAA2B,sBAAsB;AAG9E;AACA;AACA;AACA;AACA,OAAO,MAAMC,qBAEZ,GAAGA,CAACC,CAAC,EAAEC,iBAAiB,KAAK;EAC5B,MAAMC,IAAI,GAAG,CAAC,0BAA0B,EAAE,yBAAyB,CAAC;EAEpE,IAAI,CAACD,iBAAiB,EAAE;IACtBA,iBAAiB,GAAG;MAClBE,gBAAgB,EAAE,IAAI;MACtBC,eAAe,EAAE;IACnB,CAAC;EACH;EAEA,OAAON,oBAAoB,CAACE,CAAC,EAAGK,MAAM,IAAK;IACzCA,MAAM,CAACC,UAAU,GAAGD,MAAM,CAACC,UAAU,CAACC,MAAM,CAAEC,IAAI,IAAK;MACrD,IAAIA,IAAI,CAACC,IAAI,KAAK,UAAU,IAAIP,IAAI,CAACQ,QAAQ,CAACF,IAAI,CAACG,GAAG,CAAC,EAAE;QACvD,OAAO,KAAK;MACd;MACA,OAAO,IAAI;IACb,CAAC,CAAC;IAEF,KAAK,MAAMA,GAAG,IAAIT,IAAI,EAAE;MACtB,MAAMU,QAAQ,GAAGD,GAAG,CAACE,OAAO,CAC1B,UAAU,EACV,EACF,CAAmC;MACnC,MAAMC,KAAK,GAAGb,iBAAiB,GAC1BA,iBAAiB,CAACW,QAAQ,CAAC,IAAI,KAAK,GACrC,KAAK;MAETP,MAAM,CAACC,UAAU,CAACS,IAAI,CAAC;QACrBN,IAAI,EAAE,UAAU;QAChBE,GAAG;QACHG,KAAK,EAAEA,KAAK,CAACE,QAAQ,CAAC;MACxB,CAAC,CAAC;IACJ;IAEA,OAAOX,MAAM;EACf,CAAC,CAAC;AACJ,CAAC","ignoreList":[]} diff --git a/lib/module/expo-plugins/withAndroidPictureInPicture.js b/lib/module/expo-plugins/withAndroidPictureInPicture.js new file mode 100644 index 00000000..ce25b702 --- /dev/null +++ b/lib/module/expo-plugins/withAndroidPictureInPicture.js @@ -0,0 +1,18 @@ +"use strict"; + +import { AndroidConfig, withAndroidManifest } from '@expo/config-plugins'; +export const withAndroidPictureInPicture = (config, enableAndroidPictureInPicture) => { + return withAndroidManifest(config, _config => { + if (!enableAndroidPictureInPicture) { + return _config; + } + const mainActivity = AndroidConfig.Manifest.getMainActivity(_config.modResults); + if (!mainActivity) { + console.warn('AndroidManifest.xml is missing an element - skipping adding Picture-In-Picture related config.'); + return _config; + } + mainActivity.$['android:supportsPictureInPicture'] = 'true'; + return _config; + }); +}; +//# sourceMappingURL=withAndroidPictureInPicture.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/withAndroidPictureInPicture.js.map b/lib/module/expo-plugins/withAndroidPictureInPicture.js.map new file mode 100644 index 00000000..89e8bef9 --- /dev/null +++ b/lib/module/expo-plugins/withAndroidPictureInPicture.js.map @@ -0,0 +1 @@ +{"version":3,"names":["AndroidConfig","withAndroidManifest","withAndroidPictureInPicture","config","enableAndroidPictureInPicture","_config","mainActivity","Manifest","getMainActivity","modResults","console","warn","$"],"sourceRoot":"../../../src","sources":["expo-plugins/withAndroidPictureInPicture.ts"],"mappings":";;AAAA,SACEA,aAAa,EACbC,mBAAmB,QAEd,sBAAsB;AAE7B,OAAO,MAAMC,2BAAkD,GAAGA,CAChEC,MAAM,EACNC,6BAA6B,KAC1B;EACH,OAAOH,mBAAmB,CAACE,MAAM,EAAGE,OAAO,IAAK;IAC9C,IAAI,CAACD,6BAA6B,EAAE;MAClC,OAAOC,OAAO;IAChB;IAEA,MAAMC,YAAY,GAAGN,aAAa,CAACO,QAAQ,CAACC,eAAe,CACzDH,OAAO,CAACI,UACV,CAAC;IAED,IAAI,CAACH,YAAY,EAAE;MACjBI,OAAO,CAACC,IAAI,CACV,0IACF,CAAC;MACD,OAAON,OAAO;IAChB;IAEAC,YAAY,CAACM,CAAC,CAAC,kCAAkC,CAAC,GAAG,MAAM;IAE3D,OAAOP,OAAO;EAChB,CAAC,CAAC;AACJ,CAAC","ignoreList":[]} diff --git a/lib/module/expo-plugins/withBackgroundAudio.js b/lib/module/expo-plugins/withBackgroundAudio.js new file mode 100644 index 00000000..756a4730 --- /dev/null +++ b/lib/module/expo-plugins/withBackgroundAudio.js @@ -0,0 +1,22 @@ +"use strict"; + +import { withInfoPlist } from '@expo/config-plugins'; + +/** + * Sets `UIBackgroundModes` in `Info.plist` to enable background audio on Apple platforms. + * This is required for audio to continue playing when the app is in the background. + */ +export const withBackgroundAudio = (c, enableBackgroundAudio) => { + return withInfoPlist(c, config => { + const modes = config.modResults.UIBackgroundModes || []; + if (enableBackgroundAudio) { + if (!modes.includes('audio')) { + config.modResults.UIBackgroundModes = [...modes, 'audio']; + } + } else { + config.modResults.UIBackgroundModes = modes.filter(mode => mode !== 'audio'); + } + return config; + }); +}; +//# sourceMappingURL=withBackgroundAudio.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/withBackgroundAudio.js.map b/lib/module/expo-plugins/withBackgroundAudio.js.map new file mode 100644 index 00000000..ce8216f9 --- /dev/null +++ b/lib/module/expo-plugins/withBackgroundAudio.js.map @@ -0,0 +1 @@ +{"version":3,"names":["withInfoPlist","withBackgroundAudio","c","enableBackgroundAudio","config","modes","modResults","UIBackgroundModes","includes","filter","mode"],"sourceRoot":"../../../src","sources":["expo-plugins/withBackgroundAudio.ts"],"mappings":";;AAAA,SAASA,aAAa,QAA2B,sBAAsB;;AAEvE;AACA;AACA;AACA;AACA,OAAO,MAAMC,mBAA0C,GAAGA,CACxDC,CAAC,EACDC,qBAAqB,KAClB;EACH,OAAOH,aAAa,CAACE,CAAC,EAAGE,MAAM,IAAK;IAClC,MAAMC,KAAK,GAAGD,MAAM,CAACE,UAAU,CAACC,iBAAiB,IAAI,EAAE;IAEvD,IAAIJ,qBAAqB,EAAE;MACzB,IAAI,CAACE,KAAK,CAACG,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC5BJ,MAAM,CAACE,UAAU,CAACC,iBAAiB,GAAG,CAAC,GAAGF,KAAK,EAAE,OAAO,CAAC;MAC3D;IACF,CAAC,MAAM;MACLD,MAAM,CAACE,UAAU,CAACC,iBAAiB,GAAGF,KAAK,CAACI,MAAM,CAC/CC,IAAY,IAAKA,IAAI,KAAK,OAC7B,CAAC;IACH;IAEA,OAAON,MAAM;EACf,CAAC,CAAC;AACJ,CAAC","ignoreList":[]} diff --git a/lib/module/expo-plugins/withReactNativeVideo.js b/lib/module/expo-plugins/withReactNativeVideo.js new file mode 100644 index 00000000..eeabd069 --- /dev/null +++ b/lib/module/expo-plugins/withReactNativeVideo.js @@ -0,0 +1,25 @@ +"use strict"; + +import { createRunOncePlugin } from '@expo/config-plugins'; +import { getPackageInfo } from "./getPackageInfo.js"; +import { withAndroidExtensions } from "./withAndroidExtensions.js"; +import { withAndroidPictureInPicture } from "./withAndroidPictureInPicture.js"; +import { withBackgroundAudio } from "./withBackgroundAudio.js"; +const withRNVideo = (config, props = {}) => { + if (props.enableAndroidPictureInPicture) { + config = withAndroidPictureInPicture(config, props.enableAndroidPictureInPicture); + } + if (props.androidExtensions != null) { + config = withAndroidExtensions(config, props.androidExtensions); + } + if (props.enableBackgroundAudio) { + config = withBackgroundAudio(config, props.enableBackgroundAudio); + } + return config; +}; +const { + name, + version +} = getPackageInfo(); +export default createRunOncePlugin(withRNVideo, name, version); +//# sourceMappingURL=withReactNativeVideo.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/withReactNativeVideo.js.map b/lib/module/expo-plugins/withReactNativeVideo.js.map new file mode 100644 index 00000000..a904951d --- /dev/null +++ b/lib/module/expo-plugins/withReactNativeVideo.js.map @@ -0,0 +1 @@ +{"version":3,"names":["createRunOncePlugin","getPackageInfo","withAndroidExtensions","withAndroidPictureInPicture","withBackgroundAudio","withRNVideo","config","props","enableAndroidPictureInPicture","androidExtensions","enableBackgroundAudio","name","version"],"sourceRoot":"../../../src","sources":["expo-plugins/withReactNativeVideo.ts"],"mappings":";;AAAA,SAA4BA,mBAAmB,QAAQ,sBAAsB;AAE7E,SAASC,cAAc,QAAQ,qBAAkB;AACjD,SAASC,qBAAqB,QAAQ,4BAAyB;AAC/D,SAASC,2BAA2B,QAAQ,kCAA+B;AAC3E,SAASC,mBAAmB,QAAQ,0BAAuB;AAE3D,MAAMC,WAAsC,GAAGA,CAACC,MAAM,EAAEC,KAAK,GAAG,CAAC,CAAC,KAAK;EACrE,IAAIA,KAAK,CAACC,6BAA6B,EAAE;IACvCF,MAAM,GAAGH,2BAA2B,CAClCG,MAAM,EACNC,KAAK,CAACC,6BACR,CAAC;EACH;EAEA,IAAID,KAAK,CAACE,iBAAiB,IAAI,IAAI,EAAE;IACnCH,MAAM,GAAGJ,qBAAqB,CAACI,MAAM,EAAEC,KAAK,CAACE,iBAAiB,CAAC;EACjE;EAEA,IAAIF,KAAK,CAACG,qBAAqB,EAAE;IAC/BJ,MAAM,GAAGF,mBAAmB,CAACE,MAAM,EAAEC,KAAK,CAACG,qBAAqB,CAAC;EACnE;EAEA,OAAOJ,MAAM;AACf,CAAC;AAED,MAAM;EAAEK,IAAI;EAAEC;AAAQ,CAAC,GAAGX,cAAc,CAAC,CAAC;AAE1C,eAAeD,mBAAmB,CAACK,WAAW,EAAEM,IAAI,EAAEC,OAAO,CAAC","ignoreList":[]} diff --git a/lib/module/expo-plugins/writeToPodfile.js b/lib/module/expo-plugins/writeToPodfile.js new file mode 100644 index 00000000..7f220710 --- /dev/null +++ b/lib/module/expo-plugins/writeToPodfile.js @@ -0,0 +1,53 @@ +"use strict"; + +import { mergeContents } from '@expo/config-plugins/build/utils/generateCode'; +import fs from 'fs'; +import path from 'path'; +export const writeToPodfile = (projectRoot, key, value, testApp = false) => { + const podfilePath = path.join(projectRoot, 'ios', 'Podfile'); + const podfileContent = fs.readFileSync(podfilePath, 'utf8'); + if (podfileContent.includes(`$${key} =`)) { + console.warn(`RNV - Podfile already contains a definition for "$${key}". Skipping...`); + return; + } + if (testApp) { + mergeTestAppPodfile(podfileContent, podfilePath, key, value); + } else { + mergeExpoPodfile(podfileContent, podfilePath, key, value); + } +}; +const mergeTestAppPodfile = (podfileContent, podfilePath, key, value) => { + // We will try to inject the variable definition above the `use_test_app!` call in the Podfile. + const newPodfileContent = mergeContents({ + tag: `rn-video-set-${key.toLowerCase()}`, + src: podfileContent, + newSrc: `$${key} = ${value}`, + anchor: /use_test_app!/, + offset: -1, + // Insert the key-value pair just above the `use_test_app!` call. + comment: '#' + }); + + // Write to Podfile only if the merge was successful + if (newPodfileContent.didMerge) { + fs.writeFileSync(podfilePath, newPodfileContent.contents); + } else { + console.warn(`RNV - Failed to write "$${key} = ${value}" to Test App Podfile`); + } +}; +const mergeExpoPodfile = (podfileContent, podfilePath, key, value) => { + const newPodfileContent = mergeContents({ + tag: `rn-video-set-${key.toLowerCase()}`, + src: podfileContent, + newSrc: `$${key} = ${value}`, + anchor: /platform :ios/, + offset: 0, + comment: '#' + }); + if (newPodfileContent.didMerge) { + fs.writeFileSync(podfilePath, newPodfileContent.contents); + } else { + console.warn(`RNV - Failed to write "$${key} = ${value}" to Podfile`); + } +}; +//# sourceMappingURL=writeToPodfile.js.map \ No newline at end of file diff --git a/lib/module/expo-plugins/writeToPodfile.js.map b/lib/module/expo-plugins/writeToPodfile.js.map new file mode 100644 index 00000000..4474c93d --- /dev/null +++ b/lib/module/expo-plugins/writeToPodfile.js.map @@ -0,0 +1 @@ +{"version":3,"names":["mergeContents","fs","path","writeToPodfile","projectRoot","key","value","testApp","podfilePath","join","podfileContent","readFileSync","includes","console","warn","mergeTestAppPodfile","mergeExpoPodfile","newPodfileContent","tag","toLowerCase","src","newSrc","anchor","offset","comment","didMerge","writeFileSync","contents"],"sourceRoot":"../../../src","sources":["expo-plugins/writeToPodfile.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,+CAA+C;AAC7E,OAAOC,EAAE,MAAM,IAAI;AACnB,OAAOC,IAAI,MAAM,MAAM;AAEvB,OAAO,MAAMC,cAAc,GAAGA,CAC5BC,WAAmB,EACnBC,GAAW,EACXC,KAAa,EACbC,OAAgB,GAAG,KAAK,KACrB;EACH,MAAMC,WAAW,GAAGN,IAAI,CAACO,IAAI,CAACL,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC;EAC5D,MAAMM,cAAc,GAAGT,EAAE,CAACU,YAAY,CAACH,WAAW,EAAE,MAAM,CAAC;EAE3D,IAAIE,cAAc,CAACE,QAAQ,CAAC,IAAIP,GAAG,IAAI,CAAC,EAAE;IACxCQ,OAAO,CAACC,IAAI,CACV,qDAAqDT,GAAG,gBAC1D,CAAC;IACD;EACF;EAEA,IAAIE,OAAO,EAAE;IACXQ,mBAAmB,CAACL,cAAc,EAAEF,WAAW,EAAEH,GAAG,EAAEC,KAAK,CAAC;EAC9D,CAAC,MAAM;IACLU,gBAAgB,CAACN,cAAc,EAAEF,WAAW,EAAEH,GAAG,EAAEC,KAAK,CAAC;EAC3D;AACF,CAAC;AAED,MAAMS,mBAAmB,GAAGA,CAC1BL,cAAsB,EACtBF,WAAmB,EACnBH,GAAW,EACXC,KAAa,KACV;EACH;EACA,MAAMW,iBAAiB,GAAGjB,aAAa,CAAC;IACtCkB,GAAG,EAAE,gBAAgBb,GAAG,CAACc,WAAW,CAAC,CAAC,EAAE;IACxCC,GAAG,EAAEV,cAAc;IACnBW,MAAM,EAAE,IAAIhB,GAAG,MAAMC,KAAK,EAAE;IAC5BgB,MAAM,EAAE,eAAe;IACvBC,MAAM,EAAE,CAAC,CAAC;IAAE;IACZC,OAAO,EAAE;EACX,CAAC,CAAC;;EAEF;EACA,IAAIP,iBAAiB,CAACQ,QAAQ,EAAE;IAC9BxB,EAAE,CAACyB,aAAa,CAAClB,WAAW,EAAES,iBAAiB,CAACU,QAAQ,CAAC;EAC3D,CAAC,MAAM;IACLd,OAAO,CAACC,IAAI,CACV,2BAA2BT,GAAG,MAAMC,KAAK,uBAC3C,CAAC;EACH;AACF,CAAC;AAED,MAAMU,gBAAgB,GAAGA,CACvBN,cAAsB,EACtBF,WAAmB,EACnBH,GAAW,EACXC,KAAa,KACV;EACH,MAAMW,iBAAiB,GAAGjB,aAAa,CAAC;IACtCkB,GAAG,EAAE,gBAAgBb,GAAG,CAACc,WAAW,CAAC,CAAC,EAAE;IACxCC,GAAG,EAAEV,cAAc;IACnBW,MAAM,EAAE,IAAIhB,GAAG,MAAMC,KAAK,EAAE;IAC5BgB,MAAM,EAAE,eAAe;IACvBC,MAAM,EAAE,CAAC;IACTC,OAAO,EAAE;EACX,CAAC,CAAC;EAEF,IAAIP,iBAAiB,CAACQ,QAAQ,EAAE;IAC9BxB,EAAE,CAACyB,aAAa,CAAClB,WAAW,EAAES,iBAAiB,CAACU,QAAQ,CAAC;EAC3D,CAAC,MAAM;IACLd,OAAO,CAACC,IAAI,CAAC,2BAA2BT,GAAG,MAAMC,KAAK,cAAc,CAAC;EACvE;AACF,CAAC","ignoreList":[]} diff --git a/lib/module/index.js b/lib/module/index.js new file mode 100644 index 00000000..55c66be1 --- /dev/null +++ b/lib/module/index.js @@ -0,0 +1,7 @@ +"use strict"; + +export { useEvent } from "./core/hooks/useEvent.js"; +export { useVideoPlayer } from "./core/hooks/useVideoPlayer.js"; +export { VideoPlayer } from "./core/VideoPlayer"; +export { default as VideoView } from "./core/video-view/VideoView"; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/module/index.js.map b/lib/module/index.js.map new file mode 100644 index 00000000..40ea2011 --- /dev/null +++ b/lib/module/index.js.map @@ -0,0 +1 @@ +{"version":3,"names":["useEvent","useVideoPlayer","VideoPlayer","default","VideoView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,0BAAuB;AAChD,SAASC,cAAc,QAAQ,gCAA6B;AAoB5D,SAASC,WAAW,QAAQ,oBAAoB;AAChD,SAASC,OAAO,IAAIC,SAAS,QAAQ,6BAA6B","ignoreList":[]} diff --git a/lib/module/package.json b/lib/module/package.json new file mode 100644 index 00000000..089153bc --- /dev/null +++ b/lib/module/package.json @@ -0,0 +1 @@ +{"type":"module"} diff --git a/lib/module/spec/fabric/VideoViewNativeComponent.ts b/lib/module/spec/fabric/VideoViewNativeComponent.ts new file mode 100644 index 00000000..41a83d37 --- /dev/null +++ b/lib/module/spec/fabric/VideoViewNativeComponent.ts @@ -0,0 +1,17 @@ +import type { ViewProps } from 'react-native'; +import type { + DirectEventHandler, + Int32, +} from 'react-native/Libraries/Types/CodegenTypes'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +type OnNitroIdChangeEvent = Readonly<{ + nitroId: Int32; +}>; + +export interface ViewViewNativeProps extends ViewProps { + nitroId: Int32; + onNitroIdChange?: DirectEventHandler; +} + +export default codegenNativeComponent('RNCVideoView'); diff --git a/lib/module/spec/nitro/VideoPlayer.nitro.js b/lib/module/spec/nitro/VideoPlayer.nitro.js new file mode 100644 index 00000000..8d7cd016 --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayer.nitro.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoPlayer.nitro.js.map \ No newline at end of file diff --git a/lib/module/spec/nitro/VideoPlayer.nitro.js.map b/lib/module/spec/nitro/VideoPlayer.nitro.js.map new file mode 100644 index 00000000..f974a4e3 --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayer.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayer.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js b/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js new file mode 100644 index 00000000..d427b491 --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoPlayerEventEmitter.nitro.js.map \ No newline at end of file diff --git a/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js.map b/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js.map new file mode 100644 index 00000000..7250c716 --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayerEventEmitter.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayerEventEmitter.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/spec/nitro/VideoPlayerSource.nitro.js b/lib/module/spec/nitro/VideoPlayerSource.nitro.js new file mode 100644 index 00000000..ffca8e3d --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayerSource.nitro.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoPlayerSource.nitro.js.map \ No newline at end of file diff --git a/lib/module/spec/nitro/VideoPlayerSource.nitro.js.map b/lib/module/spec/nitro/VideoPlayerSource.nitro.js.map new file mode 100644 index 00000000..0717839d --- /dev/null +++ b/lib/module/spec/nitro/VideoPlayerSource.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoPlayerSource.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/module/spec/nitro/VideoViewViewManager.nitro.js b/lib/module/spec/nitro/VideoViewViewManager.nitro.js new file mode 100644 index 00000000..c5e22bef --- /dev/null +++ b/lib/module/spec/nitro/VideoViewViewManager.nitro.js @@ -0,0 +1,4 @@ +"use strict"; + +export {}; +//# sourceMappingURL=VideoViewViewManager.nitro.js.map \ No newline at end of file diff --git a/lib/module/spec/nitro/VideoViewViewManager.nitro.js.map b/lib/module/spec/nitro/VideoViewViewManager.nitro.js.map new file mode 100644 index 00000000..102a6896 --- /dev/null +++ b/lib/module/spec/nitro/VideoViewViewManager.nitro.js.map @@ -0,0 +1 @@ +{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["spec/nitro/VideoViewViewManager.nitro.ts"],"mappings":"","ignoreList":[]} diff --git a/lib/typescript/commonjs/package.json b/lib/typescript/commonjs/package.json new file mode 100644 index 00000000..729ac4d9 --- /dev/null +++ b/lib/typescript/commonjs/package.json @@ -0,0 +1 @@ +{"type":"commonjs"} diff --git a/lib/typescript/commonjs/src/core/VideoPlayer.d.ts b/lib/typescript/commonjs/src/core/VideoPlayer.d.ts new file mode 100644 index 00000000..9143bf43 --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayer.d.ts @@ -0,0 +1,57 @@ +import type { VideoPlayer as VideoPlayerImpl } from '../spec/nitro/VideoPlayer.nitro'; +import type { VideoPlayerSource } from '../spec/nitro/VideoPlayerSource.nitro'; +import type { IgnoreSilentSwitchMode } from './types/IgnoreSilentSwitchMode'; +import type { MixAudioMode } from './types/MixAudioMode'; +import type { TextTrack } from './types/TextTrack'; +import type { NoAutocomplete } from './types/Utils'; +import type { VideoConfig, VideoSource } from './types/VideoConfig'; +import type { VideoPlayerBase } from './types/VideoPlayerBase'; +import type { VideoPlayerStatus } from './types/VideoPlayerStatus'; +import { VideoPlayerEvents } from './VideoPlayerEvents'; +declare class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase { + protected player: VideoPlayerImpl; + constructor(source: VideoSource | VideoConfig | VideoPlayerSource); + get source(): VideoPlayerSource; + get status(): VideoPlayerStatus; + get duration(): number; + get volume(): number; + set volume(value: number); + get currentTime(): number; + set currentTime(value: number); + get muted(): boolean; + set muted(value: boolean); + get loop(): boolean; + set loop(value: boolean); + get rate(): number; + set rate(value: number); + get mixAudioMode(): MixAudioMode; + set mixAudioMode(value: MixAudioMode); + get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode; + set ignoreSilentSwitchMode(value: IgnoreSilentSwitchMode); + get playInBackground(): boolean; + set playInBackground(value: boolean); + get playWhenInactive(): boolean; + set playWhenInactive(value: boolean); + get isPlaying(): boolean; + get showNotificationControls(): boolean; + set showNotificationControls(value: boolean); + initialize(): Promise; + preload(): Promise; + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release(): void; + play(): void; + pause(): void; + seekBy(time: number): void; + seekTo(time: number): void; + replaceSourceAsync(source: VideoSource | VideoConfig | NoAutocomplete | null): Promise; + getAvailableTextTracks(): TextTrack[]; + selectTextTrack(textTrack: TextTrack | null): void; + get selectedTrack(): TextTrack | undefined; +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/VideoPlayer.d.ts.map b/lib/typescript/commonjs/src/core/VideoPlayer.d.ts.map new file mode 100644 index 00000000..f69e717a --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAM,WAAY,SAAQ,iBAAkB,YAAW,eAAe;IACpE,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC;gBAEtB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,iBAAiB;IA2DjE,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAGD,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAGD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAGD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAEvB;IAGD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAE5B;IAGD,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAGD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAGD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAGD,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,YAAY,CAAC,KAAK,EAAE,YAAY,EAEnC;IAGD,IAAI,sBAAsB,IAAI,sBAAsB,CAEnD;IAED,IAAI,sBAAsB,CAAC,KAAK,EAAE,sBAAsB,EAQvD;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAElC;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAElC;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,wBAAwB,IAAI,OAAO,CAEtC;IAED,IAAI,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAE1C;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAIf,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQpB,kBAAkB,CACtB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC,iBAAiB,CAAC,GAAG,IAAI,GAC3E,OAAO,CAAC,IAAI,CAAC;IAWhB,sBAAsB,IAAI,SAAS,EAAE;IASrC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IASlD,IAAI,aAAa,IAAI,SAAS,GAAG,SAAS,CAEzC;CACF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts b/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts new file mode 100644 index 00000000..54011de9 --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts @@ -0,0 +1,58 @@ +import shaka from "shaka-player"; +import type { VideoPlayerSource } from "../spec/nitro/VideoPlayerSource.nitro"; +import type { IgnoreSilentSwitchMode } from "./types/IgnoreSilentSwitchMode"; +import type { MixAudioMode } from "./types/MixAudioMode"; +import type { TextTrack } from "./types/TextTrack"; +import type { NoAutocomplete } from "./types/Utils"; +import type { VideoConfig, VideoSource } from "./types/VideoConfig"; +import type { VideoPlayerBase } from "./types/VideoPlayerBase"; +import type { VideoPlayerStatus } from "./types/VideoPlayerStatus"; +import { VideoPlayerEvents } from "./VideoPlayerEvents"; +declare class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase { + protected player: shaka.Player; + protected video: HTMLVideoElement; + protected headers: Record; + constructor(source: VideoSource | VideoConfig | VideoPlayerSource); + __getNativeRef(): HTMLVideoElement; + get source(): VideoPlayerSource; + get status(): VideoPlayerStatus; + get duration(): number; + get volume(): number; + set volume(value: number); + get currentTime(): number; + set currentTime(value: number); + get muted(): boolean; + set muted(value: boolean); + get loop(): boolean; + set loop(value: boolean); + get rate(): number; + set rate(value: number); + get mixAudioMode(): MixAudioMode; + set mixAudioMode(_: MixAudioMode); + get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode; + set ignoreSilentSwitchMode(_: IgnoreSilentSwitchMode); + get playInBackground(): boolean; + set playInBackground(_: boolean); + get playWhenInactive(): boolean; + set playWhenInactive(_: boolean); + get isPlaying(): boolean; + initialize(): Promise; + preload(): Promise; + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release(): void; + play(): void; + pause(): void; + seekBy(time: number): void; + seekTo(time: number): void; + replaceSourceAsync(source: VideoSource | VideoConfig | NoAutocomplete | null): Promise; + getAvailableTextTracks(): TextTrack[]; + selectTextTrack(textTrack: TextTrack | null): void; + get selectedTrack(): TextTrack | undefined; +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.web.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts.map b/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts.map new file mode 100644 index 00000000..152dbada --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayer.web.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.web.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayer.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,cAAM,WAAY,SAAQ,iBAAkB,YAAW,eAAe;IACpE,SAAS,CAAC,MAAM,eAAsB;IACtC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;gBAEnC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,iBAAiB;IAoBjE,cAAc;IAuBd,IAAI,MAAM,IAAI,iBAAiB,CAM9B;IAGD,IAAI,MAAM,IAAI,iBAAiB,CAS9B;IAGD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAGD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAEvB;IAGD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAE5B;IAGD,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAGD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAGD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAGD,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,YAAY,CAAC,CAAC,EAAE,YAAY,EAM/B;IAGD,IAAI,sBAAsB,IAAI,sBAAsB,CAEnD;IAED,IAAI,sBAAsB,CAAC,CAAC,EAAE,sBAAsB,EAMnD;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAM9B;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAM9B;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAIf,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQpB,kBAAkB,CACtB,MAAM,EACF,WAAW,GACX,WAAW,GACX,cAAc,CAAC,iBAAiB,CAAC,GACjC,IAAI,GACP,OAAO,CAAC,IAAI,CAAC;IAuBhB,sBAAsB,IAAI,SAAS,EAAE;IASrC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAUlD,IAAI,aAAa,IAAI,SAAS,GAAG,SAAS,CAEzC;CACF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts b/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts new file mode 100644 index 00000000..711e6068 --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts @@ -0,0 +1,20 @@ +import { type VideoPlayerEvents as NativePlayerEvents, type AllPlayerEvents as PlayerEvents } from "./types/Events"; +export declare class VideoPlayerEvents { + protected eventEmitter: NativePlayerEvents; + protected eventListeners: Partial void>>>; + protected readonly supportedEvents: (keyof PlayerEvents)[]; + constructor(eventEmitter: NativePlayerEvents); + protected triggerEvent(event: Event, ...params: Parameters): boolean; + addEventListener(event: Event, callback: PlayerEvents[Event]): void; + removeEventListener(event: Event, callback: PlayerEvents[Event]): void; + /** + * Clears all events from the event emitter. + */ + clearAllEvents(): void; + /** + * Clears a specific event from the event emitter. + * @param event - The name of the event to clear. + */ + clearEvent(event: keyof PlayerEvents): void; +} +//# sourceMappingURL=VideoPlayerEvents.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts.map b/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts.map new file mode 100644 index 00000000..d2993d16 --- /dev/null +++ b/lib/typescript/commonjs/src/core/VideoPlayerEvents.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerEvents.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayerEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,IAAI,kBAAkB,EAC5C,KAAK,eAAe,IAAI,YAAY,EACrC,MAAM,gBAAgB,CAAC;AAExB,qBAAa,iBAAiB;IAC5B,SAAS,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC3C,SAAS,CAAC,cAAc,EAAE,OAAO,CAC/B,MAAM,CAAC,MAAM,YAAY,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAC5D,CAAM;IAEP,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,YAAY,CAAC,EAAE,CACtC;gBAER,YAAY,EAAE,kBAAkB;IAQ5C,SAAS,CAAC,YAAY,CAAC,KAAK,SAAS,MAAM,YAAY,EACrD,KAAK,EAAE,KAAK,EACZ,GAAG,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GACzC,OAAO;IAQV,gBAAgB,CAAC,KAAK,SAAS,MAAM,YAAY,EAC/C,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC;IAM/B,mBAAmB,CAAC,KAAK,SAAS,MAAM,YAAY,EAClD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC;IAK/B;;OAEG;IACH,cAAc;IAMd;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,YAAY;CAGrC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts b/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts new file mode 100644 index 00000000..937443e1 --- /dev/null +++ b/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts @@ -0,0 +1,45 @@ +import type { BandwidthData, onLoadData, onLoadStartData, onPlaybackStateChangeData, onProgressData, onVolumeChangeData, AllPlayerEvents as PlayerEvents, TimedMetadata } from "./types/Events"; +import type { TextTrack } from "./types/TextTrack"; +import type { VideoRuntimeError } from "./types/VideoError"; +import type { VideoPlayerStatus } from "./types/VideoPlayerStatus"; +export declare class WebEventEmiter implements PlayerEvents { + private video; + private _isBuferring; + constructor(video: HTMLVideoElement); + destroy(): void; + _onTimeUpdate(): void; + _onCanPlay(): void; + _onWaiting(): void; + _onDurationChange(): void; + _onEnded(): void; + _onLoadStart(): void; + _onPlay(): void; + _onPause(): void; + _onRateChange(): void; + _onLoadedData(): void; + _onSeeked(): void; + _onVolumeChange(): void; + _onError(): void; + NOOP: () => void; + onError: (error: VideoRuntimeError) => void; + onAudioBecomingNoisy: () => void; + onAudioFocusChange: (hasAudioFocus: boolean) => void; + onBandwidthUpdate: (data: BandwidthData) => void; + onBuffer: (buffering: boolean) => void; + onControlsVisibleChange: (visible: boolean) => void; + onEnd: () => void; + onExternalPlaybackChange: (externalPlaybackActive: boolean) => void; + onLoad: (data: onLoadData) => void; + onLoadStart: (data: onLoadStartData) => void; + onPlaybackStateChange: (data: onPlaybackStateChangeData) => void; + onPlaybackRateChange: (rate: number) => void; + onProgress: (data: onProgressData) => void; + onReadyToDisplay: () => void; + onSeek: (seekTime: number) => void; + onTimedMetadata: (metadata: TimedMetadata) => void; + onTextTrackDataChanged: (texts: string[]) => void; + onTrackChange: (track: TextTrack | null) => void; + onVolumeChange: (data: onVolumeChangeData) => void; + onStatusChange: (status: VideoPlayerStatus) => void; +} +//# sourceMappingURL=WebEventEmiter.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts.map b/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts.map new file mode 100644 index 00000000..11b34110 --- /dev/null +++ b/lib/typescript/commonjs/src/core/WebEventEmiter.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"WebEventEmiter.d.ts","sourceRoot":"","sources":["../../../../../src/core/WebEventEmiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,eAAe,IAAI,YAAY,EAC/B,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,cAAe,YAAW,YAAY;IAGrC,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,YAAY,CAAS;gBAET,KAAK,EAAE,gBAAgB;IAoD3C,OAAO;IAwBP,aAAa;IASb,UAAU;IAKV,UAAU;IAMV,iBAAiB;IAUjB,QAAQ;IAKR,YAAY;IAyBZ,OAAO;IAOP,QAAQ;IAOR,aAAa;IAIb,aAAa;IAIb,SAAS;IAIT,eAAe;IAIf,QAAQ;IAIR,IAAI,aAAY;IAEhB,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAa;IACxD,oBAAoB,EAAE,MAAM,IAAI,CAAa;IAC7C,kBAAkB,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAa;IACjE,iBAAiB,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAa;IAC7D,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAa;IACnD,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAa;IAChE,KAAK,EAAE,MAAM,IAAI,CAAa;IAC9B,wBAAwB,EAAE,CAAC,sBAAsB,EAAE,OAAO,KAAK,IAAI,CACvD;IACZ,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAa;IAC/C,WAAW,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAa;IACzD,qBAAqB,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAa;IAC7E,oBAAoB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAa;IACzD,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAa;IACvD,gBAAgB,EAAE,MAAM,IAAI,CAAa;IACzC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAa;IAC/C,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAa;IAC/D,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAa;IAC9D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAa;IAC7D,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAa;IAC/D,cAAc,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAa;CACjE"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts b/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts new file mode 100644 index 00000000..3f27f22d --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts @@ -0,0 +1,11 @@ +import type { AllPlayerEvents } from '../types/Events'; +import type { VideoPlayer } from '../VideoPlayer'; +/** + * Attaches an event listener to a `VideoPlayer` instance for a specified event. + * + * @param player - The player to attach the event to + * @param event - The name of the event to attach the callback to + * @param callback - The callback for the event + */ +export declare const useEvent: (player: VideoPlayer, event: T, callback: AllPlayerEvents[T]) => void; +//# sourceMappingURL=useEvent.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts.map b/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts.map new file mode 100644 index 00000000..1640535b --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useEvent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useEvent.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useEvent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,eAAe,EACtD,QAAQ,WAAW,EACnB,OAAO,CAAC,EACR,UAAU,eAAe,CAAC,CAAC,CAAC,SAO7B,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts b/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts new file mode 100644 index 00000000..ec6b0c60 --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=useManagedInstance.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts.map b/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts.map new file mode 100644 index 00000000..6457fb74 --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useManagedInstance.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useManagedInstance.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useManagedInstance.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts b/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts new file mode 100644 index 00000000..def17916 --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts @@ -0,0 +1,13 @@ +import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro'; +import type { NoAutocomplete } from '../types/Utils'; +import type { VideoConfig, VideoSource } from '../types/VideoConfig'; +import { VideoPlayer } from '../VideoPlayer'; +/** + * Creates a `VideoPlayer` instance and manages its lifecycle. + * + * @param source - The source of the video to play + * @param setup - A function to setup the player + * @returns The `VideoPlayer` instance + */ +export declare const useVideoPlayer: (source: VideoConfig | VideoSource | NoAutocomplete, setup?: (player: VideoPlayer) => void) => VideoPlayer; +//# sourceMappingURL=useVideoPlayer.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts.map b/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts.map new file mode 100644 index 00000000..f81150c5 --- /dev/null +++ b/lib/typescript/commonjs/src/core/hooks/useVideoPlayer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useVideoPlayer.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useVideoPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAc7C;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC,iBAAiB,CAAC,EACrE,QAAQ,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,gBAgBtC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts b/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts new file mode 100644 index 00000000..d12f642d --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts @@ -0,0 +1,97 @@ +export interface LivePlaybackParams { + /** + * Minimum playback speed for catching up to target live offset. + * @platform android + */ + minPlaybackSpeed?: number; + /** + * Maximum playback speed for catching up to target live offset. + * @platform android + */ + maxPlaybackSpeed?: number; + /** + * Maximum allowed live offset. The player won’t exceed this limit. + * @platform android + */ + maxOffsetMs?: number; + /** + * Minimum allowed live offset. The player won’t go below this limit. + * @platform android + */ + minOffsetMs?: number; + /** + * Target live offset. The player will try to maintain this offset. + * @platform android, ios, visionOS, tvOS + */ + targetOffsetMs?: number; +} +interface Resolution { + width: number; + height: number; +} +export interface BufferConfig { + /** + * Configuration for live playback. + */ + livePlayback?: LivePlaybackParams; + /** + * Minimum duration (ms) the player will attempt to keep buffered. + * @default 5000 + * @platform android + */ + minBufferMs?: number; + /** + * Maximum duration (ms) the player will attempt to keep buffered. + * @default 10000 + * @platform android + */ + maxBufferMs?: number; + /** + * Duration (ms) of media that must be buffered for playback to start or resume following a user action such as a seek. + * @default 1000 + * @platform android + */ + bufferForPlaybackMs?: number; + /** + * Duration (ms) of media that must be buffered for playback to resume after a rebuffer. + * @default 2000 + * @platform android + */ + bufferForPlaybackAfterRebufferMs?: number; + /** + * Duration (ms) of media that must be buffered before it can be played from the back buffer. + * @platform android + */ + backBufferDurationMs?: number; + /** + * The preferred duration (ms) of media that the player will attempt to retain in the buffer. + * @platform ios, visionOS, tvOS + */ + preferredForwardBufferDurationMs?: number; + /** + * The desired limit, in bits per second, of network bandwidth used for loading the current item. + * + * You can use {@linkcode preferredPeakBitRateForExpensiveNetworks} to set a different bit rate when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredPeakBitRate?: number; + /** + * The preferred maximum resolution of the video. + * + * You can use {@linkcode preferredMaximumResolutionForExpensiveNetworks} to set a different resolution when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredMaximumResolution?: Resolution; + /** + * The desired limit, in bits per second, of network bandwidth used for loading the current item when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredPeakBitRateForExpensiveNetworks?: number; + /** + * The preferred maximum resolution of the video when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredMaximumResolutionForExpensiveNetworks?: Resolution; +} +export {}; +//# sourceMappingURL=BufferConfig.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts.map b/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts.map new file mode 100644 index 00000000..b4bed131 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/BufferConfig.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"BufferConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/BufferConfig.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAIlC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAI9B;;;OAGG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,UAAU,CAAC;IACxC;;;OAGG;IACH,wCAAwC,CAAC,EAAE,MAAM,CAAC;IAClD;;;OAGG;IACH,8CAA8C,CAAC,EAAE,UAAU,CAAC;CAC7D"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/DrmParams.d.ts b/lib/typescript/commonjs/src/core/types/DrmParams.d.ts new file mode 100644 index 00000000..d19b21e1 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/DrmParams.d.ts @@ -0,0 +1,64 @@ +/** + * Headers type specifically for DRM license requests + */ +export interface DrmParams { + /** + * The license URL for the DRM license request. + * @platform iOS, visionOS + */ + licenseUrl?: string; + /** + * The certificate URL for the DRM license request. + * @platform iOS, visionOS + */ + certificateUrl?: string; + /** + * The content ID for the DRM license request. + * @platform iOS, visionOS + */ + contentId?: string; + /** + * The type of DRM to use. + * @platform Android, iOS, visionOS + */ + type?: DRMType; + /** + * The headers to send with the DRM license request. + * @platform Android, iOS, visionOS + */ + licenseHeaders?: Record; + /** + * Whether to allow multiple sessions for the DRM license request. + * @platform Android + */ + multiSession?: boolean; + /** + * A function to get the license for the DRM license request. + * @platform iOS + */ + getLicense?: (payload: OnGetLicensePayload) => Promise; +} +interface OnGetLicensePayload { + /** + * The content ID for the DRM license request. + * This is typically a unique identifier for the content being played. + */ + contentId: string; + /** + * The license URL for the DRM license request. + */ + licenseUrl: string; + /** + * The key URL for the DRM license request. + * Typically starts with starting with skd:// or clearkey:// + */ + keyUrl: string; + /** + * The secure playback context (SPC) for the DRM license request. + * This is typically a base64-encoded string that contains information about the playback environment. + */ + spc: string; +} +type DRMType = 'widevine' | 'fairplay' | (string & {}); +export {}; +//# sourceMappingURL=DrmParams.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/DrmParams.d.ts.map b/lib/typescript/commonjs/src/core/types/DrmParams.d.ts.map new file mode 100644 index 00000000..0f001621 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/DrmParams.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DrmParams.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/DrmParams.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChE;AAED,UAAU,mBAAmB;IAC3B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,KAAK,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/Events.d.ts b/lib/typescript/commonjs/src/core/types/Events.d.ts new file mode 100644 index 00000000..af4270a4 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/Events.d.ts @@ -0,0 +1,221 @@ +import type { TextTrack } from './TextTrack'; +import type { VideoRuntimeError } from './VideoError'; +import type { VideoOrientation } from './VideoOrientation'; +import type { VideoPlayerSourceBase } from './VideoPlayerSourceBase'; +import type { VideoPlayerStatus } from './VideoPlayerStatus'; +export interface VideoPlayerEvents { + /** + * Called when the audio becomes noisy. + * @platform Android + */ + onAudioBecomingNoisy: () => void; + /** + * Called when the audio focus changes. + * @param hasAudioFocus Whether the audio has focus. + * @platform Android + */ + onAudioFocusChange: (hasAudioFocus: boolean) => void; + /** + * Called when the bandwidth of the video changes. + */ + onBandwidthUpdate: (data: BandwidthData) => void; + /** + * Called when the video is buffering. + * @param buffering Whether the video is buffering. + */ + onBuffer: (buffering: boolean) => void; + /** + * Called when the video view's controls visibility changes. + * @param visible Whether the video view's controls are visible. + * @platform Android, Ios + */ + onControlsVisibleChange: (visible: boolean) => void; + /** + * Called when the video ends. + */ + onEnd: () => void; + /** + * Called when the external playback state changes. + * @param externalPlaybackActive Whether the external playback is active. + * @platform iOS + */ + onExternalPlaybackChange: (externalPlaybackActive: boolean) => void; + /** + * Called when the video is loaded. + * @note onLoadStart -> initialize the player -> onLoad + */ + onLoad: (data: onLoadData) => void; + /** + * Called when the video starts loading. + * @note onLoadStart -> initialize the player -> onLoad + */ + onLoadStart: (data: onLoadStartData) => void; + /** + * Called when the player playback state changes. + */ + onPlaybackStateChange: (data: onPlaybackStateChangeData) => void; + /** + * Called when the player playback rate changes. + */ + onPlaybackRateChange: (rate: number) => void; + /** + * Called when the player progress changes. + */ + onProgress: (data: onProgressData) => void; + /** + * Called when the video is ready to display. + */ + onReadyToDisplay: () => void; + /** + * Called when the player seeks. + */ + onSeek: (seekTime: number) => void; + /** + * Called when player receives timed metadata. + * @platform Android, Ios + */ + onTimedMetadata: (metadata: TimedMetadata) => void; + /** + * Called when the text track (currently displayed subtitle) data changes. + * @platform Android, Ios + */ + onTextTrackDataChanged: (texts: string[]) => void; + /** + * Called when the selected text track changes. + * @param track - The newly selected text track, or null if no track is selected + * @platform Android, Ios + */ + onTrackChange: (track: TextTrack | null) => void; + /** + * Called when the volume of the player changes. + */ + onVolumeChange: (data: onVolumeChangeData) => void; + /** + * Called when the player status changes. + */ + onStatusChange: (status: VideoPlayerStatus) => void; +} +export interface AllPlayerEvents extends VideoPlayerEvents { + onError: (error: VideoRuntimeError) => void; +} +export interface VideoViewEvents { + /** + * Called when the video view's picture in picture state changes. + * @param isInPictureInPicture Whether the video view is in picture in picture mode. + */ + onPictureInPictureChange: (isInPictureInPicture: boolean) => void; + /** + * Called when the video view's fullscreen state changes. + * @param fullscreen Whether the video view is in fullscreen mode. + */ + onFullscreenChange: (fullscreen: boolean) => void; + /** + * Called when the video view will enter fullscreen mode. + */ + willEnterFullscreen: () => void; + /** + * Called when the video view will exit fullscreen mode. + */ + willExitFullscreen: () => void; + /** + * Called when the video view will enter picture in picture mode. + */ + willEnterPictureInPicture: () => void; + /** + * Called when the video view will exit picture in picture mode. + */ + willExitPictureInPicture: () => void; +} +export interface BandwidthData { + /** + * The bitrate of the video in bits per second. + */ + bitrate: number; + /** + * The width of the video in pixels. + * @platform android + */ + width?: number; + /** + * The height of the video in pixels. + * @platform Android + */ + height?: number; +} +export interface onLoadData { + /** + * The current time of the video in seconds. + */ + currentTime: number; + /** + * The duration of the video in seconds. + * @note NaN if the duration is unknown. + */ + duration: number; + /** + * The height of the video in pixels. + */ + height: number; + /** + * The width of the video in pixels. + */ + width: number; + /** + * The orientation of the video. + */ + orientation: VideoOrientation; +} +export type SourceType = 'local' | 'network'; +export interface onLoadStartData { + /** + * The type of the source. + * @note `local` for local files, `network` for network sources. + */ + sourceType: SourceType; + /** + * The source of the video. + */ + source: VideoPlayerSourceBase; +} +export interface onPlaybackStateChangeData { + /** + * Whether the video is playing. + */ + isPlaying: boolean; + /** + * Whether the video is buffering. + */ + isBuffering: boolean; +} +export interface onProgressData { + /** + * The current time of the video in seconds. + */ + currentTime: number; + /** + * The time that player is able to play with only buffer. + */ + bufferDuration: number; +} +export type TimedMetadataObject = { + value: string; + identifier: string; +}; +export interface TimedMetadata { + /** + * The timed metadata of the video. + */ + metadata: Array; +} +export interface onVolumeChangeData { + /** + * The volume of the player (0.0 = 0%, 1.0 = 100%). + */ + volume: number; + /** + * Whether the player is muted. + */ + muted: boolean; +} +export declare const ALL_PLAYER_EVENTS: (keyof AllPlayerEvents)[]; +//# sourceMappingURL=Events.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/Events.d.ts.map b/lib/typescript/commonjs/src/core/types/Events.d.ts.map new file mode 100644 index 00000000..93d17163 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/Events.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Events.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/Events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD;;OAEG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;OAIG;IACH,wBAAwB,EAAE,CAAC,sBAAsB,EAAE,OAAO,KAAK,IAAI,CAAC;IACpE;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,WAAW,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,qBAAqB,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACjE;;OAEG;IACH,oBAAoB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C;;OAEG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B;;OAEG;IACH,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD;;OAEG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,cAAc,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,wBAAwB,EAAE,CAAC,oBAAoB,EAAE,OAAO,KAAK,IAAI,CAAC;IAClE;;;OAGG;IACH,kBAAkB,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC;;OAEG;IACH,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B;;OAEG;IACH,yBAAyB,EAAE,MAAM,IAAI,CAAC;IACtC;;OAEG;IACH,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAiBD,eAAO,MAAM,iBAAiB,EAAE,CAAC,MAAM,eAAe,CAAC,EAsBpD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts b/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts new file mode 100644 index 00000000..4bf842ef --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts @@ -0,0 +1,2 @@ +export type IgnoreSilentSwitchMode = 'auto' | 'ignore' | 'obey'; +//# sourceMappingURL=IgnoreSilentSwitchMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts.map b/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts.map new file mode 100644 index 00000000..a5219753 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/IgnoreSilentSwitchMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"IgnoreSilentSwitchMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/IgnoreSilentSwitchMode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts b/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts new file mode 100644 index 00000000..9526d372 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts @@ -0,0 +1,2 @@ +export type MixAudioMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers' | 'auto'; +//# sourceMappingURL=MixAudioMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts.map b/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts.map new file mode 100644 index 00000000..93f4b499 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/MixAudioMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MixAudioMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/MixAudioMode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts b/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts new file mode 100644 index 00000000..7593e483 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts @@ -0,0 +1,10 @@ +/** + * Video resize modes that determine how video content is resized to fit the view + * + * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view + * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop) + * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio + * - 'none': Do not resize the video - it will fallback to default behavior (contain) + */ +export type ResizeMode = 'contain' | 'cover' | 'stretch' | 'none'; +//# sourceMappingURL=ResizeMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts.map b/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts.map new file mode 100644 index 00000000..2260f355 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/ResizeMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ResizeMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/ResizeMode.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/TextTrack.d.ts b/lib/typescript/commonjs/src/core/types/TextTrack.d.ts new file mode 100644 index 00000000..45e616cc --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/TextTrack.d.ts @@ -0,0 +1,20 @@ +export interface TextTrack { + /** + * Unique identifier for the text track + */ + id: string; + /** + * Display label for the text track + */ + label: string; + /** + * Language code (ISO 639-1 or ISO 639-2) + * @example "en", "es", "fr" + */ + language?: string; + /** + * Whether this track is currently selected + */ + selected: boolean; +} +//# sourceMappingURL=TextTrack.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/TextTrack.d.ts.map b/lib/typescript/commonjs/src/core/types/TextTrack.d.ts.map new file mode 100644 index 00000000..d0b729b6 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/TextTrack.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TextTrack.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/TextTrack.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/Utils.d.ts b/lib/typescript/commonjs/src/core/types/Utils.d.ts new file mode 100644 index 00000000..e5422cc9 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/Utils.d.ts @@ -0,0 +1,2 @@ +export type NoAutocomplete = T & never; +//# sourceMappingURL=Utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/Utils.d.ts.map b/lib/typescript/commonjs/src/core/types/Utils.d.ts.map new file mode 100644 index 00000000..4ad5d84d --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/Utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/Utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts b/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts new file mode 100644 index 00000000..0e287edf --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts @@ -0,0 +1,124 @@ +import type { BufferConfig } from './BufferConfig'; +import type { DrmParams } from './DrmParams'; +export type VideoSource = number | string; +export type VideoConfig = { + /** + * The uri of the video. + * @example + * ```ts + * uri: 'https://example.com/video.mp4' + * // or + * uri: require('./assets/video.mp4') + * ``` + */ + uri: VideoSource; + /** + * The headers to be sent with the request. + */ + headers?: Record; + /** + * The DRM parameters to be used. + */ + drm?: DrmParams; + /** + * The player buffer configuration. + */ + bufferConfig?: BufferConfig; + /** + * The custom metadata to be associated with the video. + * This metadata can be used by the native player to show information about the video. + */ + metadata?: CustomVideoMetadata; + /** + * The external subtitles to be used. + * @note on iOS, only WebVTT (.vtt) subtitles are supported (for HLS streams and MP4 files). + * @note on iOS, `label` can be overridden by player and there is no way to get around it. + * @example + * ```ts + * externalSubtitles: [ + * { + * uri: 'https://example.com/subtitles_en.vtt', + * label: 'English', + * type: 'vtt', + * language: 'en' + * }, + * { + * uri: 'https://example.com/subtitles_es.vtt', + * label: 'Español', + * type: 'vtt', + * language: 'es' + * } + * ] + * ``` + */ + externalSubtitles?: ExternalSubtitle[]; + /** + * when the player is created, this flag will determine if native player should be initialized immediately. + * If set to true, the player will be initialized as soon as player is created + * If set to false, the player will need be initialized manually later + * @default true + */ + initializeOnCreation?: boolean; +}; +/** + * The type of the subtitle. + * - `vtt` - WebVTT + * - `srt` - SubRip + * - `ssa` - SubStation Alpha + * - `ass` - Advanced SubStation Alpha + * - `auto` - Auto detect the subtitle type from the file extension + * + * @note `auto` is not available when uri have no extension. + */ +export type SubtitleType = 'vtt' | 'srt' | 'ssa' | 'ass' | 'auto'; +interface ExternalSubtitleWithInferredType { + /** + * The uri of the subtitle. + * @note the uri must end with the subtitle type. + */ + uri: `${string}.${SubtitleType}`; + /** + * The label for the subtitle. + */ + label: string; + /** + * The type of the subtitle. + */ + type?: SubtitleType; + /** + * The language code for the subtitle (ISO 639-1 or ISO 639-2). + * @example 'en', 'es', 'fr', 'de', 'zh-CN' + * @default 'und' (undefined) + */ + language?: string; +} +interface ExternalSubtitleWithCustomType { + /** + * The uri of the subtitle. + */ + uri: string; + /** + * The label for the subtitle. + */ + label: string; + /** + * The type of the subtitle. + */ + type: Omit; + /** + * The language code for the subtitle (ISO 639-1 or ISO 639-2). + * @example 'en', 'es', 'fr', 'de', 'zh-CN' + * @default 'und' (undefined) + */ + language?: string; +} +export type ExternalSubtitle = ExternalSubtitleWithInferredType | ExternalSubtitleWithCustomType; +interface CustomVideoMetadata { + title?: string; + subtitle?: string; + description?: string; + artist?: string; + imageUri?: string; +} +export {}; +//# sourceMappingURL=VideoConfig.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts.map new file mode 100644 index 00000000..a6d3b7d3 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoConfig.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;;OAQG;IACH,GAAG,EAAE,WAAW,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACvC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAUF;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAElE,UAAU,gCAAgC;IACxC;;;OAGG;IACH,GAAG,EAAE,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,8BAA8B;IACtC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GACxB,gCAAgC,GAChC,8BAA8B,CAAC;AAanC,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoError.d.ts b/lib/typescript/commonjs/src/core/types/VideoError.d.ts new file mode 100644 index 00000000..70065a90 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoError.d.ts @@ -0,0 +1,27 @@ +export type LibraryError = 'library/deallocated' | 'library/application-context-not-found'; +export type PlayerError = 'player/released' | 'player/not-initialized' | 'player/asset-not-initialized' | 'player/invalid-source'; +export type SourceError = 'source/invalid-uri' | 'source/missing-read-file-permission' | 'source/file-does-not-exist' | 'source/failed-to-initialize-asset' | 'source/unsupported-content-type'; +export type VideoViewError = 'view/not-found' | 'view/deallocated' | 'view/picture-in-picture-not-supported'; +export type UnknownError = 'unknown/unknown'; +export type VideoErrorCode = LibraryError | PlayerError | SourceError | VideoViewError | UnknownError; +export declare class VideoError extends Error { + private readonly _code; + private readonly _message; + private readonly _stack?; + get code(): TCode; + get message(): string; + get stack(): string | undefined; + toString(): string; +} +export declare class VideoComponentError extends VideoError { +} +export declare class VideoRuntimeError extends VideoError { +} +/** + * Tries to parse an error coming from native to a typed JS video error. + * @param {VideoError} nativeError The native error instance. This is a JSON in the legacy native module architecture. + * @returns A {@linkcode VideoRuntimeError} or {@linkcode VideoComponentError}, or the `nativeError` itself if it's not parsable + * @method + */ +export declare const tryParseNativeVideoError: (nativeError: T) => (VideoRuntimeError | VideoComponentError) | T; +//# sourceMappingURL=VideoError.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoError.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoError.d.ts.map new file mode 100644 index 00000000..f731add6 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoError.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoError.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoError.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,qBAAqB,GACrB,uCAAuC,CAAC;AAE5C,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,wBAAwB,GACxB,8BAA8B,GAC9B,uBAAuB,CAAC;AAE5B,MAAM,MAAM,WAAW,GACnB,oBAAoB,GACpB,qCAAqC,GACrC,4BAA4B,GAC5B,mCAAmC,GACnC,iCAAiC,CAAC;AAEtC,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,kBAAkB,GAClB,uCAAuC,CAAC;AAE5C,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAE7C,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,WAAW,GACX,WAAW,GACX,cAAc,GACd,YAAY,CAAC;AAEjB,qBAAa,UAAU,CAAC,KAAK,SAAS,cAAc,CAAE,SAAQ,KAAK;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IAEjC,IAAW,IAAI,IAAI,KAAK,CAEvB;IACD,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,KAAK,IAAI,MAAM,GAAG,SAAS,CAErC;IAeM,QAAQ,IAAI,MAAM;CAI1B;AAED,qBAAa,mBAAoB,SAAQ,UAAU,CAAC,cAAc,CAAC;CAAG;AAEtE,qBAAa,iBAAkB,SAAQ,UAAU,CAC/C,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CACxD;CAAG;AAkEJ;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,EACxC,aAAa,CAAC,KACb,CAAC,iBAAiB,GAAG,mBAAmB,CAAC,GAAG,CA6B9C,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts b/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts new file mode 100644 index 00000000..baa92d3e --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts @@ -0,0 +1,37 @@ +import type { VideoOrientation } from './VideoOrientation'; +export interface VideoInformation { + /** + * The bitrate of the video in kbps. + */ + bitrate: number; + /** + * The width of the video in pixels. + */ + width: number; + /** + * The height of the video in pixels. + */ + height: number; + /** + * The duration of the video in seconds. + */ + duration: bigint; + /** + * The file size of the video in bytes. + */ + fileSize: bigint; + /** + * Whether the video is HDR. + */ + isHDR: boolean; + /** + * Whether the video is live + */ + isLive: boolean; + /** + * The orientation of the video. + * see {@link VideoOrientation} + */ + orientation: VideoOrientation; +} +//# sourceMappingURL=VideoInformation.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts.map new file mode 100644 index 00000000..21c4567e --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoInformation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoInformation.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoInformation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,EAAE,gBAAgB,CAAC;CAC/B"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts b/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts new file mode 100644 index 00000000..bb244d1a --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts @@ -0,0 +1,2 @@ +export type VideoOrientation = 'portrait' | 'landscape' | 'portrait-upside-down' | 'landscape-left' | 'landscape-right' | 'square' | 'unknown'; +//# sourceMappingURL=VideoOrientation.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts.map new file mode 100644 index 00000000..84f79fe0 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoOrientation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoOrientation.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoOrientation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,WAAW,GACX,sBAAsB,GACtB,gBAAgB,GAChB,iBAAiB,GACjB,QAAQ,GACR,SAAS,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts b/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts new file mode 100644 index 00000000..26b934e9 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts @@ -0,0 +1,149 @@ +import type { IgnoreSilentSwitchMode } from './IgnoreSilentSwitchMode'; +import type { MixAudioMode } from './MixAudioMode'; +import type { TextTrack } from './TextTrack'; +import type { VideoPlayerSourceBase } from './VideoPlayerSourceBase'; +import type { VideoPlayerStatus } from './VideoPlayerStatus'; +export interface VideoPlayerBase { + /** + * The source of the video. + * Source is immutable. To change the source, you need to call {@link replaceSourceAsync} method. + * see {@link VideoPlayerSourceBase} + */ + readonly source: VideoPlayerSourceBase; + /** + * The status of the player. + * @param idle - The player is idle (source is not loaded) + * @param loading - The player is loading. + * @param readyToPlay - The player is ready to play (source is loaded). + * @param error - The player has an error. + */ + readonly status: VideoPlayerStatus; + /** + * The current time of the video in seconds (1.0 = 1 sec). + * Returns NaN if the current time is not available. + */ + readonly duration: number; + /** + * The volume of the video (0.0 = 0%, 1.0 = 100%). + * @note If the player is {@link muted}, the volume will be 0.0. + */ + volume: number; + /** + * The duration of the video in seconds (1.0 = 1 sec). + * Returns NaN if the duration is not available. + */ + currentTime: number; + /** + * Whether the player is muted. + */ + muted: boolean; + /** + * Whether the player is looped. + */ + loop: boolean; + /** + * Controls the speed at which the player should play. + * @note if rate is = 0, it will pause video. + */ + rate: number; + /** + * Controls the audio mixing mode of the player. + * + * - `mixWithOthers` - Mix with other players. + * - `doNotMix` - Do not mix with other players. + * - `duckOthers` - Duck other players. + * - `auto` - uses default behavior for player. + * + * default is `auto`. + */ + mixAudioMode: MixAudioMode; + /** + * Controls the silent switch mode of the player. + * @note This is only supported on iOS. + * + * - `auto` - uses default behavior for player. + * - `ignore` - ignore the silent switch. + * - `obey` - obey the silent switch. + */ + ignoreSilentSwitchMode: IgnoreSilentSwitchMode; + /** + * Whether the player should play in background. + * + * - `true` - play in background. + * - `false` - pause in background (default). + * + * @note this can override {@link playWhenInactive}. + */ + playInBackground: boolean; + /** + * Whether the player should play when the app is inactive (user opened control center). + * + * - `true` - play when the app is inactive. + * - `false` - pause when the app is inactive (default). + * + * @note this can be overridden by {@link playInBackground}. + * @note This is only supported on iOS. + */ + playWhenInactive: boolean; + /** + * Whether the player is playing. + * @note This is a read-only property. + * @note To pause/resume the player, you need to use {@link play} and {@link pause} methods. + */ + readonly isPlaying: boolean; + /** + * Manually initialize the player. You don't need to call this method manually, unless you set `initializeOnCreation` to false in {@link VideoConfig} + */ + initialize(): Promise; + /** + * Preload the video. + * This is useful to avoid delay when the user plays the video. + * Preloading too many videos can lead to memory issues or performance issues. + */ + preload(): Promise; + /** + * Start playback of player. + */ + play(): void; + /** + * Pause playback of player. + */ + pause(): void; + /** + * Seek by given time. + * If the time is negative, it will seek backward. + * time will be clamped if it is out of range (0 ~ {@link duration}). + * @param time - The time to seek from current time in seconds. + */ + seekBy(time: number): void; + /** + * Seek to a specific time in the video. + * @param time - The time to seek to in seconds. + * @note This have same effect as {@link currentTime} setter. + * @note time will be clamped if it is out of range (0 ~ {@link duration}). + */ + seekTo(time: number): void; + /** + * 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. + * see {@link VideoPlayerSourceBase} + */ + replaceSourceAsync(source: VideoPlayerSourceBase | null): Promise; + /** + * Get all available text tracks for the current source. + * @returns Array of available text tracks + */ + getAvailableTextTracks(): TextTrack[]; + /** + * Select a text track to display. + * @param textTrack - Text track to select, or null to unselect current track + */ + selectTextTrack(textTrack: TextTrack | null): void; + /** + * Get the currently selected text track. + * @returns The currently selected text track, or undefined if none is selected + */ + readonly selectedTrack?: TextTrack; +} +//# sourceMappingURL=VideoPlayerBase.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts.map new file mode 100644 index 00000000..b7fbce68 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerBase.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerBase.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEvC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;;OASG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;;;;;;OAOG;IACH,sBAAsB,EAAE,sBAAsB,CAAC;IAE/C;;;;;;;OAOG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;;;;;OAQG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;OAEG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B;;;;;OAKG;IACH,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;;OAGG;IACH,sBAAsB,IAAI,SAAS,EAAE,CAAC;IAEtC;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IAEnD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;CACpC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts b/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts new file mode 100644 index 00000000..2b2cf59c --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts @@ -0,0 +1,17 @@ +import type { NativeVideoConfig } from './VideoConfig'; +import type { VideoInformation } from './VideoInformation'; +export interface VideoPlayerSourceBase { + /** + * The URI of the asset. + */ + readonly uri: string; + /** + * The config of the asset. + */ + readonly config: NativeVideoConfig; + /** + * Get the information about the asset. + */ + getAssetInformationAsync(): Promise; +} +//# sourceMappingURL=VideoPlayerSourceBase.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts.map new file mode 100644 index 00000000..72055ff7 --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerSourceBase.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerSourceBase.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerSourceBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC;;OAEG;IACH,wBAAwB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvD"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts b/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts new file mode 100644 index 00000000..37921b0e --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts @@ -0,0 +1,9 @@ +/** + * The status of the player. + * @param idle - The player is idle (source is not loaded) + * @param loading - The player is loading (source is loading). + * @param readyToPlay - The player is ready to play (source is loaded). + * @param error - The player has an error (source is not loaded). + */ +export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error'; +//# sourceMappingURL=VideoPlayerStatus.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts.map b/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts.map new file mode 100644 index 00000000..74294cfe --- /dev/null +++ b/lib/typescript/commonjs/src/core/types/VideoPlayerStatus.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerStatus.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerStatus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts b/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts new file mode 100644 index 00000000..573dce4c --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=playerFactory.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts.map b/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts.map new file mode 100644 index 00000000..d5dad934 --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/playerFactory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"playerFactory.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/playerFactory.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts b/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts new file mode 100644 index 00000000..3c957c93 --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts @@ -0,0 +1,28 @@ +import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro'; +import type { VideoConfig, VideoSource } from '../types/VideoConfig'; +/** + * Creates a `VideoPlayerSource` instance from a URI (string). + * + * @param uri - The URI of the video to play + * @returns The `VideoPlayerSource` instance + */ +export declare const createSourceFromUri: (uri: string) => VideoPlayerSource; +/** + * Creates a `VideoPlayerSource` instance from a `VideoConfig`. + * + * @note The `uri` property is required to be a string. + * + * @param config - The `VideoConfig` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export declare const createSourceFromVideoConfig: (config: VideoConfig & { + uri: string; +}) => VideoPlayerSource; +/** + * Creates a `VideoPlayerSource` + * + * @param source - The `VideoSource` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export declare const createSource: (source: VideoSource | VideoConfig | VideoPlayerSource) => VideoPlayerSource; +//# sourceMappingURL=sourceFactory.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts.map b/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts.map new file mode 100644 index 00000000..09f54d62 --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/sourceFactory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sourceFactory.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/sourceFactory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAIV,WAAW,EACX,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAS9B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,sBAM9C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GACtC,QAAQ,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,sBAkCtC,CAAC;AAmBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,WAAW,GAAG,WAAW,GAAG,iBAAiB,KACpD,iBAoCF,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts b/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts new file mode 100644 index 00000000..863d17c3 --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts @@ -0,0 +1,3 @@ +import type { VideoPlayerSource } from "../../spec/nitro/VideoPlayerSource.nitro"; +export declare const isVideoPlayerSource: (obj: any) => obj is VideoPlayerSource; +//# sourceMappingURL=sourceUtils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts.map b/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts.map new file mode 100644 index 00000000..d1016e84 --- /dev/null +++ b/lib/typescript/commonjs/src/core/utils/sourceUtils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sourceUtils.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/sourceUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAElF,eAAO,MAAM,mBAAmB,GAAI,KAAK,GAAG,KAAG,GAAG,IAAI,iBAOrD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts b/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts new file mode 100644 index 00000000..50af5bf8 --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts @@ -0,0 +1,2 @@ +export declare const NativeVideoView: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType | (() => never); +//# sourceMappingURL=NativeVideoView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts.map b/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts.map new file mode 100644 index 00000000..c6647fcc --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/NativeVideoView.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"NativeVideoView.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/NativeVideoView.tsx"],"names":[],"mappings":"AAYA,eAAO,MAAM,eAAe,iLAKrB,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts b/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts new file mode 100644 index 00000000..709f4a29 --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts @@ -0,0 +1,5 @@ +import * as React from 'react'; +import type { VideoViewProps, VideoViewRef } from './ViewViewProps'; +declare const _default: React.MemoExoticComponent>>; +export default _default; +//# sourceMappingURL=VideoView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts.map b/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts.map new file mode 100644 index 00000000..9ce6495d --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/VideoView.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AAqLpE,wBAAqC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts b/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts new file mode 100644 index 00000000..46174f6e --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts @@ -0,0 +1,4 @@ +import type { VideoViewProps, VideoViewRef } from "./ViewViewProps"; +declare const _default: import("react").MemoExoticComponent>>; +export default _default; +//# sourceMappingURL=VideoView.web.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts.map b/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts.map new file mode 100644 index 00000000..201f63de --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/VideoView.web.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/VideoView.web.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AA0EpE,wBAA+B"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts b/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts new file mode 100644 index 00000000..880181d6 --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts @@ -0,0 +1,74 @@ +import type { ViewProps, ViewStyle } from "react-native"; +import type { SurfaceType } from "../../spec/nitro/VideoViewViewManager.nitro"; +import type { VideoViewEvents } from "../types/Events"; +import type { ResizeMode } from "../types/ResizeMode"; +import type { VideoPlayer } from "../VideoPlayer"; +export interface VideoViewProps extends Partial, ViewProps { + /** + * The player to play the video - {@link VideoPlayer} + */ + player: VideoPlayer; + /** + * The style of the video view - {@link ViewStyle} + */ + style?: ViewStyle; + /** + * Whether to show the controls. Defaults to false. + */ + controls?: boolean; + /** + * Whether to enable & show the picture in picture button in native controls. Defaults to false. + */ + pictureInPicture?: boolean; + /** + * Whether to automatically enter picture in picture mode when the video is playing. Defaults to false. + */ + autoEnterPictureInPicture?: boolean; + /** + * How the video should be resized to fit the view. Defaults to 'none'. + * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view + * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop) + * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio + * - 'none': Do not resize the video + */ + resizeMode?: ResizeMode; + /** + * Whether to keep the screen awake while the video view is mounted. Defaults to true. + */ + keepScreenAwake?: boolean; + /** + * The type of underlying native view. Defaults to 'surface'. + * - 'surface': Uses a SurfaceView on Android. More performant, but cannot be animated or transformed. + * - 'texture': Uses a TextureView on Android. Less performant, but can be animated and transformed. + * + * Only applicable on Android + * + * @default 'surface' + * @platform android + */ + surfaceType?: SurfaceType; +} +export interface VideoViewRef { + /** + * Enter fullscreen mode + */ + enterFullscreen: () => void; + /** + * Exit fullscreen mode + */ + exitFullscreen: () => void; + /** + * Enter picture in picture mode + */ + enterPictureInPicture: () => void; + /** + * Exit picture in picture mode + */ + exitPictureInPicture: () => void; + /** + * Check if picture in picture mode is supported + * @returns true if picture in picture mode is supported, false otherwise + */ + canEnterPictureInPicture: () => boolean; +} +//# sourceMappingURL=ViewViewProps.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts.map b/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts.map new file mode 100644 index 00000000..f979b856 --- /dev/null +++ b/lib/typescript/commonjs/src/core/video-view/ViewViewProps.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ViewViewProps.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/ViewViewProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,eAAe,CAAC,EAAE,SAAS;IACzE;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B;;OAEG;IACH,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC;;OAEG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC;;;OAGG;IACH,wBAAwB,EAAE,MAAM,OAAO,CAAC;CACzC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/@types.d.ts b/lib/typescript/commonjs/src/expo-plugins/@types.d.ts new file mode 100644 index 00000000..b01557a9 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/@types.d.ts @@ -0,0 +1,34 @@ +export type ConfigProps = { + /** + * Whether to use react-native-test-app compatible mode. + * @default false + */ + reactNativeTestApp?: boolean; + /** + * Apply configs to be able to use Picture-in-picture on Android. + * @default false + */ + enableAndroidPictureInPicture?: boolean; + /** + * Whether to enable background audio feature. + * @default false + */ + enableBackgroundAudio?: boolean; + /** + * Android extensions for ExoPlayer - you can choose which extensions to include in order to reduce the size of the app. + * @default { useExoplayerDash: true, useExoplayerHls: true } + */ + androidExtensions?: { + /** + * Whether to use ExoPlayer's Dash extension. + * @default true + */ + useExoplayerDash?: boolean; + /** + * Whether to use ExoPlayer's HLS extension. + * @default true + */ + useExoplayerHls?: boolean; + }; +}; +//# sourceMappingURL=@types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/@types.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/@types.d.ts.map new file mode 100644 index 00000000..ae3b7af4 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/@types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"@types.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/@types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;IAExC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,iBAAiB,CAAC,EAAE;QAClB;;;WAGG;QACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAE3B;;;WAGG;QACH,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts b/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts new file mode 100644 index 00000000..05880eac --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts @@ -0,0 +1,5 @@ +export declare function getPackageInfo(): { + name: string; + version: string; +}; +//# sourceMappingURL=getPackageInfo.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts.map new file mode 100644 index 00000000..503842b8 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/getPackageInfo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"getPackageInfo.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/getPackageInfo.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAsBlE"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts b/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts new file mode 100644 index 00000000..b221d984 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts @@ -0,0 +1,8 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +import type { ConfigProps } from './@types'; +/** + * Sets the Android extensions for ExoPlayer in `gradle.properties`. + * You can choose which extensions to include in order to reduce the size of the app. + */ +export declare const withAndroidExtensions: ConfigPlugin; +//# sourceMappingURL=withAndroidExtensions.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts.map new file mode 100644 index 00000000..d499b89b --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withAndroidExtensions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidExtensions.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withAndroidExtensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAAY,CAC9C,WAAW,CAAC,mBAAmB,CAAC,CAqCjC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts b/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts new file mode 100644 index 00000000..2bbffae8 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts @@ -0,0 +1,3 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +export declare const withAndroidPictureInPicture: ConfigPlugin; +//# sourceMappingURL=withAndroidPictureInPicture.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts.map new file mode 100644 index 00000000..dd0f2cd7 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withAndroidPictureInPicture.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidPictureInPicture.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withAndroidPictureInPicture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,2BAA2B,EAAE,YAAY,CAAC,OAAO,CAwB7D,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts b/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts new file mode 100644 index 00000000..65196e78 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts @@ -0,0 +1,7 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +/** + * Sets `UIBackgroundModes` in `Info.plist` to enable background audio on Apple platforms. + * This is required for audio to continue playing when the app is in the background. + */ +export declare const withBackgroundAudio: ConfigPlugin; +//# sourceMappingURL=withBackgroundAudio.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts.map new file mode 100644 index 00000000..23308807 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withBackgroundAudio.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withBackgroundAudio.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withBackgroundAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,OAAO,CAmBrD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts b/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts new file mode 100644 index 00000000..5c4dbd4b --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts @@ -0,0 +1,5 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +import type { ConfigProps } from './@types'; +declare const _default: ConfigPlugin; +export default _default; +//# sourceMappingURL=withReactNativeVideo.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts.map new file mode 100644 index 00000000..b4542c5d --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/withReactNativeVideo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withReactNativeVideo.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withReactNativeVideo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;;AA2B5C,wBAA+D"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts b/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts new file mode 100644 index 00000000..20be5197 --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts @@ -0,0 +1,2 @@ +export declare const writeToPodfile: (projectRoot: string, key: string, value: string, testApp?: boolean) => void; +//# sourceMappingURL=writeToPodfile.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts.map b/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts.map new file mode 100644 index 00000000..62e7906b --- /dev/null +++ b/lib/typescript/commonjs/src/expo-plugins/writeToPodfile.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"writeToPodfile.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/writeToPodfile.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,GACzB,aAAa,MAAM,EACnB,KAAK,MAAM,EACX,OAAO,MAAM,EACb,UAAS,OAAe,SAiBzB,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/index.d.ts b/lib/typescript/commonjs/src/index.d.ts new file mode 100644 index 00000000..f0a87ccb --- /dev/null +++ b/lib/typescript/commonjs/src/index.d.ts @@ -0,0 +1,14 @@ +export { useEvent } from "./core/hooks/useEvent"; +export { useVideoPlayer } from "./core/hooks/useVideoPlayer"; +export type * from "./core/types/Events"; +export type { IgnoreSilentSwitchMode } from "./core/types/IgnoreSilentSwitchMode"; +export type { MixAudioMode } from "./core/types/MixAudioMode"; +export type { ResizeMode } from "./core/types/ResizeMode"; +export type { TextTrack } from "./core/types/TextTrack"; +export type { VideoConfig, VideoSource } from "./core/types/VideoConfig"; +export type { LibraryError, PlayerError, SourceError, UnknownError, VideoComponentError, VideoError, VideoErrorCode, VideoRuntimeError, VideoViewError, } from "./core/types/VideoError"; +export type { VideoPlayerStatus } from "./core/types/VideoPlayerStatus"; +export { VideoPlayer } from "./core/VideoPlayer"; +export { default as VideoView } from "./core/video-view/VideoView"; +export type { VideoViewProps, VideoViewRef, } from "./core/video-view/ViewViewProps"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/index.d.ts.map b/lib/typescript/commonjs/src/index.d.ts.map new file mode 100644 index 00000000..f715f6b5 --- /dev/null +++ b/lib/typescript/commonjs/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,mBAAmB,qBAAqB,CAAC;AACzC,YAAY,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EACV,cAAc,EACd,YAAY,GACb,MAAM,iCAAiC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts b/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts new file mode 100644 index 00000000..d3fe0e93 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts @@ -0,0 +1,12 @@ +import type { ViewProps } from 'react-native'; +import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes'; +type OnNitroIdChangeEvent = Readonly<{ + nitroId: Int32; +}>; +export interface ViewViewNativeProps extends ViewProps { + nitroId: Int32; + onNitroIdChange?: DirectEventHandler; +} +declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType; +export default _default; +//# sourceMappingURL=VideoViewNativeComponent.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts.map b/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts.map new file mode 100644 index 00000000..21f1a01f --- /dev/null +++ b/lib/typescript/commonjs/src/spec/fabric/VideoViewNativeComponent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/fabric/VideoViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,kBAAkB,EAClB,KAAK,EACN,MAAM,2CAA2C,CAAC;AAGnD,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,WAAW,mBAAoB,SAAQ,SAAS;IACpD,OAAO,EAAE,KAAK,CAAC;IACf,eAAe,CAAC,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,CAAC;CAC5D;;AAED,wBAA2E"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts b/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts new file mode 100644 index 00000000..2b52c445 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts @@ -0,0 +1,39 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { TextTrack } from '../../core/types/TextTrack'; +import type { VideoPlayerBase } from '../../core/types/VideoPlayerBase'; +import type { VideoPlayerEventEmitter } from './VideoPlayerEventEmitter.nitro'; +import type { VideoPlayerSource } from './VideoPlayerSource.nitro'; +export interface VideoPlayer extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerBase { + readonly source: VideoPlayerSource; + readonly eventEmitter: VideoPlayerEventEmitter; + /** + * Show playback controls in the notifications area + * + * @note on Android, this can be overridden by {@linkcode VideoPlayer.playInBackground}, as Android requires + * a foreground service to show notifications while the app is in the background. + * + * @default false + */ + showNotificationControls: boolean; + replaceSourceAsync(source: VideoPlayerSource | null): Promise; + /** + * Get all available text tracks for the current source. + * @returns Array of available text tracks + */ + getAvailableTextTracks(): TextTrack[]; + /** + * Select a text track to display. + * @param textTrack - Text track to select, or null to unselect current track + */ + selectTextTrack(textTrack: TextTrack | null): void; +} +export interface VideoPlayerFactory extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}> { + createPlayer(source: VideoPlayerSource): VideoPlayer; +} +//# sourceMappingURL=VideoPlayer.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts.map b/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts.map new file mode 100644 index 00000000..edbf9c10 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayer.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayer.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,WAAW,WACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EACvD,eAAe;IAEjB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAGnC,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAE/C;;;;;;;OAOG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAElC,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,sBAAsB,IAAI,SAAS,EAAE,CAAC;IAEtC;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,kBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IACzD,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAAC;CACtD"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts new file mode 100644 index 00000000..1018d261 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts @@ -0,0 +1,13 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { VideoPlayerEvents } from '../../core/types/Events'; +/** + * The holder of the video player events. + * @platform iOS + * @platform android + */ +export interface VideoPlayerEventEmitter extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerEvents { +} +//# sourceMappingURL=VideoPlayerEventEmitter.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map new file mode 100644 index 00000000..d42cb9c9 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerEventEmitter.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayerEventEmitter.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,uBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EAGvD,iBAAiB;CAAG"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts new file mode 100644 index 00000000..b5251320 --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts @@ -0,0 +1,21 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { NativeVideoConfig } from '../../core/types/VideoConfig'; +import type { VideoPlayerSourceBase } from '../../core/types/VideoPlayerSourceBase'; +/** + * A source for a {@link VideoPlayer}. + * Source cannot be changed after it is created. If you need to update the source, you need to create a new one. + * It provides functions to get information about the asset. + */ +export interface VideoPlayerSource extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerSourceBase { +} +export interface VideoPlayerSourceFactory extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}> { + fromUri(uri: string): VideoPlayerSource; + fromVideoConfig(config: NativeVideoConfig): VideoPlayerSource; +} +//# sourceMappingURL=VideoPlayerSource.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map new file mode 100644 index 00000000..e766ab6b --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerSource.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayerSource.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAEpF;;;;GAIG;AACH,MAAM,WAAW,iBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EACvD,qBAAqB;CAAG;AAE5B,MAAM,WAAW,wBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IACzD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;CAC/D"} \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts b/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts new file mode 100644 index 00000000..daafad1b --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts @@ -0,0 +1,2 @@ +export type SurfaceType = 'surface' | 'texture'; +//# sourceMappingURL=VideoViewViewManager.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map b/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map new file mode 100644 index 00000000..c5841d9c --- /dev/null +++ b/lib/typescript/commonjs/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoViewViewManager.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoViewViewManager.nitro.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/package.json b/lib/typescript/module/package.json new file mode 100644 index 00000000..089153bc --- /dev/null +++ b/lib/typescript/module/package.json @@ -0,0 +1 @@ +{"type":"module"} diff --git a/lib/typescript/module/src/core/VideoPlayer.d.ts b/lib/typescript/module/src/core/VideoPlayer.d.ts new file mode 100644 index 00000000..9143bf43 --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayer.d.ts @@ -0,0 +1,57 @@ +import type { VideoPlayer as VideoPlayerImpl } from '../spec/nitro/VideoPlayer.nitro'; +import type { VideoPlayerSource } from '../spec/nitro/VideoPlayerSource.nitro'; +import type { IgnoreSilentSwitchMode } from './types/IgnoreSilentSwitchMode'; +import type { MixAudioMode } from './types/MixAudioMode'; +import type { TextTrack } from './types/TextTrack'; +import type { NoAutocomplete } from './types/Utils'; +import type { VideoConfig, VideoSource } from './types/VideoConfig'; +import type { VideoPlayerBase } from './types/VideoPlayerBase'; +import type { VideoPlayerStatus } from './types/VideoPlayerStatus'; +import { VideoPlayerEvents } from './VideoPlayerEvents'; +declare class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase { + protected player: VideoPlayerImpl; + constructor(source: VideoSource | VideoConfig | VideoPlayerSource); + get source(): VideoPlayerSource; + get status(): VideoPlayerStatus; + get duration(): number; + get volume(): number; + set volume(value: number); + get currentTime(): number; + set currentTime(value: number); + get muted(): boolean; + set muted(value: boolean); + get loop(): boolean; + set loop(value: boolean); + get rate(): number; + set rate(value: number); + get mixAudioMode(): MixAudioMode; + set mixAudioMode(value: MixAudioMode); + get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode; + set ignoreSilentSwitchMode(value: IgnoreSilentSwitchMode); + get playInBackground(): boolean; + set playInBackground(value: boolean); + get playWhenInactive(): boolean; + set playWhenInactive(value: boolean); + get isPlaying(): boolean; + get showNotificationControls(): boolean; + set showNotificationControls(value: boolean); + initialize(): Promise; + preload(): Promise; + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release(): void; + play(): void; + pause(): void; + seekBy(time: number): void; + seekTo(time: number): void; + replaceSourceAsync(source: VideoSource | VideoConfig | NoAutocomplete | null): Promise; + getAvailableTextTracks(): TextTrack[]; + selectTextTrack(textTrack: TextTrack | null): void; + get selectedTrack(): TextTrack | undefined; +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/VideoPlayer.d.ts.map b/lib/typescript/module/src/core/VideoPlayer.d.ts.map new file mode 100644 index 00000000..f69e717a --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAM,WAAY,SAAQ,iBAAkB,YAAW,eAAe;IACpE,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC;gBAEtB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,iBAAiB;IA2DjE,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAGD,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAGD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAGD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAEvB;IAGD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAE5B;IAGD,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAGD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAGD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAGD,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,YAAY,CAAC,KAAK,EAAE,YAAY,EAEnC;IAGD,IAAI,sBAAsB,IAAI,sBAAsB,CAEnD;IAED,IAAI,sBAAsB,CAAC,KAAK,EAAE,sBAAsB,EAQvD;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAElC;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAElC;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,wBAAwB,IAAI,OAAO,CAEtC;IAED,IAAI,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAE1C;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAIf,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQpB,kBAAkB,CACtB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC,iBAAiB,CAAC,GAAG,IAAI,GAC3E,OAAO,CAAC,IAAI,CAAC;IAWhB,sBAAsB,IAAI,SAAS,EAAE;IASrC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IASlD,IAAI,aAAa,IAAI,SAAS,GAAG,SAAS,CAEzC;CACF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/VideoPlayer.web.d.ts b/lib/typescript/module/src/core/VideoPlayer.web.d.ts new file mode 100644 index 00000000..54011de9 --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayer.web.d.ts @@ -0,0 +1,58 @@ +import shaka from "shaka-player"; +import type { VideoPlayerSource } from "../spec/nitro/VideoPlayerSource.nitro"; +import type { IgnoreSilentSwitchMode } from "./types/IgnoreSilentSwitchMode"; +import type { MixAudioMode } from "./types/MixAudioMode"; +import type { TextTrack } from "./types/TextTrack"; +import type { NoAutocomplete } from "./types/Utils"; +import type { VideoConfig, VideoSource } from "./types/VideoConfig"; +import type { VideoPlayerBase } from "./types/VideoPlayerBase"; +import type { VideoPlayerStatus } from "./types/VideoPlayerStatus"; +import { VideoPlayerEvents } from "./VideoPlayerEvents"; +declare class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase { + protected player: shaka.Player; + protected video: HTMLVideoElement; + protected headers: Record; + constructor(source: VideoSource | VideoConfig | VideoPlayerSource); + __getNativeRef(): HTMLVideoElement; + get source(): VideoPlayerSource; + get status(): VideoPlayerStatus; + get duration(): number; + get volume(): number; + set volume(value: number); + get currentTime(): number; + set currentTime(value: number); + get muted(): boolean; + set muted(value: boolean); + get loop(): boolean; + set loop(value: boolean); + get rate(): number; + set rate(value: number); + get mixAudioMode(): MixAudioMode; + set mixAudioMode(_: MixAudioMode); + get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode; + set ignoreSilentSwitchMode(_: IgnoreSilentSwitchMode); + get playInBackground(): boolean; + set playInBackground(_: boolean); + get playWhenInactive(): boolean; + set playWhenInactive(_: boolean); + get isPlaying(): boolean; + initialize(): Promise; + preload(): Promise; + /** + * Releases the player's native resources and releases native state. + * After calling this method, the player is no longer usable. + * Accessing any properties or methods of the player after calling this method will throw an error. + * If you want to clean player resource use `replaceSourceAsync` with `null` instead. + */ + release(): void; + play(): void; + pause(): void; + seekBy(time: number): void; + seekTo(time: number): void; + replaceSourceAsync(source: VideoSource | VideoConfig | NoAutocomplete | null): Promise; + getAvailableTextTracks(): TextTrack[]; + selectTextTrack(textTrack: TextTrack | null): void; + get selectedTrack(): TextTrack | undefined; +} +export { VideoPlayer }; +//# sourceMappingURL=VideoPlayer.web.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/VideoPlayer.web.d.ts.map b/lib/typescript/module/src/core/VideoPlayer.web.d.ts.map new file mode 100644 index 00000000..152dbada --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayer.web.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.web.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayer.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,cAAM,WAAY,SAAQ,iBAAkB,YAAW,eAAe;IACpE,SAAS,CAAC,MAAM,eAAsB;IACtC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;gBAEnC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,iBAAiB;IAoBjE,cAAc;IAuBd,IAAI,MAAM,IAAI,iBAAiB,CAM9B;IAGD,IAAI,MAAM,IAAI,iBAAiB,CAS9B;IAGD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAGD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAEvB;IAGD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAE5B;IAGD,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAGD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAGD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAErB;IAGD,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,YAAY,CAAC,CAAC,EAAE,YAAY,EAM/B;IAGD,IAAI,sBAAsB,IAAI,sBAAsB,CAEnD;IAED,IAAI,sBAAsB,CAAC,CAAC,EAAE,sBAAsB,EAMnD;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAM9B;IAGD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAM9B;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAIf,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQpB,kBAAkB,CACtB,MAAM,EACF,WAAW,GACX,WAAW,GACX,cAAc,CAAC,iBAAiB,CAAC,GACjC,IAAI,GACP,OAAO,CAAC,IAAI,CAAC;IAuBhB,sBAAsB,IAAI,SAAS,EAAE;IASrC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAUlD,IAAI,aAAa,IAAI,SAAS,GAAG,SAAS,CAEzC;CACF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/VideoPlayerEvents.d.ts b/lib/typescript/module/src/core/VideoPlayerEvents.d.ts new file mode 100644 index 00000000..711e6068 --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayerEvents.d.ts @@ -0,0 +1,20 @@ +import { type VideoPlayerEvents as NativePlayerEvents, type AllPlayerEvents as PlayerEvents } from "./types/Events"; +export declare class VideoPlayerEvents { + protected eventEmitter: NativePlayerEvents; + protected eventListeners: Partial void>>>; + protected readonly supportedEvents: (keyof PlayerEvents)[]; + constructor(eventEmitter: NativePlayerEvents); + protected triggerEvent(event: Event, ...params: Parameters): boolean; + addEventListener(event: Event, callback: PlayerEvents[Event]): void; + removeEventListener(event: Event, callback: PlayerEvents[Event]): void; + /** + * Clears all events from the event emitter. + */ + clearAllEvents(): void; + /** + * Clears a specific event from the event emitter. + * @param event - The name of the event to clear. + */ + clearEvent(event: keyof PlayerEvents): void; +} +//# sourceMappingURL=VideoPlayerEvents.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/VideoPlayerEvents.d.ts.map b/lib/typescript/module/src/core/VideoPlayerEvents.d.ts.map new file mode 100644 index 00000000..d2993d16 --- /dev/null +++ b/lib/typescript/module/src/core/VideoPlayerEvents.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerEvents.d.ts","sourceRoot":"","sources":["../../../../../src/core/VideoPlayerEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,IAAI,kBAAkB,EAC5C,KAAK,eAAe,IAAI,YAAY,EACrC,MAAM,gBAAgB,CAAC;AAExB,qBAAa,iBAAiB;IAC5B,SAAS,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC3C,SAAS,CAAC,cAAc,EAAE,OAAO,CAC/B,MAAM,CAAC,MAAM,YAAY,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAC5D,CAAM;IAEP,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,YAAY,CAAC,EAAE,CACtC;gBAER,YAAY,EAAE,kBAAkB;IAQ5C,SAAS,CAAC,YAAY,CAAC,KAAK,SAAS,MAAM,YAAY,EACrD,KAAK,EAAE,KAAK,EACZ,GAAG,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GACzC,OAAO;IAQV,gBAAgB,CAAC,KAAK,SAAS,MAAM,YAAY,EAC/C,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC;IAM/B,mBAAmB,CAAC,KAAK,SAAS,MAAM,YAAY,EAClD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC;IAK/B;;OAEG;IACH,cAAc;IAMd;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,YAAY;CAGrC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/WebEventEmiter.d.ts b/lib/typescript/module/src/core/WebEventEmiter.d.ts new file mode 100644 index 00000000..937443e1 --- /dev/null +++ b/lib/typescript/module/src/core/WebEventEmiter.d.ts @@ -0,0 +1,45 @@ +import type { BandwidthData, onLoadData, onLoadStartData, onPlaybackStateChangeData, onProgressData, onVolumeChangeData, AllPlayerEvents as PlayerEvents, TimedMetadata } from "./types/Events"; +import type { TextTrack } from "./types/TextTrack"; +import type { VideoRuntimeError } from "./types/VideoError"; +import type { VideoPlayerStatus } from "./types/VideoPlayerStatus"; +export declare class WebEventEmiter implements PlayerEvents { + private video; + private _isBuferring; + constructor(video: HTMLVideoElement); + destroy(): void; + _onTimeUpdate(): void; + _onCanPlay(): void; + _onWaiting(): void; + _onDurationChange(): void; + _onEnded(): void; + _onLoadStart(): void; + _onPlay(): void; + _onPause(): void; + _onRateChange(): void; + _onLoadedData(): void; + _onSeeked(): void; + _onVolumeChange(): void; + _onError(): void; + NOOP: () => void; + onError: (error: VideoRuntimeError) => void; + onAudioBecomingNoisy: () => void; + onAudioFocusChange: (hasAudioFocus: boolean) => void; + onBandwidthUpdate: (data: BandwidthData) => void; + onBuffer: (buffering: boolean) => void; + onControlsVisibleChange: (visible: boolean) => void; + onEnd: () => void; + onExternalPlaybackChange: (externalPlaybackActive: boolean) => void; + onLoad: (data: onLoadData) => void; + onLoadStart: (data: onLoadStartData) => void; + onPlaybackStateChange: (data: onPlaybackStateChangeData) => void; + onPlaybackRateChange: (rate: number) => void; + onProgress: (data: onProgressData) => void; + onReadyToDisplay: () => void; + onSeek: (seekTime: number) => void; + onTimedMetadata: (metadata: TimedMetadata) => void; + onTextTrackDataChanged: (texts: string[]) => void; + onTrackChange: (track: TextTrack | null) => void; + onVolumeChange: (data: onVolumeChangeData) => void; + onStatusChange: (status: VideoPlayerStatus) => void; +} +//# sourceMappingURL=WebEventEmiter.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/WebEventEmiter.d.ts.map b/lib/typescript/module/src/core/WebEventEmiter.d.ts.map new file mode 100644 index 00000000..11b34110 --- /dev/null +++ b/lib/typescript/module/src/core/WebEventEmiter.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"WebEventEmiter.d.ts","sourceRoot":"","sources":["../../../../../src/core/WebEventEmiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,eAAe,EACf,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,eAAe,IAAI,YAAY,EAC/B,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,cAAe,YAAW,YAAY;IAGrC,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,YAAY,CAAS;gBAET,KAAK,EAAE,gBAAgB;IAoD3C,OAAO;IAwBP,aAAa;IASb,UAAU;IAKV,UAAU;IAMV,iBAAiB;IAUjB,QAAQ;IAKR,YAAY;IAyBZ,OAAO;IAOP,QAAQ;IAOR,aAAa;IAIb,aAAa;IAIb,SAAS;IAIT,eAAe;IAIf,QAAQ;IAIR,IAAI,aAAY;IAEhB,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAa;IACxD,oBAAoB,EAAE,MAAM,IAAI,CAAa;IAC7C,kBAAkB,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAa;IACjE,iBAAiB,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAa;IAC7D,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAa;IACnD,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAa;IAChE,KAAK,EAAE,MAAM,IAAI,CAAa;IAC9B,wBAAwB,EAAE,CAAC,sBAAsB,EAAE,OAAO,KAAK,IAAI,CACvD;IACZ,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAa;IAC/C,WAAW,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAa;IACzD,qBAAqB,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAa;IAC7E,oBAAoB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAa;IACzD,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAa;IACvD,gBAAgB,EAAE,MAAM,IAAI,CAAa;IACzC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAa;IAC/C,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAa;IAC/D,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAa;IAC9D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAa;IAC7D,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAa;IAC/D,cAAc,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAa;CACjE"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useEvent.d.ts b/lib/typescript/module/src/core/hooks/useEvent.d.ts new file mode 100644 index 00000000..3f27f22d --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useEvent.d.ts @@ -0,0 +1,11 @@ +import type { AllPlayerEvents } from '../types/Events'; +import type { VideoPlayer } from '../VideoPlayer'; +/** + * Attaches an event listener to a `VideoPlayer` instance for a specified event. + * + * @param player - The player to attach the event to + * @param event - The name of the event to attach the callback to + * @param callback - The callback for the event + */ +export declare const useEvent: (player: VideoPlayer, event: T, callback: AllPlayerEvents[T]) => void; +//# sourceMappingURL=useEvent.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useEvent.d.ts.map b/lib/typescript/module/src/core/hooks/useEvent.d.ts.map new file mode 100644 index 00000000..1640535b --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useEvent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useEvent.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useEvent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,eAAe,EACtD,QAAQ,WAAW,EACnB,OAAO,CAAC,EACR,UAAU,eAAe,CAAC,CAAC,CAAC,SAO7B,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts b/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts new file mode 100644 index 00000000..ec6b0c60 --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=useManagedInstance.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts.map b/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts.map new file mode 100644 index 00000000..6457fb74 --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useManagedInstance.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useManagedInstance.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useManagedInstance.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts b/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts new file mode 100644 index 00000000..def17916 --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts @@ -0,0 +1,13 @@ +import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro'; +import type { NoAutocomplete } from '../types/Utils'; +import type { VideoConfig, VideoSource } from '../types/VideoConfig'; +import { VideoPlayer } from '../VideoPlayer'; +/** + * Creates a `VideoPlayer` instance and manages its lifecycle. + * + * @param source - The source of the video to play + * @param setup - A function to setup the player + * @returns The `VideoPlayer` instance + */ +export declare const useVideoPlayer: (source: VideoConfig | VideoSource | NoAutocomplete, setup?: (player: VideoPlayer) => void) => VideoPlayer; +//# sourceMappingURL=useVideoPlayer.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts.map b/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts.map new file mode 100644 index 00000000..f81150c5 --- /dev/null +++ b/lib/typescript/module/src/core/hooks/useVideoPlayer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useVideoPlayer.d.ts","sourceRoot":"","sources":["../../../../../../src/core/hooks/useVideoPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAc7C;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC,iBAAiB,CAAC,EACrE,QAAQ,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,gBAgBtC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/BufferConfig.d.ts b/lib/typescript/module/src/core/types/BufferConfig.d.ts new file mode 100644 index 00000000..d12f642d --- /dev/null +++ b/lib/typescript/module/src/core/types/BufferConfig.d.ts @@ -0,0 +1,97 @@ +export interface LivePlaybackParams { + /** + * Minimum playback speed for catching up to target live offset. + * @platform android + */ + minPlaybackSpeed?: number; + /** + * Maximum playback speed for catching up to target live offset. + * @platform android + */ + maxPlaybackSpeed?: number; + /** + * Maximum allowed live offset. The player won’t exceed this limit. + * @platform android + */ + maxOffsetMs?: number; + /** + * Minimum allowed live offset. The player won’t go below this limit. + * @platform android + */ + minOffsetMs?: number; + /** + * Target live offset. The player will try to maintain this offset. + * @platform android, ios, visionOS, tvOS + */ + targetOffsetMs?: number; +} +interface Resolution { + width: number; + height: number; +} +export interface BufferConfig { + /** + * Configuration for live playback. + */ + livePlayback?: LivePlaybackParams; + /** + * Minimum duration (ms) the player will attempt to keep buffered. + * @default 5000 + * @platform android + */ + minBufferMs?: number; + /** + * Maximum duration (ms) the player will attempt to keep buffered. + * @default 10000 + * @platform android + */ + maxBufferMs?: number; + /** + * Duration (ms) of media that must be buffered for playback to start or resume following a user action such as a seek. + * @default 1000 + * @platform android + */ + bufferForPlaybackMs?: number; + /** + * Duration (ms) of media that must be buffered for playback to resume after a rebuffer. + * @default 2000 + * @platform android + */ + bufferForPlaybackAfterRebufferMs?: number; + /** + * Duration (ms) of media that must be buffered before it can be played from the back buffer. + * @platform android + */ + backBufferDurationMs?: number; + /** + * The preferred duration (ms) of media that the player will attempt to retain in the buffer. + * @platform ios, visionOS, tvOS + */ + preferredForwardBufferDurationMs?: number; + /** + * The desired limit, in bits per second, of network bandwidth used for loading the current item. + * + * You can use {@linkcode preferredPeakBitRateForExpensiveNetworks} to set a different bit rate when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredPeakBitRate?: number; + /** + * The preferred maximum resolution of the video. + * + * You can use {@linkcode preferredMaximumResolutionForExpensiveNetworks} to set a different resolution when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredMaximumResolution?: Resolution; + /** + * The desired limit, in bits per second, of network bandwidth used for loading the current item when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredPeakBitRateForExpensiveNetworks?: number; + /** + * The preferred maximum resolution of the video when on an expensive network (e.g. cellular). + * @platform ios, visionOS, tvOS + */ + preferredMaximumResolutionForExpensiveNetworks?: Resolution; +} +export {}; +//# sourceMappingURL=BufferConfig.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/BufferConfig.d.ts.map b/lib/typescript/module/src/core/types/BufferConfig.d.ts.map new file mode 100644 index 00000000..b4bed131 --- /dev/null +++ b/lib/typescript/module/src/core/types/BufferConfig.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"BufferConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/BufferConfig.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAIlC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAI9B;;;OAGG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,UAAU,CAAC;IACxC;;;OAGG;IACH,wCAAwC,CAAC,EAAE,MAAM,CAAC;IAClD;;;OAGG;IACH,8CAA8C,CAAC,EAAE,UAAU,CAAC;CAC7D"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/DrmParams.d.ts b/lib/typescript/module/src/core/types/DrmParams.d.ts new file mode 100644 index 00000000..d19b21e1 --- /dev/null +++ b/lib/typescript/module/src/core/types/DrmParams.d.ts @@ -0,0 +1,64 @@ +/** + * Headers type specifically for DRM license requests + */ +export interface DrmParams { + /** + * The license URL for the DRM license request. + * @platform iOS, visionOS + */ + licenseUrl?: string; + /** + * The certificate URL for the DRM license request. + * @platform iOS, visionOS + */ + certificateUrl?: string; + /** + * The content ID for the DRM license request. + * @platform iOS, visionOS + */ + contentId?: string; + /** + * The type of DRM to use. + * @platform Android, iOS, visionOS + */ + type?: DRMType; + /** + * The headers to send with the DRM license request. + * @platform Android, iOS, visionOS + */ + licenseHeaders?: Record; + /** + * Whether to allow multiple sessions for the DRM license request. + * @platform Android + */ + multiSession?: boolean; + /** + * A function to get the license for the DRM license request. + * @platform iOS + */ + getLicense?: (payload: OnGetLicensePayload) => Promise; +} +interface OnGetLicensePayload { + /** + * The content ID for the DRM license request. + * This is typically a unique identifier for the content being played. + */ + contentId: string; + /** + * The license URL for the DRM license request. + */ + licenseUrl: string; + /** + * The key URL for the DRM license request. + * Typically starts with starting with skd:// or clearkey:// + */ + keyUrl: string; + /** + * The secure playback context (SPC) for the DRM license request. + * This is typically a base64-encoded string that contains information about the playback environment. + */ + spc: string; +} +type DRMType = 'widevine' | 'fairplay' | (string & {}); +export {}; +//# sourceMappingURL=DrmParams.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/DrmParams.d.ts.map b/lib/typescript/module/src/core/types/DrmParams.d.ts.map new file mode 100644 index 00000000..0f001621 --- /dev/null +++ b/lib/typescript/module/src/core/types/DrmParams.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DrmParams.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/DrmParams.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChE;AAED,UAAU,mBAAmB;IAC3B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,KAAK,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/Events.d.ts b/lib/typescript/module/src/core/types/Events.d.ts new file mode 100644 index 00000000..af4270a4 --- /dev/null +++ b/lib/typescript/module/src/core/types/Events.d.ts @@ -0,0 +1,221 @@ +import type { TextTrack } from './TextTrack'; +import type { VideoRuntimeError } from './VideoError'; +import type { VideoOrientation } from './VideoOrientation'; +import type { VideoPlayerSourceBase } from './VideoPlayerSourceBase'; +import type { VideoPlayerStatus } from './VideoPlayerStatus'; +export interface VideoPlayerEvents { + /** + * Called when the audio becomes noisy. + * @platform Android + */ + onAudioBecomingNoisy: () => void; + /** + * Called when the audio focus changes. + * @param hasAudioFocus Whether the audio has focus. + * @platform Android + */ + onAudioFocusChange: (hasAudioFocus: boolean) => void; + /** + * Called when the bandwidth of the video changes. + */ + onBandwidthUpdate: (data: BandwidthData) => void; + /** + * Called when the video is buffering. + * @param buffering Whether the video is buffering. + */ + onBuffer: (buffering: boolean) => void; + /** + * Called when the video view's controls visibility changes. + * @param visible Whether the video view's controls are visible. + * @platform Android, Ios + */ + onControlsVisibleChange: (visible: boolean) => void; + /** + * Called when the video ends. + */ + onEnd: () => void; + /** + * Called when the external playback state changes. + * @param externalPlaybackActive Whether the external playback is active. + * @platform iOS + */ + onExternalPlaybackChange: (externalPlaybackActive: boolean) => void; + /** + * Called when the video is loaded. + * @note onLoadStart -> initialize the player -> onLoad + */ + onLoad: (data: onLoadData) => void; + /** + * Called when the video starts loading. + * @note onLoadStart -> initialize the player -> onLoad + */ + onLoadStart: (data: onLoadStartData) => void; + /** + * Called when the player playback state changes. + */ + onPlaybackStateChange: (data: onPlaybackStateChangeData) => void; + /** + * Called when the player playback rate changes. + */ + onPlaybackRateChange: (rate: number) => void; + /** + * Called when the player progress changes. + */ + onProgress: (data: onProgressData) => void; + /** + * Called when the video is ready to display. + */ + onReadyToDisplay: () => void; + /** + * Called when the player seeks. + */ + onSeek: (seekTime: number) => void; + /** + * Called when player receives timed metadata. + * @platform Android, Ios + */ + onTimedMetadata: (metadata: TimedMetadata) => void; + /** + * Called when the text track (currently displayed subtitle) data changes. + * @platform Android, Ios + */ + onTextTrackDataChanged: (texts: string[]) => void; + /** + * Called when the selected text track changes. + * @param track - The newly selected text track, or null if no track is selected + * @platform Android, Ios + */ + onTrackChange: (track: TextTrack | null) => void; + /** + * Called when the volume of the player changes. + */ + onVolumeChange: (data: onVolumeChangeData) => void; + /** + * Called when the player status changes. + */ + onStatusChange: (status: VideoPlayerStatus) => void; +} +export interface AllPlayerEvents extends VideoPlayerEvents { + onError: (error: VideoRuntimeError) => void; +} +export interface VideoViewEvents { + /** + * Called when the video view's picture in picture state changes. + * @param isInPictureInPicture Whether the video view is in picture in picture mode. + */ + onPictureInPictureChange: (isInPictureInPicture: boolean) => void; + /** + * Called when the video view's fullscreen state changes. + * @param fullscreen Whether the video view is in fullscreen mode. + */ + onFullscreenChange: (fullscreen: boolean) => void; + /** + * Called when the video view will enter fullscreen mode. + */ + willEnterFullscreen: () => void; + /** + * Called when the video view will exit fullscreen mode. + */ + willExitFullscreen: () => void; + /** + * Called when the video view will enter picture in picture mode. + */ + willEnterPictureInPicture: () => void; + /** + * Called when the video view will exit picture in picture mode. + */ + willExitPictureInPicture: () => void; +} +export interface BandwidthData { + /** + * The bitrate of the video in bits per second. + */ + bitrate: number; + /** + * The width of the video in pixels. + * @platform android + */ + width?: number; + /** + * The height of the video in pixels. + * @platform Android + */ + height?: number; +} +export interface onLoadData { + /** + * The current time of the video in seconds. + */ + currentTime: number; + /** + * The duration of the video in seconds. + * @note NaN if the duration is unknown. + */ + duration: number; + /** + * The height of the video in pixels. + */ + height: number; + /** + * The width of the video in pixels. + */ + width: number; + /** + * The orientation of the video. + */ + orientation: VideoOrientation; +} +export type SourceType = 'local' | 'network'; +export interface onLoadStartData { + /** + * The type of the source. + * @note `local` for local files, `network` for network sources. + */ + sourceType: SourceType; + /** + * The source of the video. + */ + source: VideoPlayerSourceBase; +} +export interface onPlaybackStateChangeData { + /** + * Whether the video is playing. + */ + isPlaying: boolean; + /** + * Whether the video is buffering. + */ + isBuffering: boolean; +} +export interface onProgressData { + /** + * The current time of the video in seconds. + */ + currentTime: number; + /** + * The time that player is able to play with only buffer. + */ + bufferDuration: number; +} +export type TimedMetadataObject = { + value: string; + identifier: string; +}; +export interface TimedMetadata { + /** + * The timed metadata of the video. + */ + metadata: Array; +} +export interface onVolumeChangeData { + /** + * The volume of the player (0.0 = 0%, 1.0 = 100%). + */ + volume: number; + /** + * Whether the player is muted. + */ + muted: boolean; +} +export declare const ALL_PLAYER_EVENTS: (keyof AllPlayerEvents)[]; +//# sourceMappingURL=Events.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/Events.d.ts.map b/lib/typescript/module/src/core/types/Events.d.ts.map new file mode 100644 index 00000000..93d17163 --- /dev/null +++ b/lib/typescript/module/src/core/types/Events.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Events.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/Events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD;;OAEG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;OAIG;IACH,wBAAwB,EAAE,CAAC,sBAAsB,EAAE,OAAO,KAAK,IAAI,CAAC;IACpE;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,WAAW,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,qBAAqB,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACjE;;OAEG;IACH,oBAAoB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C;;OAEG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B;;OAEG;IACH,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD;;OAEG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,cAAc,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,wBAAwB,EAAE,CAAC,oBAAoB,EAAE,OAAO,KAAK,IAAI,CAAC;IAClE;;;OAGG;IACH,kBAAkB,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC;;OAEG;IACH,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B;;OAEG;IACH,yBAAyB,EAAE,MAAM,IAAI,CAAC;IACtC;;OAEG;IACH,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAiBD,eAAO,MAAM,iBAAiB,EAAE,CAAC,MAAM,eAAe,CAAC,EAsBpD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts b/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts new file mode 100644 index 00000000..4bf842ef --- /dev/null +++ b/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts @@ -0,0 +1,2 @@ +export type IgnoreSilentSwitchMode = 'auto' | 'ignore' | 'obey'; +//# sourceMappingURL=IgnoreSilentSwitchMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts.map b/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts.map new file mode 100644 index 00000000..a5219753 --- /dev/null +++ b/lib/typescript/module/src/core/types/IgnoreSilentSwitchMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"IgnoreSilentSwitchMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/IgnoreSilentSwitchMode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/MixAudioMode.d.ts b/lib/typescript/module/src/core/types/MixAudioMode.d.ts new file mode 100644 index 00000000..9526d372 --- /dev/null +++ b/lib/typescript/module/src/core/types/MixAudioMode.d.ts @@ -0,0 +1,2 @@ +export type MixAudioMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers' | 'auto'; +//# sourceMappingURL=MixAudioMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/MixAudioMode.d.ts.map b/lib/typescript/module/src/core/types/MixAudioMode.d.ts.map new file mode 100644 index 00000000..93f4b499 --- /dev/null +++ b/lib/typescript/module/src/core/types/MixAudioMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MixAudioMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/MixAudioMode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/ResizeMode.d.ts b/lib/typescript/module/src/core/types/ResizeMode.d.ts new file mode 100644 index 00000000..7593e483 --- /dev/null +++ b/lib/typescript/module/src/core/types/ResizeMode.d.ts @@ -0,0 +1,10 @@ +/** + * Video resize modes that determine how video content is resized to fit the view + * + * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view + * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop) + * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio + * - 'none': Do not resize the video - it will fallback to default behavior (contain) + */ +export type ResizeMode = 'contain' | 'cover' | 'stretch' | 'none'; +//# sourceMappingURL=ResizeMode.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/ResizeMode.d.ts.map b/lib/typescript/module/src/core/types/ResizeMode.d.ts.map new file mode 100644 index 00000000..2260f355 --- /dev/null +++ b/lib/typescript/module/src/core/types/ResizeMode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ResizeMode.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/ResizeMode.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/TextTrack.d.ts b/lib/typescript/module/src/core/types/TextTrack.d.ts new file mode 100644 index 00000000..45e616cc --- /dev/null +++ b/lib/typescript/module/src/core/types/TextTrack.d.ts @@ -0,0 +1,20 @@ +export interface TextTrack { + /** + * Unique identifier for the text track + */ + id: string; + /** + * Display label for the text track + */ + label: string; + /** + * Language code (ISO 639-1 or ISO 639-2) + * @example "en", "es", "fr" + */ + language?: string; + /** + * Whether this track is currently selected + */ + selected: boolean; +} +//# sourceMappingURL=TextTrack.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/TextTrack.d.ts.map b/lib/typescript/module/src/core/types/TextTrack.d.ts.map new file mode 100644 index 00000000..d0b729b6 --- /dev/null +++ b/lib/typescript/module/src/core/types/TextTrack.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TextTrack.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/TextTrack.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/Utils.d.ts b/lib/typescript/module/src/core/types/Utils.d.ts new file mode 100644 index 00000000..e5422cc9 --- /dev/null +++ b/lib/typescript/module/src/core/types/Utils.d.ts @@ -0,0 +1,2 @@ +export type NoAutocomplete = T & never; +//# sourceMappingURL=Utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/Utils.d.ts.map b/lib/typescript/module/src/core/types/Utils.d.ts.map new file mode 100644 index 00000000..4ad5d84d --- /dev/null +++ b/lib/typescript/module/src/core/types/Utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/Utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoConfig.d.ts b/lib/typescript/module/src/core/types/VideoConfig.d.ts new file mode 100644 index 00000000..0e287edf --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoConfig.d.ts @@ -0,0 +1,124 @@ +import type { BufferConfig } from './BufferConfig'; +import type { DrmParams } from './DrmParams'; +export type VideoSource = number | string; +export type VideoConfig = { + /** + * The uri of the video. + * @example + * ```ts + * uri: 'https://example.com/video.mp4' + * // or + * uri: require('./assets/video.mp4') + * ``` + */ + uri: VideoSource; + /** + * The headers to be sent with the request. + */ + headers?: Record; + /** + * The DRM parameters to be used. + */ + drm?: DrmParams; + /** + * The player buffer configuration. + */ + bufferConfig?: BufferConfig; + /** + * The custom metadata to be associated with the video. + * This metadata can be used by the native player to show information about the video. + */ + metadata?: CustomVideoMetadata; + /** + * The external subtitles to be used. + * @note on iOS, only WebVTT (.vtt) subtitles are supported (for HLS streams and MP4 files). + * @note on iOS, `label` can be overridden by player and there is no way to get around it. + * @example + * ```ts + * externalSubtitles: [ + * { + * uri: 'https://example.com/subtitles_en.vtt', + * label: 'English', + * type: 'vtt', + * language: 'en' + * }, + * { + * uri: 'https://example.com/subtitles_es.vtt', + * label: 'Español', + * type: 'vtt', + * language: 'es' + * } + * ] + * ``` + */ + externalSubtitles?: ExternalSubtitle[]; + /** + * when the player is created, this flag will determine if native player should be initialized immediately. + * If set to true, the player will be initialized as soon as player is created + * If set to false, the player will need be initialized manually later + * @default true + */ + initializeOnCreation?: boolean; +}; +/** + * The type of the subtitle. + * - `vtt` - WebVTT + * - `srt` - SubRip + * - `ssa` - SubStation Alpha + * - `ass` - Advanced SubStation Alpha + * - `auto` - Auto detect the subtitle type from the file extension + * + * @note `auto` is not available when uri have no extension. + */ +export type SubtitleType = 'vtt' | 'srt' | 'ssa' | 'ass' | 'auto'; +interface ExternalSubtitleWithInferredType { + /** + * The uri of the subtitle. + * @note the uri must end with the subtitle type. + */ + uri: `${string}.${SubtitleType}`; + /** + * The label for the subtitle. + */ + label: string; + /** + * The type of the subtitle. + */ + type?: SubtitleType; + /** + * The language code for the subtitle (ISO 639-1 or ISO 639-2). + * @example 'en', 'es', 'fr', 'de', 'zh-CN' + * @default 'und' (undefined) + */ + language?: string; +} +interface ExternalSubtitleWithCustomType { + /** + * The uri of the subtitle. + */ + uri: string; + /** + * The label for the subtitle. + */ + label: string; + /** + * The type of the subtitle. + */ + type: Omit; + /** + * The language code for the subtitle (ISO 639-1 or ISO 639-2). + * @example 'en', 'es', 'fr', 'de', 'zh-CN' + * @default 'und' (undefined) + */ + language?: string; +} +export type ExternalSubtitle = ExternalSubtitleWithInferredType | ExternalSubtitleWithCustomType; +interface CustomVideoMetadata { + title?: string; + subtitle?: string; + description?: string; + artist?: string; + imageUri?: string; +} +export {}; +//# sourceMappingURL=VideoConfig.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoConfig.d.ts.map b/lib/typescript/module/src/core/types/VideoConfig.d.ts.map new file mode 100644 index 00000000..a6d3b7d3 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoConfig.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoConfig.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;;OAQG;IACH,GAAG,EAAE,WAAW,CAAC;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACvC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAUF;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAElE,UAAU,gCAAgC;IACxC;;;OAGG;IACH,GAAG,EAAE,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,8BAA8B;IACtC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GACxB,gCAAgC,GAChC,8BAA8B,CAAC;AAanC,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoError.d.ts b/lib/typescript/module/src/core/types/VideoError.d.ts new file mode 100644 index 00000000..70065a90 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoError.d.ts @@ -0,0 +1,27 @@ +export type LibraryError = 'library/deallocated' | 'library/application-context-not-found'; +export type PlayerError = 'player/released' | 'player/not-initialized' | 'player/asset-not-initialized' | 'player/invalid-source'; +export type SourceError = 'source/invalid-uri' | 'source/missing-read-file-permission' | 'source/file-does-not-exist' | 'source/failed-to-initialize-asset' | 'source/unsupported-content-type'; +export type VideoViewError = 'view/not-found' | 'view/deallocated' | 'view/picture-in-picture-not-supported'; +export type UnknownError = 'unknown/unknown'; +export type VideoErrorCode = LibraryError | PlayerError | SourceError | VideoViewError | UnknownError; +export declare class VideoError extends Error { + private readonly _code; + private readonly _message; + private readonly _stack?; + get code(): TCode; + get message(): string; + get stack(): string | undefined; + toString(): string; +} +export declare class VideoComponentError extends VideoError { +} +export declare class VideoRuntimeError extends VideoError { +} +/** + * Tries to parse an error coming from native to a typed JS video error. + * @param {VideoError} nativeError The native error instance. This is a JSON in the legacy native module architecture. + * @returns A {@linkcode VideoRuntimeError} or {@linkcode VideoComponentError}, or the `nativeError` itself if it's not parsable + * @method + */ +export declare const tryParseNativeVideoError: (nativeError: T) => (VideoRuntimeError | VideoComponentError) | T; +//# sourceMappingURL=VideoError.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoError.d.ts.map b/lib/typescript/module/src/core/types/VideoError.d.ts.map new file mode 100644 index 00000000..f731add6 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoError.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoError.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoError.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,qBAAqB,GACrB,uCAAuC,CAAC;AAE5C,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,wBAAwB,GACxB,8BAA8B,GAC9B,uBAAuB,CAAC;AAE5B,MAAM,MAAM,WAAW,GACnB,oBAAoB,GACpB,qCAAqC,GACrC,4BAA4B,GAC5B,mCAAmC,GACnC,iCAAiC,CAAC;AAEtC,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,kBAAkB,GAClB,uCAAuC,CAAC;AAE5C,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAE7C,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,WAAW,GACX,WAAW,GACX,cAAc,GACd,YAAY,CAAC;AAEjB,qBAAa,UAAU,CAAC,KAAK,SAAS,cAAc,CAAE,SAAQ,KAAK;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IAEjC,IAAW,IAAI,IAAI,KAAK,CAEvB;IACD,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,KAAK,IAAI,MAAM,GAAG,SAAS,CAErC;IAeM,QAAQ,IAAI,MAAM;CAI1B;AAED,qBAAa,mBAAoB,SAAQ,UAAU,CAAC,cAAc,CAAC;CAAG;AAEtE,qBAAa,iBAAkB,SAAQ,UAAU,CAC/C,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CACxD;CAAG;AAkEJ;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,EACxC,aAAa,CAAC,KACb,CAAC,iBAAiB,GAAG,mBAAmB,CAAC,GAAG,CA6B9C,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoInformation.d.ts b/lib/typescript/module/src/core/types/VideoInformation.d.ts new file mode 100644 index 00000000..baa92d3e --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoInformation.d.ts @@ -0,0 +1,37 @@ +import type { VideoOrientation } from './VideoOrientation'; +export interface VideoInformation { + /** + * The bitrate of the video in kbps. + */ + bitrate: number; + /** + * The width of the video in pixels. + */ + width: number; + /** + * The height of the video in pixels. + */ + height: number; + /** + * The duration of the video in seconds. + */ + duration: bigint; + /** + * The file size of the video in bytes. + */ + fileSize: bigint; + /** + * Whether the video is HDR. + */ + isHDR: boolean; + /** + * Whether the video is live + */ + isLive: boolean; + /** + * The orientation of the video. + * see {@link VideoOrientation} + */ + orientation: VideoOrientation; +} +//# sourceMappingURL=VideoInformation.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoInformation.d.ts.map b/lib/typescript/module/src/core/types/VideoInformation.d.ts.map new file mode 100644 index 00000000..21c4567e --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoInformation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoInformation.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoInformation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,EAAE,gBAAgB,CAAC;CAC/B"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoOrientation.d.ts b/lib/typescript/module/src/core/types/VideoOrientation.d.ts new file mode 100644 index 00000000..bb244d1a --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoOrientation.d.ts @@ -0,0 +1,2 @@ +export type VideoOrientation = 'portrait' | 'landscape' | 'portrait-upside-down' | 'landscape-left' | 'landscape-right' | 'square' | 'unknown'; +//# sourceMappingURL=VideoOrientation.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoOrientation.d.ts.map b/lib/typescript/module/src/core/types/VideoOrientation.d.ts.map new file mode 100644 index 00000000..84f79fe0 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoOrientation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoOrientation.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoOrientation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,WAAW,GACX,sBAAsB,GACtB,gBAAgB,GAChB,iBAAiB,GACjB,QAAQ,GACR,SAAS,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts b/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts new file mode 100644 index 00000000..26b934e9 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts @@ -0,0 +1,149 @@ +import type { IgnoreSilentSwitchMode } from './IgnoreSilentSwitchMode'; +import type { MixAudioMode } from './MixAudioMode'; +import type { TextTrack } from './TextTrack'; +import type { VideoPlayerSourceBase } from './VideoPlayerSourceBase'; +import type { VideoPlayerStatus } from './VideoPlayerStatus'; +export interface VideoPlayerBase { + /** + * The source of the video. + * Source is immutable. To change the source, you need to call {@link replaceSourceAsync} method. + * see {@link VideoPlayerSourceBase} + */ + readonly source: VideoPlayerSourceBase; + /** + * The status of the player. + * @param idle - The player is idle (source is not loaded) + * @param loading - The player is loading. + * @param readyToPlay - The player is ready to play (source is loaded). + * @param error - The player has an error. + */ + readonly status: VideoPlayerStatus; + /** + * The current time of the video in seconds (1.0 = 1 sec). + * Returns NaN if the current time is not available. + */ + readonly duration: number; + /** + * The volume of the video (0.0 = 0%, 1.0 = 100%). + * @note If the player is {@link muted}, the volume will be 0.0. + */ + volume: number; + /** + * The duration of the video in seconds (1.0 = 1 sec). + * Returns NaN if the duration is not available. + */ + currentTime: number; + /** + * Whether the player is muted. + */ + muted: boolean; + /** + * Whether the player is looped. + */ + loop: boolean; + /** + * Controls the speed at which the player should play. + * @note if rate is = 0, it will pause video. + */ + rate: number; + /** + * Controls the audio mixing mode of the player. + * + * - `mixWithOthers` - Mix with other players. + * - `doNotMix` - Do not mix with other players. + * - `duckOthers` - Duck other players. + * - `auto` - uses default behavior for player. + * + * default is `auto`. + */ + mixAudioMode: MixAudioMode; + /** + * Controls the silent switch mode of the player. + * @note This is only supported on iOS. + * + * - `auto` - uses default behavior for player. + * - `ignore` - ignore the silent switch. + * - `obey` - obey the silent switch. + */ + ignoreSilentSwitchMode: IgnoreSilentSwitchMode; + /** + * Whether the player should play in background. + * + * - `true` - play in background. + * - `false` - pause in background (default). + * + * @note this can override {@link playWhenInactive}. + */ + playInBackground: boolean; + /** + * Whether the player should play when the app is inactive (user opened control center). + * + * - `true` - play when the app is inactive. + * - `false` - pause when the app is inactive (default). + * + * @note this can be overridden by {@link playInBackground}. + * @note This is only supported on iOS. + */ + playWhenInactive: boolean; + /** + * Whether the player is playing. + * @note This is a read-only property. + * @note To pause/resume the player, you need to use {@link play} and {@link pause} methods. + */ + readonly isPlaying: boolean; + /** + * Manually initialize the player. You don't need to call this method manually, unless you set `initializeOnCreation` to false in {@link VideoConfig} + */ + initialize(): Promise; + /** + * Preload the video. + * This is useful to avoid delay when the user plays the video. + * Preloading too many videos can lead to memory issues or performance issues. + */ + preload(): Promise; + /** + * Start playback of player. + */ + play(): void; + /** + * Pause playback of player. + */ + pause(): void; + /** + * Seek by given time. + * If the time is negative, it will seek backward. + * time will be clamped if it is out of range (0 ~ {@link duration}). + * @param time - The time to seek from current time in seconds. + */ + seekBy(time: number): void; + /** + * Seek to a specific time in the video. + * @param time - The time to seek to in seconds. + * @note This have same effect as {@link currentTime} setter. + * @note time will be clamped if it is out of range (0 ~ {@link duration}). + */ + seekTo(time: number): void; + /** + * 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. + * see {@link VideoPlayerSourceBase} + */ + replaceSourceAsync(source: VideoPlayerSourceBase | null): Promise; + /** + * Get all available text tracks for the current source. + * @returns Array of available text tracks + */ + getAvailableTextTracks(): TextTrack[]; + /** + * Select a text track to display. + * @param textTrack - Text track to select, or null to unselect current track + */ + selectTextTrack(textTrack: TextTrack | null): void; + /** + * Get the currently selected text track. + * @returns The currently selected text track, or undefined if none is selected + */ + readonly selectedTrack?: TextTrack; +} +//# sourceMappingURL=VideoPlayerBase.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts.map b/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts.map new file mode 100644 index 00000000..b7fbce68 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerBase.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerBase.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEvC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;;OASG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;;;;;;OAOG;IACH,sBAAsB,EAAE,sBAAsB,CAAC;IAE/C;;;;;;;OAOG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;;;;;OAQG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;OAEG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B;;;;;OAKG;IACH,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;;OAGG;IACH,sBAAsB,IAAI,SAAS,EAAE,CAAC;IAEtC;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IAEnD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;CACpC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts b/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts new file mode 100644 index 00000000..2b2cf59c --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts @@ -0,0 +1,17 @@ +import type { NativeVideoConfig } from './VideoConfig'; +import type { VideoInformation } from './VideoInformation'; +export interface VideoPlayerSourceBase { + /** + * The URI of the asset. + */ + readonly uri: string; + /** + * The config of the asset. + */ + readonly config: NativeVideoConfig; + /** + * Get the information about the asset. + */ + getAssetInformationAsync(): Promise; +} +//# sourceMappingURL=VideoPlayerSourceBase.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts.map b/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts.map new file mode 100644 index 00000000..72055ff7 --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerSourceBase.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerSourceBase.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerSourceBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC;;OAEG;IACH,wBAAwB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvD"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts b/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts new file mode 100644 index 00000000..37921b0e --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts @@ -0,0 +1,9 @@ +/** + * The status of the player. + * @param idle - The player is idle (source is not loaded) + * @param loading - The player is loading (source is loading). + * @param readyToPlay - The player is ready to play (source is loaded). + * @param error - The player has an error (source is not loaded). + */ +export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error'; +//# sourceMappingURL=VideoPlayerStatus.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts.map b/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts.map new file mode 100644 index 00000000..74294cfe --- /dev/null +++ b/lib/typescript/module/src/core/types/VideoPlayerStatus.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerStatus.d.ts","sourceRoot":"","sources":["../../../../../../src/core/types/VideoPlayerStatus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/playerFactory.d.ts b/lib/typescript/module/src/core/utils/playerFactory.d.ts new file mode 100644 index 00000000..573dce4c --- /dev/null +++ b/lib/typescript/module/src/core/utils/playerFactory.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=playerFactory.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/playerFactory.d.ts.map b/lib/typescript/module/src/core/utils/playerFactory.d.ts.map new file mode 100644 index 00000000..d5dad934 --- /dev/null +++ b/lib/typescript/module/src/core/utils/playerFactory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"playerFactory.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/playerFactory.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/sourceFactory.d.ts b/lib/typescript/module/src/core/utils/sourceFactory.d.ts new file mode 100644 index 00000000..3c957c93 --- /dev/null +++ b/lib/typescript/module/src/core/utils/sourceFactory.d.ts @@ -0,0 +1,28 @@ +import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro'; +import type { VideoConfig, VideoSource } from '../types/VideoConfig'; +/** + * Creates a `VideoPlayerSource` instance from a URI (string). + * + * @param uri - The URI of the video to play + * @returns The `VideoPlayerSource` instance + */ +export declare const createSourceFromUri: (uri: string) => VideoPlayerSource; +/** + * Creates a `VideoPlayerSource` instance from a `VideoConfig`. + * + * @note The `uri` property is required to be a string. + * + * @param config - The `VideoConfig` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export declare const createSourceFromVideoConfig: (config: VideoConfig & { + uri: string; +}) => VideoPlayerSource; +/** + * Creates a `VideoPlayerSource` + * + * @param source - The `VideoSource` to create the `VideoPlayerSource` from + * @returns The `VideoPlayerSource` instance + */ +export declare const createSource: (source: VideoSource | VideoConfig | VideoPlayerSource) => VideoPlayerSource; +//# sourceMappingURL=sourceFactory.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/sourceFactory.d.ts.map b/lib/typescript/module/src/core/utils/sourceFactory.d.ts.map new file mode 100644 index 00000000..09f54d62 --- /dev/null +++ b/lib/typescript/module/src/core/utils/sourceFactory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sourceFactory.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/sourceFactory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAIV,WAAW,EACX,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAS9B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,sBAM9C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GACtC,QAAQ,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,sBAkCtC,CAAC;AAmBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,WAAW,GAAG,WAAW,GAAG,iBAAiB,KACpD,iBAoCF,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/sourceUtils.d.ts b/lib/typescript/module/src/core/utils/sourceUtils.d.ts new file mode 100644 index 00000000..863d17c3 --- /dev/null +++ b/lib/typescript/module/src/core/utils/sourceUtils.d.ts @@ -0,0 +1,3 @@ +import type { VideoPlayerSource } from "../../spec/nitro/VideoPlayerSource.nitro"; +export declare const isVideoPlayerSource: (obj: any) => obj is VideoPlayerSource; +//# sourceMappingURL=sourceUtils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/utils/sourceUtils.d.ts.map b/lib/typescript/module/src/core/utils/sourceUtils.d.ts.map new file mode 100644 index 00000000..d1016e84 --- /dev/null +++ b/lib/typescript/module/src/core/utils/sourceUtils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sourceUtils.d.ts","sourceRoot":"","sources":["../../../../../../src/core/utils/sourceUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAElF,eAAO,MAAM,mBAAmB,GAAI,KAAK,GAAG,KAAG,GAAG,IAAI,iBAOrD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts b/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts new file mode 100644 index 00000000..50af5bf8 --- /dev/null +++ b/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts @@ -0,0 +1,2 @@ +export declare const NativeVideoView: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType | (() => never); +//# sourceMappingURL=NativeVideoView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts.map b/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts.map new file mode 100644 index 00000000..c6647fcc --- /dev/null +++ b/lib/typescript/module/src/core/video-view/NativeVideoView.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"NativeVideoView.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/NativeVideoView.tsx"],"names":[],"mappings":"AAYA,eAAO,MAAM,eAAe,iLAKrB,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/VideoView.d.ts b/lib/typescript/module/src/core/video-view/VideoView.d.ts new file mode 100644 index 00000000..709f4a29 --- /dev/null +++ b/lib/typescript/module/src/core/video-view/VideoView.d.ts @@ -0,0 +1,5 @@ +import * as React from 'react'; +import type { VideoViewProps, VideoViewRef } from './ViewViewProps'; +declare const _default: React.MemoExoticComponent>>; +export default _default; +//# sourceMappingURL=VideoView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/VideoView.d.ts.map b/lib/typescript/module/src/core/video-view/VideoView.d.ts.map new file mode 100644 index 00000000..9ce6495d --- /dev/null +++ b/lib/typescript/module/src/core/video-view/VideoView.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AAqLpE,wBAAqC"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/VideoView.web.d.ts b/lib/typescript/module/src/core/video-view/VideoView.web.d.ts new file mode 100644 index 00000000..46174f6e --- /dev/null +++ b/lib/typescript/module/src/core/video-view/VideoView.web.d.ts @@ -0,0 +1,4 @@ +import type { VideoViewProps, VideoViewRef } from "./ViewViewProps"; +declare const _default: import("react").MemoExoticComponent>>; +export default _default; +//# sourceMappingURL=VideoView.web.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/VideoView.web.d.ts.map b/lib/typescript/module/src/core/video-view/VideoView.web.d.ts.map new file mode 100644 index 00000000..201f63de --- /dev/null +++ b/lib/typescript/module/src/core/video-view/VideoView.web.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/VideoView.web.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AA0EpE,wBAA+B"} \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts b/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts new file mode 100644 index 00000000..880181d6 --- /dev/null +++ b/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts @@ -0,0 +1,74 @@ +import type { ViewProps, ViewStyle } from "react-native"; +import type { SurfaceType } from "../../spec/nitro/VideoViewViewManager.nitro"; +import type { VideoViewEvents } from "../types/Events"; +import type { ResizeMode } from "../types/ResizeMode"; +import type { VideoPlayer } from "../VideoPlayer"; +export interface VideoViewProps extends Partial, ViewProps { + /** + * The player to play the video - {@link VideoPlayer} + */ + player: VideoPlayer; + /** + * The style of the video view - {@link ViewStyle} + */ + style?: ViewStyle; + /** + * Whether to show the controls. Defaults to false. + */ + controls?: boolean; + /** + * Whether to enable & show the picture in picture button in native controls. Defaults to false. + */ + pictureInPicture?: boolean; + /** + * Whether to automatically enter picture in picture mode when the video is playing. Defaults to false. + */ + autoEnterPictureInPicture?: boolean; + /** + * How the video should be resized to fit the view. Defaults to 'none'. + * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view + * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop) + * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio + * - 'none': Do not resize the video + */ + resizeMode?: ResizeMode; + /** + * Whether to keep the screen awake while the video view is mounted. Defaults to true. + */ + keepScreenAwake?: boolean; + /** + * The type of underlying native view. Defaults to 'surface'. + * - 'surface': Uses a SurfaceView on Android. More performant, but cannot be animated or transformed. + * - 'texture': Uses a TextureView on Android. Less performant, but can be animated and transformed. + * + * Only applicable on Android + * + * @default 'surface' + * @platform android + */ + surfaceType?: SurfaceType; +} +export interface VideoViewRef { + /** + * Enter fullscreen mode + */ + enterFullscreen: () => void; + /** + * Exit fullscreen mode + */ + exitFullscreen: () => void; + /** + * Enter picture in picture mode + */ + enterPictureInPicture: () => void; + /** + * Exit picture in picture mode + */ + exitPictureInPicture: () => void; + /** + * Check if picture in picture mode is supported + * @returns true if picture in picture mode is supported, false otherwise + */ + canEnterPictureInPicture: () => boolean; +} +//# sourceMappingURL=ViewViewProps.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts.map b/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts.map new file mode 100644 index 00000000..f979b856 --- /dev/null +++ b/lib/typescript/module/src/core/video-view/ViewViewProps.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ViewViewProps.d.ts","sourceRoot":"","sources":["../../../../../../src/core/video-view/ViewViewProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,eAAe,CAAC,EAAE,SAAS;IACzE;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B;;OAEG;IACH,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC;;OAEG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC;;;OAGG;IACH,wBAAwB,EAAE,MAAM,OAAO,CAAC;CACzC"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/@types.d.ts b/lib/typescript/module/src/expo-plugins/@types.d.ts new file mode 100644 index 00000000..b01557a9 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/@types.d.ts @@ -0,0 +1,34 @@ +export type ConfigProps = { + /** + * Whether to use react-native-test-app compatible mode. + * @default false + */ + reactNativeTestApp?: boolean; + /** + * Apply configs to be able to use Picture-in-picture on Android. + * @default false + */ + enableAndroidPictureInPicture?: boolean; + /** + * Whether to enable background audio feature. + * @default false + */ + enableBackgroundAudio?: boolean; + /** + * Android extensions for ExoPlayer - you can choose which extensions to include in order to reduce the size of the app. + * @default { useExoplayerDash: true, useExoplayerHls: true } + */ + androidExtensions?: { + /** + * Whether to use ExoPlayer's Dash extension. + * @default true + */ + useExoplayerDash?: boolean; + /** + * Whether to use ExoPlayer's HLS extension. + * @default true + */ + useExoplayerHls?: boolean; + }; +}; +//# sourceMappingURL=@types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/@types.d.ts.map b/lib/typescript/module/src/expo-plugins/@types.d.ts.map new file mode 100644 index 00000000..ae3b7af4 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/@types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"@types.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/@types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;IAExC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,iBAAiB,CAAC,EAAE;QAClB;;;WAGG;QACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAE3B;;;WAGG;QACH,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts b/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts new file mode 100644 index 00000000..05880eac --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts @@ -0,0 +1,5 @@ +export declare function getPackageInfo(): { + name: string; + version: string; +}; +//# sourceMappingURL=getPackageInfo.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts.map b/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts.map new file mode 100644 index 00000000..503842b8 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/getPackageInfo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"getPackageInfo.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/getPackageInfo.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAsBlE"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts b/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts new file mode 100644 index 00000000..b221d984 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts @@ -0,0 +1,8 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +import type { ConfigProps } from './@types'; +/** + * Sets the Android extensions for ExoPlayer in `gradle.properties`. + * You can choose which extensions to include in order to reduce the size of the app. + */ +export declare const withAndroidExtensions: ConfigPlugin; +//# sourceMappingURL=withAndroidExtensions.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts.map b/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts.map new file mode 100644 index 00000000..d499b89b --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withAndroidExtensions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidExtensions.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withAndroidExtensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAAY,CAC9C,WAAW,CAAC,mBAAmB,CAAC,CAqCjC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts b/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts new file mode 100644 index 00000000..2bbffae8 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts @@ -0,0 +1,3 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +export declare const withAndroidPictureInPicture: ConfigPlugin; +//# sourceMappingURL=withAndroidPictureInPicture.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts.map b/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts.map new file mode 100644 index 00000000..dd0f2cd7 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withAndroidPictureInPicture.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidPictureInPicture.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withAndroidPictureInPicture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,2BAA2B,EAAE,YAAY,CAAC,OAAO,CAwB7D,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts b/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts new file mode 100644 index 00000000..65196e78 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts @@ -0,0 +1,7 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +/** + * Sets `UIBackgroundModes` in `Info.plist` to enable background audio on Apple platforms. + * This is required for audio to continue playing when the app is in the background. + */ +export declare const withBackgroundAudio: ConfigPlugin; +//# sourceMappingURL=withBackgroundAudio.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts.map b/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts.map new file mode 100644 index 00000000..23308807 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withBackgroundAudio.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withBackgroundAudio.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withBackgroundAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,OAAO,CAmBrD,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts b/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts new file mode 100644 index 00000000..5c4dbd4b --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts @@ -0,0 +1,5 @@ +import { type ConfigPlugin } from '@expo/config-plugins'; +import type { ConfigProps } from './@types'; +declare const _default: ConfigPlugin; +export default _default; +//# sourceMappingURL=withReactNativeVideo.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts.map b/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts.map new file mode 100644 index 00000000..b4542c5d --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/withReactNativeVideo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withReactNativeVideo.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/withReactNativeVideo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;;AA2B5C,wBAA+D"} \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts b/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts new file mode 100644 index 00000000..20be5197 --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts @@ -0,0 +1,2 @@ +export declare const writeToPodfile: (projectRoot: string, key: string, value: string, testApp?: boolean) => void; +//# sourceMappingURL=writeToPodfile.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts.map b/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts.map new file mode 100644 index 00000000..62e7906b --- /dev/null +++ b/lib/typescript/module/src/expo-plugins/writeToPodfile.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"writeToPodfile.d.ts","sourceRoot":"","sources":["../../../../../src/expo-plugins/writeToPodfile.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,GACzB,aAAa,MAAM,EACnB,KAAK,MAAM,EACX,OAAO,MAAM,EACb,UAAS,OAAe,SAiBzB,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/index.d.ts b/lib/typescript/module/src/index.d.ts new file mode 100644 index 00000000..f0a87ccb --- /dev/null +++ b/lib/typescript/module/src/index.d.ts @@ -0,0 +1,14 @@ +export { useEvent } from "./core/hooks/useEvent"; +export { useVideoPlayer } from "./core/hooks/useVideoPlayer"; +export type * from "./core/types/Events"; +export type { IgnoreSilentSwitchMode } from "./core/types/IgnoreSilentSwitchMode"; +export type { MixAudioMode } from "./core/types/MixAudioMode"; +export type { ResizeMode } from "./core/types/ResizeMode"; +export type { TextTrack } from "./core/types/TextTrack"; +export type { VideoConfig, VideoSource } from "./core/types/VideoConfig"; +export type { LibraryError, PlayerError, SourceError, UnknownError, VideoComponentError, VideoError, VideoErrorCode, VideoRuntimeError, VideoViewError, } from "./core/types/VideoError"; +export type { VideoPlayerStatus } from "./core/types/VideoPlayerStatus"; +export { VideoPlayer } from "./core/VideoPlayer"; +export { default as VideoView } from "./core/video-view/VideoView"; +export type { VideoViewProps, VideoViewRef, } from "./core/video-view/ViewViewProps"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/index.d.ts.map b/lib/typescript/module/src/index.d.ts.map new file mode 100644 index 00000000..f715f6b5 --- /dev/null +++ b/lib/typescript/module/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,mBAAmB,qBAAqB,CAAC;AACzC,YAAY,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EACV,cAAc,EACd,YAAY,GACb,MAAM,iCAAiC,CAAC"} \ No newline at end of file diff --git a/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts b/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts new file mode 100644 index 00000000..d3fe0e93 --- /dev/null +++ b/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts @@ -0,0 +1,12 @@ +import type { ViewProps } from 'react-native'; +import type { DirectEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypes'; +type OnNitroIdChangeEvent = Readonly<{ + nitroId: Int32; +}>; +export interface ViewViewNativeProps extends ViewProps { + nitroId: Int32; + onNitroIdChange?: DirectEventHandler; +} +declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType; +export default _default; +//# sourceMappingURL=VideoViewNativeComponent.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts.map b/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts.map new file mode 100644 index 00000000..21f1a01f --- /dev/null +++ b/lib/typescript/module/src/spec/fabric/VideoViewNativeComponent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/fabric/VideoViewNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,kBAAkB,EAClB,KAAK,EACN,MAAM,2CAA2C,CAAC;AAGnD,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,WAAW,mBAAoB,SAAQ,SAAS;IACpD,OAAO,EAAE,KAAK,CAAC;IACf,eAAe,CAAC,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,CAAC;CAC5D;;AAED,wBAA2E"} \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts b/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts new file mode 100644 index 00000000..2b52c445 --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts @@ -0,0 +1,39 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { TextTrack } from '../../core/types/TextTrack'; +import type { VideoPlayerBase } from '../../core/types/VideoPlayerBase'; +import type { VideoPlayerEventEmitter } from './VideoPlayerEventEmitter.nitro'; +import type { VideoPlayerSource } from './VideoPlayerSource.nitro'; +export interface VideoPlayer extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerBase { + readonly source: VideoPlayerSource; + readonly eventEmitter: VideoPlayerEventEmitter; + /** + * Show playback controls in the notifications area + * + * @note on Android, this can be overridden by {@linkcode VideoPlayer.playInBackground}, as Android requires + * a foreground service to show notifications while the app is in the background. + * + * @default false + */ + showNotificationControls: boolean; + replaceSourceAsync(source: VideoPlayerSource | null): Promise; + /** + * Get all available text tracks for the current source. + * @returns Array of available text tracks + */ + getAvailableTextTracks(): TextTrack[]; + /** + * Select a text track to display. + * @param textTrack - Text track to select, or null to unselect current track + */ + selectTextTrack(textTrack: TextTrack | null): void; +} +export interface VideoPlayerFactory extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}> { + createPlayer(source: VideoPlayerSource): VideoPlayer; +} +//# sourceMappingURL=VideoPlayer.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts.map b/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts.map new file mode 100644 index 00000000..edbf9c10 --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayer.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayer.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayer.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,WAAW,WACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EACvD,eAAe;IAEjB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAGnC,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAE/C;;;;;;;OAOG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAElC,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,sBAAsB,IAAI,SAAS,EAAE,CAAC;IAEtC;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,kBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IACzD,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAAC;CACtD"} \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts b/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts new file mode 100644 index 00000000..1018d261 --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts @@ -0,0 +1,13 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { VideoPlayerEvents } from '../../core/types/Events'; +/** + * The holder of the video player events. + * @platform iOS + * @platform android + */ +export interface VideoPlayerEventEmitter extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerEvents { +} +//# sourceMappingURL=VideoPlayerEventEmitter.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map b/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map new file mode 100644 index 00000000..d42cb9c9 --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayerEventEmitter.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerEventEmitter.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayerEventEmitter.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,uBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EAGvD,iBAAiB;CAAG"} \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts b/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts new file mode 100644 index 00000000..b5251320 --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts @@ -0,0 +1,21 @@ +import type { HybridObject } from 'react-native-nitro-modules'; +import type { NativeVideoConfig } from '../../core/types/VideoConfig'; +import type { VideoPlayerSourceBase } from '../../core/types/VideoPlayerSourceBase'; +/** + * A source for a {@link VideoPlayer}. + * Source cannot be changed after it is created. If you need to update the source, you need to create a new one. + * It provides functions to get information about the asset. + */ +export interface VideoPlayerSource extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}>, VideoPlayerSourceBase { +} +export interface VideoPlayerSourceFactory extends HybridObject<{ + ios: 'swift'; + android: 'kotlin'; +}> { + fromUri(uri: string): VideoPlayerSource; + fromVideoConfig(config: NativeVideoConfig): VideoPlayerSource; +} +//# sourceMappingURL=VideoPlayerSource.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map b/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map new file mode 100644 index 00000000..e766ab6b --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoPlayerSource.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoPlayerSource.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoPlayerSource.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAEpF;;;;GAIG;AACH,MAAM,WAAW,iBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC,EACvD,qBAAqB;CAAG;AAE5B,MAAM,WAAW,wBACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IACzD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;CAC/D"} \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts b/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts new file mode 100644 index 00000000..daafad1b --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts @@ -0,0 +1,2 @@ +export type SurfaceType = 'surface' | 'texture'; +//# sourceMappingURL=VideoViewViewManager.nitro.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map b/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map new file mode 100644 index 00000000..c5841d9c --- /dev/null +++ b/lib/typescript/module/src/spec/nitro/VideoViewViewManager.nitro.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoViewViewManager.nitro.d.ts","sourceRoot":"","sources":["../../../../../../src/spec/nitro/VideoViewViewManager.nitro.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC"} \ No newline at end of file diff --git a/nitro.json b/nitro.json new file mode 100644 index 00000000..e5668d3c --- /dev/null +++ b/nitro.json @@ -0,0 +1,28 @@ +{ + "android": { + "androidCxxLibName": "ReactNativeVideo", + "androidNamespace": [ + "video" + ] + }, + "cxxNamespace": [ + "video" + ], + "ios": { + "iosModuleName": "ReactNativeVideo" + }, + "autolinking": { + "VideoPlayerFactory": { + "swift": "HybridVideoPlayerFactory", + "kotlin": "HybridVideoPlayerFactory" + }, + "VideoPlayerSourceFactory": { + "swift": "HybridVideoPlayerSourceFactory", + "kotlin": "HybridVideoPlayerSourceFactory" + }, + "VideoViewViewManagerFactory": { + "swift": "HybridVideoViewViewManagerFactory", + "kotlin": "HybridVideoViewViewManagerFactory" + } + } +} \ No newline at end of file diff --git a/nitrogen/generated/.gitattributes b/nitrogen/generated/.gitattributes new file mode 100644 index 00000000..fb7a0d5a --- /dev/null +++ b/nitrogen/generated/.gitattributes @@ -0,0 +1 @@ +** linguist-generated=true diff --git a/nitrogen/generated/android/ReactNativeVideo+autolinking.cmake b/nitrogen/generated/android/ReactNativeVideo+autolinking.cmake new file mode 100644 index 00000000..3065a295 --- /dev/null +++ b/nitrogen/generated/android/ReactNativeVideo+autolinking.cmake @@ -0,0 +1,93 @@ +# +# ReactNativeVideo+autolinking.cmake +# This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +# https://github.com/mrousavy/nitro +# Copyright © 2025 Marc Rousavy @ Margelo +# + +# This is a CMake file that adds all files generated by Nitrogen +# to the current CMake project. +# +# To use it, add this to your CMakeLists.txt: +# ```cmake +# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideo+autolinking.cmake) +# ``` + +# Define a flag to check if we are building properly +add_definitions(-DBUILDING_REACTNATIVEVIDEO_WITH_GENERATED_CMAKE_PROJECT) + +# Enable Raw Props parsing in react-native (for Nitro Views) +add_definitions(-DRN_SERIALIZABLE_STATE) + +# Add all headers that were generated by Nitrogen +include_directories( + "../nitrogen/generated/shared/c++" + "../nitrogen/generated/android/c++" + "../nitrogen/generated/android/" +) + +# Add all .cpp sources that were generated by Nitrogen +target_sources( + # CMake project name (Android C++ library name) + ReactNativeVideo PRIVATE + # Autolinking Setup + ../nitrogen/generated/android/ReactNativeVideoOnLoad.cpp + # Shared Nitrogen C++ sources + ../nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp + ../nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp + # Android-specific Nitrogen C++ sources + ../nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp + ../nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp +) + +# From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake +# Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +target_compile_definitions( + ReactNativeVideo PRIVATE + -DFOLLY_NO_CONFIG=1 + -DFOLLY_HAVE_CLOCK_GETTIME=1 + -DFOLLY_USE_LIBCPP=1 + -DFOLLY_CFG_NO_COROUTINES=1 + -DFOLLY_MOBILE=1 + -DFOLLY_HAVE_RECVMMSG=1 + -DFOLLY_HAVE_PTHREAD=1 + # Once we target android-23 above, we can comment + # the following line. NDK uses GNU style stderror_r() after API 23. + -DFOLLY_HAVE_XSI_STRERROR_R=1 +) + +# Add all libraries required by the generated specs +find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++ +find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule) +find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library + +# Link all libraries together +target_link_libraries( + ReactNativeVideo + fbjni::fbjni # <-- Facebook C++ JNI helpers + ReactAndroid::jsi # <-- RN: JSI + react-native-nitro-modules::NitroModules # <-- NitroModules Core :) +) + +# Link react-native (different prefab between RN 0.75 and RN 0.76) +if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) + target_link_libraries( + ReactNativeVideo + ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab + ) +else() + target_link_libraries( + ReactNativeVideo + ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core + ) +endif() diff --git a/nitrogen/generated/android/ReactNativeVideo+autolinking.gradle b/nitrogen/generated/android/ReactNativeVideo+autolinking.gradle new file mode 100644 index 00000000..6abe826a --- /dev/null +++ b/nitrogen/generated/android/ReactNativeVideo+autolinking.gradle @@ -0,0 +1,27 @@ +/// +/// ReactNativeVideo+autolinking.gradle +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/// This is a Gradle file that adds all files generated by Nitrogen +/// to the current Gradle project. +/// +/// To use it, add this to your build.gradle: +/// ```gradle +/// apply from: '../nitrogen/generated/android/ReactNativeVideo+autolinking.gradle' +/// ``` + +logger.warn("[NitroModules] 🔥 ReactNativeVideo is boosted by nitro!") + +android { + sourceSets { + main { + java.srcDirs += [ + // Nitrogen files + "${project.projectDir}/../nitrogen/generated/android/kotlin" + ] + } + } +} diff --git a/nitrogen/generated/android/ReactNativeVideoOnLoad.cpp b/nitrogen/generated/android/ReactNativeVideoOnLoad.cpp new file mode 100644 index 00000000..2938284f --- /dev/null +++ b/nitrogen/generated/android/ReactNativeVideoOnLoad.cpp @@ -0,0 +1,100 @@ +/// +/// ReactNativeVideoOnLoad.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#ifndef BUILDING_REACTNATIVEVIDEO_WITH_GENERATED_CMAKE_PROJECT +#error ReactNativeVideoOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this? +#endif + +#include "ReactNativeVideoOnLoad.hpp" + +#include +#include +#include + +#include "JHybridVideoPlayerSpec.hpp" +#include "JHybridVideoPlayerFactorySpec.hpp" +#include "JHybridVideoPlayerEventEmitterSpec.hpp" +#include "JFunc_void.hpp" +#include "JFunc_void_bool.hpp" +#include "JFunc_void_BandwidthData.hpp" +#include "JFunc_void_onLoadData.hpp" +#include "JFunc_void_onLoadStartData.hpp" +#include "JFunc_void_onPlaybackStateChangeData.hpp" +#include "JFunc_void_double.hpp" +#include "JFunc_void_onProgressData.hpp" +#include "JFunc_void_TimedMetadata.hpp" +#include "JFunc_void_std__vector_std__string_.hpp" +#include "JFunc_void_std__optional_TextTrack_.hpp" +#include "JFunc_void_onVolumeChangeData.hpp" +#include "JFunc_void_VideoPlayerStatus.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" +#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp" +#include "JHybridVideoPlayerSourceFactorySpec.hpp" +#include "JHybridVideoViewViewManagerSpec.hpp" +#include "JHybridVideoViewViewManagerFactorySpec.hpp" +#include + +namespace margelo::nitro::video { + +int initialize(JavaVM* vm) { + using namespace margelo::nitro; + using namespace margelo::nitro::video; + using namespace facebook; + + return facebook::jni::initialize(vm, [] { + // Register native JNI methods + margelo::nitro::video::JHybridVideoPlayerSpec::registerNatives(); + margelo::nitro::video::JHybridVideoPlayerFactorySpec::registerNatives(); + margelo::nitro::video::JHybridVideoPlayerEventEmitterSpec::registerNatives(); + margelo::nitro::video::JFunc_void_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_bool_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_BandwidthData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_onLoadData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_onLoadStartData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_onPlaybackStateChangeData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_double_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_onProgressData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_TimedMetadata_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_std__vector_std__string__cxx::registerNatives(); + margelo::nitro::video::JFunc_void_std__optional_TextTrack__cxx::registerNatives(); + margelo::nitro::video::JFunc_void_onVolumeChangeData_cxx::registerNatives(); + margelo::nitro::video::JFunc_void_VideoPlayerStatus_cxx::registerNatives(); + margelo::nitro::video::JHybridVideoPlayerSourceSpec::registerNatives(); + margelo::nitro::video::JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::registerNatives(); + margelo::nitro::video::JHybridVideoPlayerSourceFactorySpec::registerNatives(); + margelo::nitro::video::JHybridVideoViewViewManagerSpec::registerNatives(); + margelo::nitro::video::JHybridVideoViewViewManagerFactorySpec::registerNatives(); + + // Register Nitro Hybrid Objects + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoPlayerFactory", + []() -> std::shared_ptr { + static DefaultConstructableObject object("com/margelo/nitro/video/HybridVideoPlayerFactory"); + auto instance = object.create(); + return instance->cthis()->shared(); + } + ); + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoPlayerSourceFactory", + []() -> std::shared_ptr { + static DefaultConstructableObject object("com/margelo/nitro/video/HybridVideoPlayerSourceFactory"); + auto instance = object.create(); + return instance->cthis()->shared(); + } + ); + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoViewViewManagerFactory", + []() -> std::shared_ptr { + static DefaultConstructableObject object("com/margelo/nitro/video/HybridVideoViewViewManagerFactory"); + auto instance = object.create(); + return instance->cthis()->shared(); + } + ); + }); +} + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/ReactNativeVideoOnLoad.hpp b/nitrogen/generated/android/ReactNativeVideoOnLoad.hpp new file mode 100644 index 00000000..e5f96628 --- /dev/null +++ b/nitrogen/generated/android/ReactNativeVideoOnLoad.hpp @@ -0,0 +1,25 @@ +/// +/// ReactNativeVideoOnLoad.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include +#include + +namespace margelo::nitro::video { + + /** + * Initializes the native (C++) part of ReactNativeVideo, and autolinks all Hybrid Objects. + * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`). + * Example: + * ```cpp (cpp-adapter.cpp) + * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { + * return margelo::nitro::video::initialize(vm); + * } + * ``` + */ + int initialize(JavaVM* vm); + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JBandwidthData.hpp b/nitrogen/generated/android/c++/JBandwidthData.hpp new file mode 100644 index 00000000..34482fcf --- /dev/null +++ b/nitrogen/generated/android/c++/JBandwidthData.hpp @@ -0,0 +1,61 @@ +/// +/// JBandwidthData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "BandwidthData.hpp" + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "BandwidthData" and the the Kotlin data class "BandwidthData". + */ + struct JBandwidthData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/BandwidthData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct BandwidthData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + BandwidthData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldBitrate = clazz->getField("bitrate"); + double bitrate = this->getFieldValue(fieldBitrate); + static const auto fieldWidth = clazz->getField("width"); + jni::local_ref width = this->getFieldValue(fieldWidth); + static const auto fieldHeight = clazz->getField("height"); + jni::local_ref height = this->getFieldValue(fieldHeight); + return BandwidthData( + bitrate, + width != nullptr ? std::make_optional(width->value()) : std::nullopt, + height != nullptr ? std::make_optional(height->value()) : 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 BandwidthData& value) { + return newInstance( + value.bitrate, + value.width.has_value() ? jni::JDouble::valueOf(value.width.value()) : nullptr, + value.height.has_value() ? jni::JDouble::valueOf(value.height.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JBufferConfig.hpp b/nitrogen/generated/android/c++/JBufferConfig.hpp new file mode 100644 index 00000000..6348dd89 --- /dev/null +++ b/nitrogen/generated/android/c++/JBufferConfig.hpp @@ -0,0 +1,97 @@ +/// +/// JBufferConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "BufferConfig.hpp" + +#include "JLivePlaybackParams.hpp" +#include "JResolution.hpp" +#include "LivePlaybackParams.hpp" +#include "Resolution.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "BufferConfig" and the the Kotlin data class "BufferConfig". + */ + struct JBufferConfig final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/BufferConfig;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct BufferConfig by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + BufferConfig toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldLivePlayback = clazz->getField("livePlayback"); + jni::local_ref livePlayback = this->getFieldValue(fieldLivePlayback); + static const auto fieldMinBufferMs = clazz->getField("minBufferMs"); + jni::local_ref minBufferMs = this->getFieldValue(fieldMinBufferMs); + static const auto fieldMaxBufferMs = clazz->getField("maxBufferMs"); + jni::local_ref maxBufferMs = this->getFieldValue(fieldMaxBufferMs); + static const auto fieldBufferForPlaybackMs = clazz->getField("bufferForPlaybackMs"); + jni::local_ref bufferForPlaybackMs = this->getFieldValue(fieldBufferForPlaybackMs); + static const auto fieldBufferForPlaybackAfterRebufferMs = clazz->getField("bufferForPlaybackAfterRebufferMs"); + jni::local_ref bufferForPlaybackAfterRebufferMs = this->getFieldValue(fieldBufferForPlaybackAfterRebufferMs); + static const auto fieldBackBufferDurationMs = clazz->getField("backBufferDurationMs"); + jni::local_ref backBufferDurationMs = this->getFieldValue(fieldBackBufferDurationMs); + static const auto fieldPreferredForwardBufferDurationMs = clazz->getField("preferredForwardBufferDurationMs"); + jni::local_ref preferredForwardBufferDurationMs = this->getFieldValue(fieldPreferredForwardBufferDurationMs); + static const auto fieldPreferredPeakBitRate = clazz->getField("preferredPeakBitRate"); + jni::local_ref preferredPeakBitRate = this->getFieldValue(fieldPreferredPeakBitRate); + static const auto fieldPreferredMaximumResolution = clazz->getField("preferredMaximumResolution"); + jni::local_ref preferredMaximumResolution = this->getFieldValue(fieldPreferredMaximumResolution); + static const auto fieldPreferredPeakBitRateForExpensiveNetworks = clazz->getField("preferredPeakBitRateForExpensiveNetworks"); + jni::local_ref preferredPeakBitRateForExpensiveNetworks = this->getFieldValue(fieldPreferredPeakBitRateForExpensiveNetworks); + static const auto fieldPreferredMaximumResolutionForExpensiveNetworks = clazz->getField("preferredMaximumResolutionForExpensiveNetworks"); + jni::local_ref preferredMaximumResolutionForExpensiveNetworks = this->getFieldValue(fieldPreferredMaximumResolutionForExpensiveNetworks); + return BufferConfig( + livePlayback != nullptr ? std::make_optional(livePlayback->toCpp()) : std::nullopt, + minBufferMs != nullptr ? std::make_optional(minBufferMs->value()) : std::nullopt, + maxBufferMs != nullptr ? std::make_optional(maxBufferMs->value()) : std::nullopt, + bufferForPlaybackMs != nullptr ? std::make_optional(bufferForPlaybackMs->value()) : std::nullopt, + bufferForPlaybackAfterRebufferMs != nullptr ? std::make_optional(bufferForPlaybackAfterRebufferMs->value()) : std::nullopt, + backBufferDurationMs != nullptr ? std::make_optional(backBufferDurationMs->value()) : std::nullopt, + preferredForwardBufferDurationMs != nullptr ? std::make_optional(preferredForwardBufferDurationMs->value()) : std::nullopt, + preferredPeakBitRate != nullptr ? std::make_optional(preferredPeakBitRate->value()) : std::nullopt, + preferredMaximumResolution != nullptr ? std::make_optional(preferredMaximumResolution->toCpp()) : std::nullopt, + preferredPeakBitRateForExpensiveNetworks != nullptr ? std::make_optional(preferredPeakBitRateForExpensiveNetworks->value()) : std::nullopt, + preferredMaximumResolutionForExpensiveNetworks != nullptr ? std::make_optional(preferredMaximumResolutionForExpensiveNetworks->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 BufferConfig& value) { + return newInstance( + value.livePlayback.has_value() ? JLivePlaybackParams::fromCpp(value.livePlayback.value()) : nullptr, + value.minBufferMs.has_value() ? jni::JDouble::valueOf(value.minBufferMs.value()) : nullptr, + value.maxBufferMs.has_value() ? jni::JDouble::valueOf(value.maxBufferMs.value()) : nullptr, + value.bufferForPlaybackMs.has_value() ? jni::JDouble::valueOf(value.bufferForPlaybackMs.value()) : nullptr, + value.bufferForPlaybackAfterRebufferMs.has_value() ? jni::JDouble::valueOf(value.bufferForPlaybackAfterRebufferMs.value()) : nullptr, + value.backBufferDurationMs.has_value() ? jni::JDouble::valueOf(value.backBufferDurationMs.value()) : nullptr, + value.preferredForwardBufferDurationMs.has_value() ? jni::JDouble::valueOf(value.preferredForwardBufferDurationMs.value()) : nullptr, + value.preferredPeakBitRate.has_value() ? jni::JDouble::valueOf(value.preferredPeakBitRate.value()) : nullptr, + value.preferredMaximumResolution.has_value() ? JResolution::fromCpp(value.preferredMaximumResolution.value()) : nullptr, + value.preferredPeakBitRateForExpensiveNetworks.has_value() ? jni::JDouble::valueOf(value.preferredPeakBitRateForExpensiveNetworks.value()) : nullptr, + value.preferredMaximumResolutionForExpensiveNetworks.has_value() ? JResolution::fromCpp(value.preferredMaximumResolutionForExpensiveNetworks.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp b/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp new file mode 100644 index 00000000..91a8b384 --- /dev/null +++ b/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp @@ -0,0 +1,70 @@ +/// +/// JCustomVideoMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "CustomVideoMetadata.hpp" + +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "CustomVideoMetadata" and the the Kotlin data class "CustomVideoMetadata". + */ + struct JCustomVideoMetadata final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/CustomVideoMetadata;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct CustomVideoMetadata by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + CustomVideoMetadata toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldTitle = clazz->getField("title"); + jni::local_ref title = this->getFieldValue(fieldTitle); + static const auto fieldSubtitle = clazz->getField("subtitle"); + jni::local_ref subtitle = this->getFieldValue(fieldSubtitle); + static const auto fieldDescription = clazz->getField("description"); + jni::local_ref description = this->getFieldValue(fieldDescription); + static const auto fieldArtist = clazz->getField("artist"); + jni::local_ref artist = this->getFieldValue(fieldArtist); + static const auto fieldImageUri = clazz->getField("imageUri"); + jni::local_ref imageUri = this->getFieldValue(fieldImageUri); + return CustomVideoMetadata( + title != nullptr ? std::make_optional(title->toStdString()) : std::nullopt, + subtitle != nullptr ? std::make_optional(subtitle->toStdString()) : std::nullopt, + description != nullptr ? std::make_optional(description->toStdString()) : std::nullopt, + artist != nullptr ? std::make_optional(artist->toStdString()) : std::nullopt, + imageUri != nullptr ? std::make_optional(imageUri->toStdString()) : 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 CustomVideoMetadata& value) { + return newInstance( + value.title.has_value() ? jni::make_jstring(value.title.value()) : nullptr, + value.subtitle.has_value() ? jni::make_jstring(value.subtitle.value()) : nullptr, + value.description.has_value() ? jni::make_jstring(value.description.value()) : nullptr, + value.artist.has_value() ? jni::make_jstring(value.artist.value()) : nullptr, + value.imageUri.has_value() ? jni::make_jstring(value.imageUri.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp b/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp new file mode 100644 index 00000000..be5e6d9b --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp @@ -0,0 +1,125 @@ +/// +/// JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include +#include +#include "OnGetLicensePayload.hpp" +#include +#include +#include "JOnGetLicensePayload.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(payload: OnGetLicensePayload) -> Promise>`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload;"; + + public: + /** + * Invokes the function this `JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload` instance holds through JNI. + */ + std::shared_ptr>>> invoke(const OnGetLicensePayload& payload) const { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* payload */)>("invoke"); + auto __result = method(self(), JOnGetLicensePayload::fromCpp(payload)); + return [&]() { + auto __promise = Promise>>::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { + auto __result = jni::static_ref_cast(__boxedResult); + __promise->resolve([&]() { + auto __promise = Promise::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { + auto __result = jni::static_ref_cast(__boxedResult); + __promise->resolve(__result->toStdString()); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }()); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } + }; + + /** + * An implementation of Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function>>>(const OnGetLicensePayload& /* payload */)>& func) { + return JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx` instance holds. + */ + jni::local_ref invoke_cxx(jni::alias_ref payload) { + std::shared_ptr>>> __result = _func(payload->toCpp()); + return [&]() { + jni::local_ref __localPromise = JPromise::create(); + jni::global_ref __promise = jni::make_global(__localPromise); + __result->addOnResolvedListener([=](const std::shared_ptr>& __result) { + __promise->cthis()->resolve([&]() { + jni::local_ref __localPromise = JPromise::create(); + jni::global_ref __promise = jni::make_global(__localPromise); + __result->addOnResolvedListener([=](const std::string& __result) { + __promise->cthis()->resolve(jni::make_jstring(__result)); + }); + __result->addOnRejectedListener([=](const std::exception_ptr& __error) { + auto __jniError = jni::getJavaExceptionForCppException(__error); + __promise->cthis()->reject(__jniError); + }); + return __localPromise; + }()); + }); + __result->addOnRejectedListener([=](const std::exception_ptr& __error) { + auto __jniError = jni::getJavaExceptionForCppException(__error); + __promise->cthis()->reject(__jniError); + }); + return __localPromise; + }(); + } + + public: + [[nodiscard]] + inline const std::function>>>(const OnGetLicensePayload& /* payload */)>& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx(const std::function>>>(const OnGetLicensePayload& /* payload */)>& func): _func(func) { } + + private: + friend HybridBase; + std::function>>>(const OnGetLicensePayload& /* payload */)> _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void.hpp b/nitrogen/generated/android/c++/JFunc_void.hpp new file mode 100644 index 00000000..ec57138c --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void.hpp @@ -0,0 +1,74 @@ +/// +/// JFunc_void.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `() -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void;"; + + public: + /** + * Invokes the function this `JFunc_void` instance holds through JNI. + */ + void invoke() const { + static const auto method = javaClassStatic()->getMethod("invoke"); + method(self()); + } + }; + + /** + * An implementation of Func_void that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_cxx` instance holds. + */ + void invoke_cxx() { + _func(); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_BandwidthData.hpp b/nitrogen/generated/android/c++/JFunc_void_BandwidthData.hpp new file mode 100644 index 00000000..ef113048 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_BandwidthData.hpp @@ -0,0 +1,77 @@ +/// +/// JFunc_void_BandwidthData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "BandwidthData.hpp" +#include +#include "JBandwidthData.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: BandwidthData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_BandwidthData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_BandwidthData;"; + + public: + /** + * Invokes the function this `JFunc_void_BandwidthData` instance holds through JNI. + */ + void invoke(const BandwidthData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JBandwidthData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_BandwidthData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_BandwidthData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_BandwidthData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_BandwidthData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_BandwidthData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_BandwidthData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_BandwidthData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp b/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp new file mode 100644 index 00000000..f52d8940 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp @@ -0,0 +1,80 @@ +/// +/// JFunc_void_TimedMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "TimedMetadata.hpp" +#include +#include "JTimedMetadata.hpp" +#include "TimedMetadataObject.hpp" +#include +#include "JTimedMetadataObject.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(metadata: TimedMetadata) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_TimedMetadata: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_TimedMetadata;"; + + public: + /** + * Invokes the function this `JFunc_void_TimedMetadata` instance holds through JNI. + */ + void invoke(const TimedMetadata& metadata) const { + static const auto method = javaClassStatic()->getMethod /* metadata */)>("invoke"); + method(self(), JTimedMetadata::fromCpp(metadata)); + } + }; + + /** + * An implementation of Func_void_TimedMetadata that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_TimedMetadata_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_TimedMetadata_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_TimedMetadata_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref metadata) { + _func(metadata->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_TimedMetadata_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_TimedMetadata_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_TimedMetadata_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_VideoPlayerStatus.hpp b/nitrogen/generated/android/c++/JFunc_void_VideoPlayerStatus.hpp new file mode 100644 index 00000000..ec3842a6 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_VideoPlayerStatus.hpp @@ -0,0 +1,76 @@ +/// +/// JFunc_void_VideoPlayerStatus.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "VideoPlayerStatus.hpp" +#include +#include "JVideoPlayerStatus.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(status: VideoPlayerStatus) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_VideoPlayerStatus: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_VideoPlayerStatus;"; + + public: + /** + * Invokes the function this `JFunc_void_VideoPlayerStatus` instance holds through JNI. + */ + void invoke(VideoPlayerStatus status) const { + static const auto method = javaClassStatic()->getMethod /* status */)>("invoke"); + method(self(), JVideoPlayerStatus::fromCpp(status)); + } + }; + + /** + * An implementation of Func_void_VideoPlayerStatus that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_VideoPlayerStatus_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_VideoPlayerStatus_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_VideoPlayerStatus_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref status) { + _func(status->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_VideoPlayerStatus_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_VideoPlayerStatus_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_VideoPlayerStatus_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_bool.hpp b/nitrogen/generated/android/c++/JFunc_void_bool.hpp new file mode 100644 index 00000000..aba55d48 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_bool.hpp @@ -0,0 +1,74 @@ +/// +/// JFunc_void_bool.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(isInPictureInPicture: Boolean) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_bool: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_bool;"; + + public: + /** + * Invokes the function this `JFunc_void_bool` instance holds through JNI. + */ + void invoke(bool isInPictureInPicture) const { + static const auto method = javaClassStatic()->getMethod("invoke"); + method(self(), isInPictureInPicture); + } + }; + + /** + * An implementation of Func_void_bool that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_bool_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_bool_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_bool_cxx` instance holds. + */ + void invoke_cxx(jboolean isInPictureInPicture) { + _func(static_cast(isInPictureInPicture)); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_bool_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_bool_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_bool_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_double.hpp b/nitrogen/generated/android/c++/JFunc_void_double.hpp new file mode 100644 index 00000000..653e2a01 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_double.hpp @@ -0,0 +1,74 @@ +/// +/// JFunc_void_double.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(rate: Double) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_double: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_double;"; + + public: + /** + * Invokes the function this `JFunc_void_double` instance holds through JNI. + */ + void invoke(double rate) const { + static const auto method = javaClassStatic()->getMethod("invoke"); + method(self(), rate); + } + }; + + /** + * An implementation of Func_void_double that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_double_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_double_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_double_cxx` instance holds. + */ + void invoke_cxx(double rate) { + _func(rate); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_double_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_double_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_double_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_onLoadData.hpp b/nitrogen/generated/android/c++/JFunc_void_onLoadData.hpp new file mode 100644 index 00000000..6d865d6c --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_onLoadData.hpp @@ -0,0 +1,78 @@ +/// +/// JFunc_void_onLoadData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "onLoadData.hpp" +#include +#include "JonLoadData.hpp" +#include "VideoOrientation.hpp" +#include "JVideoOrientation.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: onLoadData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_onLoadData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onLoadData;"; + + public: + /** + * Invokes the function this `JFunc_void_onLoadData` instance holds through JNI. + */ + void invoke(const onLoadData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JonLoadData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_onLoadData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_onLoadData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_onLoadData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_onLoadData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onLoadData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_onLoadData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_onLoadData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_onLoadStartData.hpp b/nitrogen/generated/android/c++/JFunc_void_onLoadStartData.hpp new file mode 100644 index 00000000..c59aac9f --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_onLoadStartData.hpp @@ -0,0 +1,81 @@ +/// +/// JFunc_void_onLoadStartData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "onLoadStartData.hpp" +#include +#include "JonLoadStartData.hpp" +#include "SourceType.hpp" +#include "JSourceType.hpp" +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: onLoadStartData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_onLoadStartData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onLoadStartData;"; + + public: + /** + * Invokes the function this `JFunc_void_onLoadStartData` instance holds through JNI. + */ + void invoke(const onLoadStartData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JonLoadStartData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_onLoadStartData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_onLoadStartData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_onLoadStartData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_onLoadStartData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onLoadStartData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_onLoadStartData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_onLoadStartData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_onPlaybackStateChangeData.hpp b/nitrogen/generated/android/c++/JFunc_void_onPlaybackStateChangeData.hpp new file mode 100644 index 00000000..9db750ad --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_onPlaybackStateChangeData.hpp @@ -0,0 +1,76 @@ +/// +/// JFunc_void_onPlaybackStateChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "onPlaybackStateChangeData.hpp" +#include +#include "JonPlaybackStateChangeData.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: onPlaybackStateChangeData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_onPlaybackStateChangeData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onPlaybackStateChangeData;"; + + public: + /** + * Invokes the function this `JFunc_void_onPlaybackStateChangeData` instance holds through JNI. + */ + void invoke(const onPlaybackStateChangeData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JonPlaybackStateChangeData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_onPlaybackStateChangeData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_onPlaybackStateChangeData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_onPlaybackStateChangeData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_onPlaybackStateChangeData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onPlaybackStateChangeData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_onPlaybackStateChangeData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_onPlaybackStateChangeData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_onProgressData.hpp b/nitrogen/generated/android/c++/JFunc_void_onProgressData.hpp new file mode 100644 index 00000000..13dcfff0 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_onProgressData.hpp @@ -0,0 +1,76 @@ +/// +/// JFunc_void_onProgressData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "onProgressData.hpp" +#include +#include "JonProgressData.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: onProgressData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_onProgressData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onProgressData;"; + + public: + /** + * Invokes the function this `JFunc_void_onProgressData` instance holds through JNI. + */ + void invoke(const onProgressData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JonProgressData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_onProgressData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_onProgressData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_onProgressData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_onProgressData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onProgressData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_onProgressData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_onProgressData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_onVolumeChangeData.hpp b/nitrogen/generated/android/c++/JFunc_void_onVolumeChangeData.hpp new file mode 100644 index 00000000..f4313d98 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_onVolumeChangeData.hpp @@ -0,0 +1,76 @@ +/// +/// JFunc_void_onVolumeChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "onVolumeChangeData.hpp" +#include +#include "JonVolumeChangeData.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(data: onVolumeChangeData) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_onVolumeChangeData: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onVolumeChangeData;"; + + public: + /** + * Invokes the function this `JFunc_void_onVolumeChangeData` instance holds through JNI. + */ + void invoke(const onVolumeChangeData& data) const { + static const auto method = javaClassStatic()->getMethod /* data */)>("invoke"); + method(self(), JonVolumeChangeData::fromCpp(data)); + } + }; + + /** + * An implementation of Func_void_onVolumeChangeData that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_onVolumeChangeData_cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& func) { + return JFunc_void_onVolumeChangeData_cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_onVolumeChangeData_cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref data) { + _func(data->toCpp()); + } + + public: + [[nodiscard]] + inline const std::function& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_onVolumeChangeData_cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_onVolumeChangeData_cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_onVolumeChangeData_cxx(const std::function& func): _func(func) { } + + private: + friend HybridBase; + std::function _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_std__optional_TextTrack_.hpp b/nitrogen/generated/android/c++/JFunc_void_std__optional_TextTrack_.hpp new file mode 100644 index 00000000..4cfc2e87 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_std__optional_TextTrack_.hpp @@ -0,0 +1,78 @@ +/// +/// JFunc_void_std__optional_TextTrack_.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include "TextTrack.hpp" +#include +#include +#include "JTextTrack.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(track: TextTrack?) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_std__optional_TextTrack_: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_std__optional_TextTrack_;"; + + public: + /** + * Invokes the function this `JFunc_void_std__optional_TextTrack_` instance holds through JNI. + */ + void invoke(const std::optional& track) const { + static const auto method = javaClassStatic()->getMethod /* track */)>("invoke"); + method(self(), track.has_value() ? JTextTrack::fromCpp(track.value()) : nullptr); + } + }; + + /** + * An implementation of Func_void_std__optional_TextTrack_ that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_std__optional_TextTrack__cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& /* track */)>& func) { + return JFunc_void_std__optional_TextTrack__cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_std__optional_TextTrack__cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref track) { + _func(track != nullptr ? std::make_optional(track->toCpp()) : std::nullopt); + } + + public: + [[nodiscard]] + inline const std::function& /* track */)>& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_std__optional_TextTrack__cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_std__optional_TextTrack__cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_std__optional_TextTrack__cxx(const std::function& /* track */)>& func): _func(func) { } + + private: + friend HybridBase; + std::function& /* track */)> _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JFunc_void_std__vector_std__string_.hpp b/nitrogen/generated/android/c++/JFunc_void_std__vector_std__string_.hpp new file mode 100644 index 00000000..50983a48 --- /dev/null +++ b/nitrogen/generated/android/c++/JFunc_void_std__vector_std__string_.hpp @@ -0,0 +1,93 @@ +/// +/// JFunc_void_std__vector_std__string_.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include + +#include +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * Represents the Java/Kotlin callback `(texts: Array) -> Unit`. + * This can be passed around between C++ and Java/Kotlin. + */ + struct JFunc_void_std__vector_std__string_: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_std__vector_std__string_;"; + + public: + /** + * Invokes the function this `JFunc_void_std__vector_std__string_` instance holds through JNI. + */ + void invoke(const std::vector& texts) const { + static const auto method = javaClassStatic()->getMethod> /* texts */)>("invoke"); + method(self(), [&]() { + size_t __size = texts.size(); + jni::local_ref> __array = jni::JArrayClass::newArray(__size); + for (size_t __i = 0; __i < __size; __i++) { + const auto& __element = texts[__i]; + __array->setElement(__i, *jni::make_jstring(__element)); + } + return __array; + }()); + } + }; + + /** + * An implementation of Func_void_std__vector_std__string_ that is backed by a C++ implementation (using `std::function<...>`) + */ + struct JFunc_void_std__vector_std__string__cxx final: public jni::HybridClass { + public: + static jni::local_ref fromCpp(const std::function& /* texts */)>& func) { + return JFunc_void_std__vector_std__string__cxx::newObjectCxxArgs(func); + } + + public: + /** + * Invokes the C++ `std::function<...>` this `JFunc_void_std__vector_std__string__cxx` instance holds. + */ + void invoke_cxx(jni::alias_ref> texts) { + _func([&]() { + size_t __size = texts->size(); + std::vector __vector; + __vector.reserve(__size); + for (size_t __i = 0; __i < __size; __i++) { + auto __element = texts->getElement(__i); + __vector.push_back(__element->toStdString()); + } + return __vector; + }()); + } + + public: + [[nodiscard]] + inline const std::function& /* texts */)>& getFunction() const { + return _func; + } + + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Func_void_std__vector_std__string__cxx;"; + static void registerNatives() { + registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_std__vector_std__string__cxx::invoke_cxx)}); + } + + private: + explicit JFunc_void_std__vector_std__string__cxx(const std::function& /* texts */)>& func): _func(func) { } + + private: + friend HybridBase; + std::function& /* texts */)> _func; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp b/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp new file mode 100644 index 00000000..ffe1f899 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp @@ -0,0 +1,470 @@ +/// +/// JHybridVideoPlayerEventEmitterSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoPlayerEventEmitterSpec.hpp" + +// Forward declaration of `BandwidthData` to properly resolve imports. +namespace margelo::nitro::video { struct BandwidthData; } +// Forward declaration of `onLoadData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadData; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } +// Forward declaration of `onLoadStartData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadStartData; } +// Forward declaration of `SourceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SourceType; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onPlaybackStateChangeData; } +// Forward declaration of `onProgressData` to properly resolve imports. +namespace margelo::nitro::video { struct onProgressData; } +// Forward declaration of `TimedMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadata; } +// Forward declaration of `TimedMetadataObject` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadataObject; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } +// Forward declaration of `onVolumeChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onVolumeChangeData; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } + +#include +#include "JFunc_void.hpp" +#include "JFunc_void_bool.hpp" +#include "BandwidthData.hpp" +#include "JFunc_void_BandwidthData.hpp" +#include "JBandwidthData.hpp" +#include +#include "onLoadData.hpp" +#include "JFunc_void_onLoadData.hpp" +#include "JonLoadData.hpp" +#include "VideoOrientation.hpp" +#include "JVideoOrientation.hpp" +#include "onLoadStartData.hpp" +#include "JFunc_void_onLoadStartData.hpp" +#include "JonLoadStartData.hpp" +#include "SourceType.hpp" +#include "JSourceType.hpp" +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" +#include "onPlaybackStateChangeData.hpp" +#include "JFunc_void_onPlaybackStateChangeData.hpp" +#include "JonPlaybackStateChangeData.hpp" +#include "JFunc_void_double.hpp" +#include "onProgressData.hpp" +#include "JFunc_void_onProgressData.hpp" +#include "JonProgressData.hpp" +#include "TimedMetadata.hpp" +#include "JFunc_void_TimedMetadata.hpp" +#include "JTimedMetadata.hpp" +#include "TimedMetadataObject.hpp" +#include +#include "JTimedMetadataObject.hpp" +#include +#include "JFunc_void_std__vector_std__string_.hpp" +#include "TextTrack.hpp" +#include "JFunc_void_std__optional_TextTrack_.hpp" +#include "JTextTrack.hpp" +#include "onVolumeChangeData.hpp" +#include "JFunc_void_onVolumeChangeData.hpp" +#include "JonVolumeChangeData.hpp" +#include "VideoPlayerStatus.hpp" +#include "JFunc_void_VideoPlayerStatus.hpp" +#include "JVideoPlayerStatus.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoPlayerEventEmitterSpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoPlayerEventEmitterSpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoPlayerEventEmitterSpec::initHybrid), + }); + } + + size_t JHybridVideoPlayerEventEmitterSpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoPlayerEventEmitterSpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + std::function JHybridVideoPlayerEventEmitterSpec::getOnAudioBecomingNoisy() { + static const auto method = javaClassStatic()->getMethod()>("getOnAudioBecomingNoisy_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnAudioBecomingNoisy(const std::function& onAudioBecomingNoisy) { + static const auto method = javaClassStatic()->getMethod /* onAudioBecomingNoisy */)>("setOnAudioBecomingNoisy_cxx"); + method(_javaPart, JFunc_void_cxx::fromCpp(onAudioBecomingNoisy)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnAudioFocusChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnAudioFocusChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool hasAudioFocus) -> void { + return __resultRef->invoke(hasAudioFocus); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnAudioFocusChange(const std::function& onAudioFocusChange) { + static const auto method = javaClassStatic()->getMethod /* onAudioFocusChange */)>("setOnAudioFocusChange_cxx"); + method(_javaPart, JFunc_void_bool_cxx::fromCpp(onAudioFocusChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnBandwidthUpdate() { + static const auto method = javaClassStatic()->getMethod()>("getOnBandwidthUpdate_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_BandwidthData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](BandwidthData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnBandwidthUpdate(const std::function& onBandwidthUpdate) { + static const auto method = javaClassStatic()->getMethod /* onBandwidthUpdate */)>("setOnBandwidthUpdate_cxx"); + method(_javaPart, JFunc_void_BandwidthData_cxx::fromCpp(onBandwidthUpdate)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnBuffer() { + static const auto method = javaClassStatic()->getMethod()>("getOnBuffer_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool buffering) -> void { + return __resultRef->invoke(buffering); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnBuffer(const std::function& onBuffer) { + static const auto method = javaClassStatic()->getMethod /* onBuffer */)>("setOnBuffer_cxx"); + method(_javaPart, JFunc_void_bool_cxx::fromCpp(onBuffer)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnControlsVisibleChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnControlsVisibleChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool visible) -> void { + return __resultRef->invoke(visible); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnControlsVisibleChange(const std::function& onControlsVisibleChange) { + static const auto method = javaClassStatic()->getMethod /* onControlsVisibleChange */)>("setOnControlsVisibleChange_cxx"); + method(_javaPart, JFunc_void_bool_cxx::fromCpp(onControlsVisibleChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnEnd() { + static const auto method = javaClassStatic()->getMethod()>("getOnEnd_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnEnd(const std::function& onEnd) { + static const auto method = javaClassStatic()->getMethod /* onEnd */)>("setOnEnd_cxx"); + method(_javaPart, JFunc_void_cxx::fromCpp(onEnd)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnExternalPlaybackChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnExternalPlaybackChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool externalPlaybackActive) -> void { + return __resultRef->invoke(externalPlaybackActive); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnExternalPlaybackChange(const std::function& onExternalPlaybackChange) { + static const auto method = javaClassStatic()->getMethod /* onExternalPlaybackChange */)>("setOnExternalPlaybackChange_cxx"); + method(_javaPart, JFunc_void_bool_cxx::fromCpp(onExternalPlaybackChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnLoad() { + static const auto method = javaClassStatic()->getMethod()>("getOnLoad_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_onLoadData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](onLoadData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnLoad(const std::function& onLoad) { + static const auto method = javaClassStatic()->getMethod /* onLoad */)>("setOnLoad_cxx"); + method(_javaPart, JFunc_void_onLoadData_cxx::fromCpp(onLoad)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnLoadStart() { + static const auto method = javaClassStatic()->getMethod()>("getOnLoadStart_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_onLoadStartData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](onLoadStartData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnLoadStart(const std::function& onLoadStart) { + static const auto method = javaClassStatic()->getMethod /* onLoadStart */)>("setOnLoadStart_cxx"); + method(_javaPart, JFunc_void_onLoadStartData_cxx::fromCpp(onLoadStart)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnPlaybackStateChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnPlaybackStateChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_onPlaybackStateChangeData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](onPlaybackStateChangeData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnPlaybackStateChange(const std::function& onPlaybackStateChange) { + static const auto method = javaClassStatic()->getMethod /* onPlaybackStateChange */)>("setOnPlaybackStateChange_cxx"); + method(_javaPart, JFunc_void_onPlaybackStateChangeData_cxx::fromCpp(onPlaybackStateChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnPlaybackRateChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnPlaybackRateChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_double_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](double rate) -> void { + return __resultRef->invoke(rate); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnPlaybackRateChange(const std::function& onPlaybackRateChange) { + static const auto method = javaClassStatic()->getMethod /* onPlaybackRateChange */)>("setOnPlaybackRateChange_cxx"); + method(_javaPart, JFunc_void_double_cxx::fromCpp(onPlaybackRateChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnProgress() { + static const auto method = javaClassStatic()->getMethod()>("getOnProgress_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_onProgressData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](onProgressData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnProgress(const std::function& onProgress) { + static const auto method = javaClassStatic()->getMethod /* onProgress */)>("setOnProgress_cxx"); + method(_javaPart, JFunc_void_onProgressData_cxx::fromCpp(onProgress)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnReadyToDisplay() { + static const auto method = javaClassStatic()->getMethod()>("getOnReadyToDisplay_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnReadyToDisplay(const std::function& onReadyToDisplay) { + static const auto method = javaClassStatic()->getMethod /* onReadyToDisplay */)>("setOnReadyToDisplay_cxx"); + method(_javaPart, JFunc_void_cxx::fromCpp(onReadyToDisplay)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnSeek() { + static const auto method = javaClassStatic()->getMethod()>("getOnSeek_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_double_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](double seekTime) -> void { + return __resultRef->invoke(seekTime); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnSeek(const std::function& onSeek) { + static const auto method = javaClassStatic()->getMethod /* onSeek */)>("setOnSeek_cxx"); + method(_javaPart, JFunc_void_double_cxx::fromCpp(onSeek)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnTimedMetadata() { + static const auto method = javaClassStatic()->getMethod()>("getOnTimedMetadata_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_TimedMetadata_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](TimedMetadata metadata) -> void { + return __resultRef->invoke(metadata); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnTimedMetadata(const std::function& onTimedMetadata) { + static const auto method = javaClassStatic()->getMethod /* onTimedMetadata */)>("setOnTimedMetadata_cxx"); + method(_javaPart, JFunc_void_TimedMetadata_cxx::fromCpp(onTimedMetadata)); + } + std::function& /* texts */)> JHybridVideoPlayerEventEmitterSpec::getOnTextTrackDataChanged() { + static const auto method = javaClassStatic()->getMethod()>("getOnTextTrackDataChanged_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function& /* texts */)> { + if (__result->isInstanceOf(JFunc_void_std__vector_std__string__cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](std::vector texts) -> void { + return __resultRef->invoke(texts); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnTextTrackDataChanged(const std::function& /* texts */)>& onTextTrackDataChanged) { + static const auto method = javaClassStatic()->getMethod /* onTextTrackDataChanged */)>("setOnTextTrackDataChanged_cxx"); + method(_javaPart, JFunc_void_std__vector_std__string__cxx::fromCpp(onTextTrackDataChanged)); + } + std::function& /* track */)> JHybridVideoPlayerEventEmitterSpec::getOnTrackChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnTrackChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function& /* track */)> { + if (__result->isInstanceOf(JFunc_void_std__optional_TextTrack__cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](std::optional track) -> void { + return __resultRef->invoke(track); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnTrackChange(const std::function& /* track */)>& onTrackChange) { + static const auto method = javaClassStatic()->getMethod /* onTrackChange */)>("setOnTrackChange_cxx"); + method(_javaPart, JFunc_void_std__optional_TextTrack__cxx::fromCpp(onTrackChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnVolumeChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnVolumeChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_onVolumeChangeData_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](onVolumeChangeData data) -> void { + return __resultRef->invoke(data); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnVolumeChange(const std::function& onVolumeChange) { + static const auto method = javaClassStatic()->getMethod /* onVolumeChange */)>("setOnVolumeChange_cxx"); + method(_javaPart, JFunc_void_onVolumeChangeData_cxx::fromCpp(onVolumeChange)); + } + std::function JHybridVideoPlayerEventEmitterSpec::getOnStatusChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnStatusChange_cxx"); + auto __result = method(_javaPart); + return [&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_VideoPlayerStatus_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](VideoPlayerStatus status) -> void { + return __resultRef->invoke(status); + }; + } + }(); + } + void JHybridVideoPlayerEventEmitterSpec::setOnStatusChange(const std::function& onStatusChange) { + static const auto method = javaClassStatic()->getMethod /* onStatusChange */)>("setOnStatusChange_cxx"); + method(_javaPart, JFunc_void_VideoPlayerStatus_cxx::fromCpp(onStatusChange)); + } + + // Methods + + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.hpp b/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.hpp new file mode 100644 index 00000000..589919d0 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.hpp @@ -0,0 +1,101 @@ +/// +/// HybridVideoPlayerEventEmitterSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoPlayerEventEmitterSpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoPlayerEventEmitterSpec: public jni::HybridClass, + public virtual HybridVideoPlayerEventEmitterSpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoPlayerEventEmitterSpec(jni::alias_ref jThis) : + HybridObject(HybridVideoPlayerEventEmitterSpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoPlayerEventEmitterSpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + std::function getOnAudioBecomingNoisy() override; + void setOnAudioBecomingNoisy(const std::function& onAudioBecomingNoisy) override; + std::function getOnAudioFocusChange() override; + void setOnAudioFocusChange(const std::function& onAudioFocusChange) override; + std::function getOnBandwidthUpdate() override; + void setOnBandwidthUpdate(const std::function& onBandwidthUpdate) override; + std::function getOnBuffer() override; + void setOnBuffer(const std::function& onBuffer) override; + std::function getOnControlsVisibleChange() override; + void setOnControlsVisibleChange(const std::function& onControlsVisibleChange) override; + std::function getOnEnd() override; + void setOnEnd(const std::function& onEnd) override; + std::function getOnExternalPlaybackChange() override; + void setOnExternalPlaybackChange(const std::function& onExternalPlaybackChange) override; + std::function getOnLoad() override; + void setOnLoad(const std::function& onLoad) override; + std::function getOnLoadStart() override; + void setOnLoadStart(const std::function& onLoadStart) override; + std::function getOnPlaybackStateChange() override; + void setOnPlaybackStateChange(const std::function& onPlaybackStateChange) override; + std::function getOnPlaybackRateChange() override; + void setOnPlaybackRateChange(const std::function& onPlaybackRateChange) override; + std::function getOnProgress() override; + void setOnProgress(const std::function& onProgress) override; + std::function getOnReadyToDisplay() override; + void setOnReadyToDisplay(const std::function& onReadyToDisplay) override; + std::function getOnSeek() override; + void setOnSeek(const std::function& onSeek) override; + std::function getOnTimedMetadata() override; + void setOnTimedMetadata(const std::function& onTimedMetadata) override; + std::function& /* texts */)> getOnTextTrackDataChanged() override; + void setOnTextTrackDataChanged(const std::function& /* texts */)>& onTextTrackDataChanged) override; + std::function& /* track */)> getOnTrackChange() override; + void setOnTrackChange(const std::function& /* track */)>& onTrackChange) override; + std::function getOnVolumeChange() override; + void setOnVolumeChange(const std::function& onVolumeChange) override; + std::function getOnStatusChange() override; + void setOnStatusChange(const std::function& onStatusChange) override; + + public: + // Methods + + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp b/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp new file mode 100644 index 00000000..5eeb9a9c --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp @@ -0,0 +1,53 @@ +/// +/// JHybridVideoPlayerFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoPlayerFactorySpec.hpp" + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include "JHybridVideoPlayerSpec.hpp" +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoPlayerFactorySpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoPlayerFactorySpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoPlayerFactorySpec::initHybrid), + }); + } + + size_t JHybridVideoPlayerFactorySpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoPlayerFactorySpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + + + // Methods + std::shared_ptr JHybridVideoPlayerFactorySpec::createPlayer(const std::shared_ptr& source) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* source */)>("createPlayer"); + auto __result = method(_javaPart, std::dynamic_pointer_cast(source)->getJavaPart()); + return __result->cthis()->shared_cast(); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.hpp b/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.hpp new file mode 100644 index 00000000..eba1b7ba --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.hpp @@ -0,0 +1,64 @@ +/// +/// HybridVideoPlayerFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoPlayerFactorySpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoPlayerFactorySpec: public jni::HybridClass, + public virtual HybridVideoPlayerFactorySpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoPlayerFactorySpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoPlayerFactorySpec(jni::alias_ref jThis) : + HybridObject(HybridVideoPlayerFactorySpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoPlayerFactorySpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + + + public: + // Methods + std::shared_ptr createPlayer(const std::shared_ptr& source) override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp new file mode 100644 index 00000000..62f47e87 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp @@ -0,0 +1,98 @@ +/// +/// JHybridVideoPlayerSourceFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoPlayerSourceFactorySpec.hpp" + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" +#include +#include "NativeVideoConfig.hpp" +#include "JNativeVideoConfig.hpp" +#include "NativeExternalSubtitle.hpp" +#include +#include +#include "JNativeExternalSubtitle.hpp" +#include "SubtitleType.hpp" +#include "JSubtitleType.hpp" +#include "NativeDrmParams.hpp" +#include "JNativeDrmParams.hpp" +#include +#include +#include "OnGetLicensePayload.hpp" +#include +#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp" +#include +#include "JOnGetLicensePayload.hpp" +#include "BufferConfig.hpp" +#include "JBufferConfig.hpp" +#include "LivePlaybackParams.hpp" +#include "JLivePlaybackParams.hpp" +#include "Resolution.hpp" +#include "JResolution.hpp" +#include "CustomVideoMetadata.hpp" +#include "JCustomVideoMetadata.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoPlayerSourceFactorySpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoPlayerSourceFactorySpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoPlayerSourceFactorySpec::initHybrid), + }); + } + + size_t JHybridVideoPlayerSourceFactorySpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoPlayerSourceFactorySpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + + + // Methods + std::shared_ptr JHybridVideoPlayerSourceFactorySpec::fromUri(const std::string& uri) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* uri */)>("fromUri"); + auto __result = method(_javaPart, jni::make_jstring(uri)); + return __result->cthis()->shared_cast(); + } + std::shared_ptr JHybridVideoPlayerSourceFactorySpec::fromVideoConfig(const NativeVideoConfig& config) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* config */)>("fromVideoConfig"); + auto __result = method(_javaPart, JNativeVideoConfig::fromCpp(config)); + return __result->cthis()->shared_cast(); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.hpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.hpp new file mode 100644 index 00000000..b7ffa7f2 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.hpp @@ -0,0 +1,65 @@ +/// +/// HybridVideoPlayerSourceFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoPlayerSourceFactorySpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoPlayerSourceFactorySpec: public jni::HybridClass, + public virtual HybridVideoPlayerSourceFactorySpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoPlayerSourceFactorySpec(jni::alias_ref jThis) : + HybridObject(HybridVideoPlayerSourceFactorySpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoPlayerSourceFactorySpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + + + public: + // Methods + std::shared_ptr fromUri(const std::string& uri) override; + std::shared_ptr fromVideoConfig(const NativeVideoConfig& config) override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp new file mode 100644 index 00000000..625752a4 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp @@ -0,0 +1,116 @@ +/// +/// JHybridVideoPlayerSourceSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoPlayerSourceSpec.hpp" + +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } +// Forward declaration of `VideoInformation` to properly resolve imports. +namespace margelo::nitro::video { struct VideoInformation; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } + +#include +#include "NativeVideoConfig.hpp" +#include "JNativeVideoConfig.hpp" +#include "NativeExternalSubtitle.hpp" +#include +#include +#include "JNativeExternalSubtitle.hpp" +#include "SubtitleType.hpp" +#include "JSubtitleType.hpp" +#include "NativeDrmParams.hpp" +#include "JNativeDrmParams.hpp" +#include +#include +#include "OnGetLicensePayload.hpp" +#include +#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp" +#include +#include "JOnGetLicensePayload.hpp" +#include "BufferConfig.hpp" +#include "JBufferConfig.hpp" +#include "LivePlaybackParams.hpp" +#include "JLivePlaybackParams.hpp" +#include "Resolution.hpp" +#include "JResolution.hpp" +#include "CustomVideoMetadata.hpp" +#include "JCustomVideoMetadata.hpp" +#include "VideoInformation.hpp" +#include "JVideoInformation.hpp" +#include "VideoOrientation.hpp" +#include "JVideoOrientation.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoPlayerSourceSpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoPlayerSourceSpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoPlayerSourceSpec::initHybrid), + }); + } + + size_t JHybridVideoPlayerSourceSpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoPlayerSourceSpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + std::string JHybridVideoPlayerSourceSpec::getUri() { + static const auto method = javaClassStatic()->getMethod()>("getUri"); + auto __result = method(_javaPart); + return __result->toStdString(); + } + NativeVideoConfig JHybridVideoPlayerSourceSpec::getConfig() { + static const auto method = javaClassStatic()->getMethod()>("getConfig"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + + // Methods + std::shared_ptr> JHybridVideoPlayerSourceSpec::getAssetInformationAsync() { + static const auto method = javaClassStatic()->getMethod()>("getAssetInformationAsync"); + auto __result = method(_javaPart); + return [&]() { + auto __promise = Promise::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { + auto __result = jni::static_ref_cast(__boxedResult); + __promise->resolve(__result->toCpp()); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.hpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.hpp new file mode 100644 index 00000000..82fa476f --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.hpp @@ -0,0 +1,65 @@ +/// +/// HybridVideoPlayerSourceSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoPlayerSourceSpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoPlayerSourceSpec: public jni::HybridClass, + public virtual HybridVideoPlayerSourceSpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoPlayerSourceSpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoPlayerSourceSpec(jni::alias_ref jThis) : + HybridObject(HybridVideoPlayerSourceSpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoPlayerSourceSpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + std::string getUri() override; + NativeVideoConfig getConfig() override; + + public: + // Methods + std::shared_ptr> getAssetInformationAsync() override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp new file mode 100644 index 00000000..0afead62 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp @@ -0,0 +1,267 @@ +/// +/// JHybridVideoPlayerSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoPlayerSpec.hpp" + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } +// Forward declaration of `MixAudioMode` to properly resolve imports. +namespace margelo::nitro::video { enum class MixAudioMode; } +// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports. +namespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" +#include "HybridVideoPlayerEventEmitterSpec.hpp" +#include "JHybridVideoPlayerEventEmitterSpec.hpp" +#include "VideoPlayerStatus.hpp" +#include "JVideoPlayerStatus.hpp" +#include "MixAudioMode.hpp" +#include "JMixAudioMode.hpp" +#include "IgnoreSilentSwitchMode.hpp" +#include "JIgnoreSilentSwitchMode.hpp" +#include "TextTrack.hpp" +#include +#include "JTextTrack.hpp" +#include +#include +#include +#include + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoPlayerSpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoPlayerSpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoPlayerSpec::initHybrid), + }); + } + + size_t JHybridVideoPlayerSpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoPlayerSpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + std::shared_ptr JHybridVideoPlayerSpec::getSource() { + static const auto method = javaClassStatic()->getMethod()>("getSource"); + auto __result = method(_javaPart); + return __result->cthis()->shared_cast(); + } + std::shared_ptr JHybridVideoPlayerSpec::getEventEmitter() { + static const auto method = javaClassStatic()->getMethod()>("getEventEmitter"); + auto __result = method(_javaPart); + return __result->cthis()->shared_cast(); + } + bool JHybridVideoPlayerSpec::getShowNotificationControls() { + static const auto method = javaClassStatic()->getMethod("getShowNotificationControls"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoPlayerSpec::setShowNotificationControls(bool showNotificationControls) { + static const auto method = javaClassStatic()->getMethod("setShowNotificationControls"); + method(_javaPart, showNotificationControls); + } + VideoPlayerStatus JHybridVideoPlayerSpec::getStatus() { + static const auto method = javaClassStatic()->getMethod()>("getStatus"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + double JHybridVideoPlayerSpec::getDuration() { + static const auto method = javaClassStatic()->getMethod("getDuration"); + auto __result = method(_javaPart); + return __result; + } + double JHybridVideoPlayerSpec::getVolume() { + static const auto method = javaClassStatic()->getMethod("getVolume"); + auto __result = method(_javaPart); + return __result; + } + void JHybridVideoPlayerSpec::setVolume(double volume) { + static const auto method = javaClassStatic()->getMethod("setVolume"); + method(_javaPart, volume); + } + double JHybridVideoPlayerSpec::getCurrentTime() { + static const auto method = javaClassStatic()->getMethod("getCurrentTime"); + auto __result = method(_javaPart); + return __result; + } + void JHybridVideoPlayerSpec::setCurrentTime(double currentTime) { + static const auto method = javaClassStatic()->getMethod("setCurrentTime"); + method(_javaPart, currentTime); + } + bool JHybridVideoPlayerSpec::getMuted() { + static const auto method = javaClassStatic()->getMethod("getMuted"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoPlayerSpec::setMuted(bool muted) { + static const auto method = javaClassStatic()->getMethod("setMuted"); + method(_javaPart, muted); + } + bool JHybridVideoPlayerSpec::getLoop() { + static const auto method = javaClassStatic()->getMethod("getLoop"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoPlayerSpec::setLoop(bool loop) { + static const auto method = javaClassStatic()->getMethod("setLoop"); + method(_javaPart, loop); + } + double JHybridVideoPlayerSpec::getRate() { + static const auto method = javaClassStatic()->getMethod("getRate"); + auto __result = method(_javaPart); + return __result; + } + void JHybridVideoPlayerSpec::setRate(double rate) { + static const auto method = javaClassStatic()->getMethod("setRate"); + method(_javaPart, rate); + } + MixAudioMode JHybridVideoPlayerSpec::getMixAudioMode() { + static const auto method = javaClassStatic()->getMethod()>("getMixAudioMode"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + void JHybridVideoPlayerSpec::setMixAudioMode(MixAudioMode mixAudioMode) { + static const auto method = javaClassStatic()->getMethod /* mixAudioMode */)>("setMixAudioMode"); + method(_javaPart, JMixAudioMode::fromCpp(mixAudioMode)); + } + IgnoreSilentSwitchMode JHybridVideoPlayerSpec::getIgnoreSilentSwitchMode() { + static const auto method = javaClassStatic()->getMethod()>("getIgnoreSilentSwitchMode"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + void JHybridVideoPlayerSpec::setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) { + static const auto method = javaClassStatic()->getMethod /* ignoreSilentSwitchMode */)>("setIgnoreSilentSwitchMode"); + method(_javaPart, JIgnoreSilentSwitchMode::fromCpp(ignoreSilentSwitchMode)); + } + bool JHybridVideoPlayerSpec::getPlayInBackground() { + static const auto method = javaClassStatic()->getMethod("getPlayInBackground"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoPlayerSpec::setPlayInBackground(bool playInBackground) { + static const auto method = javaClassStatic()->getMethod("setPlayInBackground"); + method(_javaPart, playInBackground); + } + bool JHybridVideoPlayerSpec::getPlayWhenInactive() { + static const auto method = javaClassStatic()->getMethod("getPlayWhenInactive"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoPlayerSpec::setPlayWhenInactive(bool playWhenInactive) { + static const auto method = javaClassStatic()->getMethod("setPlayWhenInactive"); + method(_javaPart, playWhenInactive); + } + bool JHybridVideoPlayerSpec::getIsPlaying() { + static const auto method = javaClassStatic()->getMethod("isPlaying"); + auto __result = method(_javaPart); + return static_cast(__result); + } + std::optional JHybridVideoPlayerSpec::getSelectedTrack() { + static const auto method = javaClassStatic()->getMethod()>("getSelectedTrack"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional(__result->toCpp()) : std::nullopt; + } + + // Methods + std::shared_ptr> JHybridVideoPlayerSpec::replaceSourceAsync(const std::optional>& source) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* source */)>("replaceSourceAsync"); + auto __result = method(_javaPart, source.has_value() ? std::dynamic_pointer_cast(source.value())->getJavaPart() : nullptr); + return [&]() { + auto __promise = Promise::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& /* unit */) { + __promise->resolve(); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } + std::vector JHybridVideoPlayerSpec::getAvailableTextTracks() { + static const auto method = javaClassStatic()->getMethod>()>("getAvailableTextTracks"); + auto __result = method(_javaPart); + return [&]() { + size_t __size = __result->size(); + std::vector __vector; + __vector.reserve(__size); + for (size_t __i = 0; __i < __size; __i++) { + auto __element = __result->getElement(__i); + __vector.push_back(__element->toCpp()); + } + return __vector; + }(); + } + void JHybridVideoPlayerSpec::selectTextTrack(const std::optional& textTrack) { + static const auto method = javaClassStatic()->getMethod /* textTrack */)>("selectTextTrack"); + method(_javaPart, textTrack.has_value() ? JTextTrack::fromCpp(textTrack.value()) : nullptr); + } + std::shared_ptr> JHybridVideoPlayerSpec::initialize() { + static const auto method = javaClassStatic()->getMethod()>("initialize"); + auto __result = method(_javaPart); + return [&]() { + auto __promise = Promise::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& /* unit */) { + __promise->resolve(); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } + std::shared_ptr> JHybridVideoPlayerSpec::preload() { + static const auto method = javaClassStatic()->getMethod()>("preload"); + auto __result = method(_javaPart); + return [&]() { + auto __promise = Promise::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& /* unit */) { + __promise->resolve(); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } + void JHybridVideoPlayerSpec::play() { + static const auto method = javaClassStatic()->getMethod("play"); + method(_javaPart); + } + void JHybridVideoPlayerSpec::pause() { + static const auto method = javaClassStatic()->getMethod("pause"); + method(_javaPart); + } + void JHybridVideoPlayerSpec::seekBy(double time) { + static const auto method = javaClassStatic()->getMethod("seekBy"); + method(_javaPart, time); + } + void JHybridVideoPlayerSpec::seekTo(double time) { + static const auto method = javaClassStatic()->getMethod("seekTo"); + method(_javaPart, time); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.hpp b/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.hpp new file mode 100644 index 00000000..292b07fd --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.hpp @@ -0,0 +1,97 @@ +/// +/// HybridVideoPlayerSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoPlayerSpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoPlayerSpec: public jni::HybridClass, + public virtual HybridVideoPlayerSpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoPlayerSpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoPlayerSpec(jni::alias_ref jThis) : + HybridObject(HybridVideoPlayerSpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoPlayerSpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + std::shared_ptr getSource() override; + std::shared_ptr getEventEmitter() override; + bool getShowNotificationControls() override; + void setShowNotificationControls(bool showNotificationControls) override; + VideoPlayerStatus getStatus() override; + double getDuration() override; + double getVolume() override; + void setVolume(double volume) override; + double getCurrentTime() override; + void setCurrentTime(double currentTime) override; + bool getMuted() override; + void setMuted(bool muted) override; + bool getLoop() override; + void setLoop(bool loop) override; + double getRate() override; + void setRate(double rate) override; + MixAudioMode getMixAudioMode() override; + void setMixAudioMode(MixAudioMode mixAudioMode) override; + IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() override; + void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) override; + bool getPlayInBackground() override; + void setPlayInBackground(bool playInBackground) override; + bool getPlayWhenInactive() override; + void setPlayWhenInactive(bool playWhenInactive) override; + bool getIsPlaying() override; + std::optional getSelectedTrack() override; + + public: + // Methods + std::shared_ptr> replaceSourceAsync(const std::optional>& source) override; + std::vector getAvailableTextTracks() override; + void selectTextTrack(const std::optional& textTrack) override; + std::shared_ptr> initialize() override; + std::shared_ptr> preload() override; + void play() override; + void pause() override; + void seekBy(double time) override; + void seekTo(double time) override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp new file mode 100644 index 00000000..e3110548 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp @@ -0,0 +1,49 @@ +/// +/// JHybridVideoViewViewManagerFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoViewViewManagerFactorySpec.hpp" + +// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; } + +#include +#include "HybridVideoViewViewManagerSpec.hpp" +#include "JHybridVideoViewViewManagerSpec.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoViewViewManagerFactorySpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoViewViewManagerFactorySpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoViewViewManagerFactorySpec::initHybrid), + }); + } + + size_t JHybridVideoViewViewManagerFactorySpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoViewViewManagerFactorySpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + + + // Methods + std::shared_ptr JHybridVideoViewViewManagerFactorySpec::createViewManager(double nitroId) { + static const auto method = javaClassStatic()->getMethod(double /* nitroId */)>("createViewManager"); + auto __result = method(_javaPart, nitroId); + return __result->cthis()->shared_cast(); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.hpp b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.hpp new file mode 100644 index 00000000..1e2b59c8 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.hpp @@ -0,0 +1,64 @@ +/// +/// HybridVideoViewViewManagerFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoViewViewManagerFactorySpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoViewViewManagerFactorySpec: public jni::HybridClass, + public virtual HybridVideoViewViewManagerFactorySpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoViewViewManagerFactorySpec(jni::alias_ref jThis) : + HybridObject(HybridVideoViewViewManagerFactorySpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoViewViewManagerFactorySpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + + + public: + // Methods + std::shared_ptr createViewManager(double nitroId) override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp new file mode 100644 index 00000000..afd45488 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp @@ -0,0 +1,253 @@ +/// +/// JHybridVideoViewViewManagerSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "JHybridVideoViewViewManagerSpec.hpp" + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `ResizeMode` to properly resolve imports. +namespace margelo::nitro::video { enum class ResizeMode; } +// Forward declaration of `SurfaceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SurfaceType; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include +#include "JHybridVideoPlayerSpec.hpp" +#include "ResizeMode.hpp" +#include "JResizeMode.hpp" +#include "SurfaceType.hpp" +#include "JSurfaceType.hpp" +#include +#include "JFunc_void_bool.hpp" +#include "JFunc_void.hpp" + +namespace margelo::nitro::video { + + jni::local_ref JHybridVideoViewViewManagerSpec::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + void JHybridVideoViewViewManagerSpec::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridVideoViewViewManagerSpec::initHybrid), + }); + } + + size_t JHybridVideoViewViewManagerSpec::getExternalMemorySize() noexcept { + static const auto method = javaClassStatic()->getMethod("getMemorySize"); + return method(_javaPart); + } + + void JHybridVideoViewViewManagerSpec::dispose() noexcept { + static const auto method = javaClassStatic()->getMethod("dispose"); + method(_javaPart); + } + + // Properties + std::optional> JHybridVideoViewViewManagerSpec::getPlayer() { + static const auto method = javaClassStatic()->getMethod()>("getPlayer"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional(__result->cthis()->shared_cast()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setPlayer(const std::optional>& player) { + static const auto method = javaClassStatic()->getMethod /* player */)>("setPlayer"); + method(_javaPart, player.has_value() ? std::dynamic_pointer_cast(player.value())->getJavaPart() : nullptr); + } + bool JHybridVideoViewViewManagerSpec::getControls() { + static const auto method = javaClassStatic()->getMethod("getControls"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoViewViewManagerSpec::setControls(bool controls) { + static const auto method = javaClassStatic()->getMethod("setControls"); + method(_javaPart, controls); + } + bool JHybridVideoViewViewManagerSpec::getPictureInPicture() { + static const auto method = javaClassStatic()->getMethod("getPictureInPicture"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoViewViewManagerSpec::setPictureInPicture(bool pictureInPicture) { + static const auto method = javaClassStatic()->getMethod("setPictureInPicture"); + method(_javaPart, pictureInPicture); + } + bool JHybridVideoViewViewManagerSpec::getAutoEnterPictureInPicture() { + static const auto method = javaClassStatic()->getMethod("getAutoEnterPictureInPicture"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoViewViewManagerSpec::setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) { + static const auto method = javaClassStatic()->getMethod("setAutoEnterPictureInPicture"); + method(_javaPart, autoEnterPictureInPicture); + } + ResizeMode JHybridVideoViewViewManagerSpec::getResizeMode() { + static const auto method = javaClassStatic()->getMethod()>("getResizeMode"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + void JHybridVideoViewViewManagerSpec::setResizeMode(ResizeMode resizeMode) { + static const auto method = javaClassStatic()->getMethod /* resizeMode */)>("setResizeMode"); + method(_javaPart, JResizeMode::fromCpp(resizeMode)); + } + bool JHybridVideoViewViewManagerSpec::getKeepScreenAwake() { + static const auto method = javaClassStatic()->getMethod("getKeepScreenAwake"); + auto __result = method(_javaPart); + return static_cast(__result); + } + void JHybridVideoViewViewManagerSpec::setKeepScreenAwake(bool keepScreenAwake) { + static const auto method = javaClassStatic()->getMethod("setKeepScreenAwake"); + method(_javaPart, keepScreenAwake); + } + SurfaceType JHybridVideoViewViewManagerSpec::getSurfaceType() { + static const auto method = javaClassStatic()->getMethod()>("getSurfaceType"); + auto __result = method(_javaPart); + return __result->toCpp(); + } + void JHybridVideoViewViewManagerSpec::setSurfaceType(SurfaceType surfaceType) { + static const auto method = javaClassStatic()->getMethod /* surfaceType */)>("setSurfaceType"); + method(_javaPart, JSurfaceType::fromCpp(surfaceType)); + } + std::optional> JHybridVideoViewViewManagerSpec::getOnPictureInPictureChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnPictureInPictureChange_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool isInPictureInPicture) -> void { + return __resultRef->invoke(isInPictureInPicture); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setOnPictureInPictureChange(const std::optional>& onPictureInPictureChange) { + static const auto method = javaClassStatic()->getMethod /* onPictureInPictureChange */)>("setOnPictureInPictureChange_cxx"); + method(_javaPart, onPictureInPictureChange.has_value() ? JFunc_void_bool_cxx::fromCpp(onPictureInPictureChange.value()) : nullptr); + } + std::optional> JHybridVideoViewViewManagerSpec::getOnFullscreenChange() { + static const auto method = javaClassStatic()->getMethod()>("getOnFullscreenChange_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_bool_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef](bool fullscreen) -> void { + return __resultRef->invoke(fullscreen); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setOnFullscreenChange(const std::optional>& onFullscreenChange) { + static const auto method = javaClassStatic()->getMethod /* onFullscreenChange */)>("setOnFullscreenChange_cxx"); + method(_javaPart, onFullscreenChange.has_value() ? JFunc_void_bool_cxx::fromCpp(onFullscreenChange.value()) : nullptr); + } + std::optional> JHybridVideoViewViewManagerSpec::getWillEnterFullscreen() { + static const auto method = javaClassStatic()->getMethod()>("getWillEnterFullscreen_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setWillEnterFullscreen(const std::optional>& willEnterFullscreen) { + static const auto method = javaClassStatic()->getMethod /* willEnterFullscreen */)>("setWillEnterFullscreen_cxx"); + method(_javaPart, willEnterFullscreen.has_value() ? JFunc_void_cxx::fromCpp(willEnterFullscreen.value()) : nullptr); + } + std::optional> JHybridVideoViewViewManagerSpec::getWillExitFullscreen() { + static const auto method = javaClassStatic()->getMethod()>("getWillExitFullscreen_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setWillExitFullscreen(const std::optional>& willExitFullscreen) { + static const auto method = javaClassStatic()->getMethod /* willExitFullscreen */)>("setWillExitFullscreen_cxx"); + method(_javaPart, willExitFullscreen.has_value() ? JFunc_void_cxx::fromCpp(willExitFullscreen.value()) : nullptr); + } + std::optional> JHybridVideoViewViewManagerSpec::getWillEnterPictureInPicture() { + static const auto method = javaClassStatic()->getMethod()>("getWillEnterPictureInPicture_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setWillEnterPictureInPicture(const std::optional>& willEnterPictureInPicture) { + static const auto method = javaClassStatic()->getMethod /* willEnterPictureInPicture */)>("setWillEnterPictureInPicture_cxx"); + method(_javaPart, willEnterPictureInPicture.has_value() ? JFunc_void_cxx::fromCpp(willEnterPictureInPicture.value()) : nullptr); + } + std::optional> JHybridVideoViewViewManagerSpec::getWillExitPictureInPicture() { + static const auto method = javaClassStatic()->getMethod()>("getWillExitPictureInPicture_cxx"); + auto __result = method(_javaPart); + return __result != nullptr ? std::make_optional([&]() -> std::function { + if (__result->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(__result); + return downcast->cthis()->getFunction(); + } else { + auto __resultRef = jni::make_global(__result); + return [__resultRef]() -> void { + return __resultRef->invoke(); + }; + } + }()) : std::nullopt; + } + void JHybridVideoViewViewManagerSpec::setWillExitPictureInPicture(const std::optional>& willExitPictureInPicture) { + static const auto method = javaClassStatic()->getMethod /* willExitPictureInPicture */)>("setWillExitPictureInPicture_cxx"); + method(_javaPart, willExitPictureInPicture.has_value() ? JFunc_void_cxx::fromCpp(willExitPictureInPicture.value()) : nullptr); + } + + // Methods + void JHybridVideoViewViewManagerSpec::enterFullscreen() { + static const auto method = javaClassStatic()->getMethod("enterFullscreen"); + method(_javaPart); + } + void JHybridVideoViewViewManagerSpec::exitFullscreen() { + static const auto method = javaClassStatic()->getMethod("exitFullscreen"); + method(_javaPart); + } + void JHybridVideoViewViewManagerSpec::enterPictureInPicture() { + static const auto method = javaClassStatic()->getMethod("enterPictureInPicture"); + method(_javaPart); + } + void JHybridVideoViewViewManagerSpec::exitPictureInPicture() { + static const auto method = javaClassStatic()->getMethod("exitPictureInPicture"); + method(_javaPart); + } + bool JHybridVideoViewViewManagerSpec::canEnterPictureInPicture() { + static const auto method = javaClassStatic()->getMethod("canEnterPictureInPicture"); + auto __result = method(_javaPart); + return static_cast(__result); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.hpp b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.hpp new file mode 100644 index 00000000..220330c9 --- /dev/null +++ b/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.hpp @@ -0,0 +1,93 @@ +/// +/// HybridVideoViewViewManagerSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include "HybridVideoViewViewManagerSpec.hpp" + + + + +namespace margelo::nitro::video { + + using namespace facebook; + + class JHybridVideoViewViewManagerSpec: public jni::HybridClass, + public virtual HybridVideoViewViewManagerSpec { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/HybridVideoViewViewManagerSpec;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + + protected: + // C++ constructor (called from Java via `initHybrid()`) + explicit JHybridVideoViewViewManagerSpec(jni::alias_ref jThis) : + HybridObject(HybridVideoViewViewManagerSpec::TAG), + HybridBase(jThis), + _javaPart(jni::make_global(jThis)) {} + + public: + ~JHybridVideoViewViewManagerSpec() override { + // Hermes GC can destroy JS objects on a non-JNI Thread. + jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); + } + + public: + size_t getExternalMemorySize() noexcept override; + void dispose() noexcept override; + + public: + inline const jni::global_ref& getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + std::optional> getPlayer() override; + void setPlayer(const std::optional>& player) override; + bool getControls() override; + void setControls(bool controls) override; + bool getPictureInPicture() override; + void setPictureInPicture(bool pictureInPicture) override; + bool getAutoEnterPictureInPicture() override; + void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) override; + ResizeMode getResizeMode() override; + void setResizeMode(ResizeMode resizeMode) override; + bool getKeepScreenAwake() override; + void setKeepScreenAwake(bool keepScreenAwake) override; + SurfaceType getSurfaceType() override; + void setSurfaceType(SurfaceType surfaceType) override; + std::optional> getOnPictureInPictureChange() override; + void setOnPictureInPictureChange(const std::optional>& onPictureInPictureChange) override; + std::optional> getOnFullscreenChange() override; + void setOnFullscreenChange(const std::optional>& onFullscreenChange) override; + std::optional> getWillEnterFullscreen() override; + void setWillEnterFullscreen(const std::optional>& willEnterFullscreen) override; + std::optional> getWillExitFullscreen() override; + void setWillExitFullscreen(const std::optional>& willExitFullscreen) override; + std::optional> getWillEnterPictureInPicture() override; + void setWillEnterPictureInPicture(const std::optional>& willEnterPictureInPicture) override; + std::optional> getWillExitPictureInPicture() override; + void setWillExitPictureInPicture(const std::optional>& willExitPictureInPicture) override; + + public: + // Methods + void enterFullscreen() override; + void exitFullscreen() override; + void enterPictureInPicture() override; + void exitPictureInPicture() override; + bool canEnterPictureInPicture() override; + + private: + friend HybridBase; + using HybridBase::HybridBase; + jni::global_ref _javaPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JIgnoreSilentSwitchMode.hpp b/nitrogen/generated/android/c++/JIgnoreSilentSwitchMode.hpp new file mode 100644 index 00000000..72afa7fb --- /dev/null +++ b/nitrogen/generated/android/c++/JIgnoreSilentSwitchMode.hpp @@ -0,0 +1,62 @@ +/// +/// JIgnoreSilentSwitchMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "IgnoreSilentSwitchMode.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "IgnoreSilentSwitchMode" and the the Kotlin enum "IgnoreSilentSwitchMode". + */ + struct JIgnoreSilentSwitchMode final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/IgnoreSilentSwitchMode;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum IgnoreSilentSwitchMode. + */ + [[maybe_unused]] + [[nodiscard]] + IgnoreSilentSwitchMode 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(IgnoreSilentSwitchMode value) { + static const auto clazz = javaClassStatic(); + static const auto fieldAUTO = clazz->getStaticField("AUTO"); + static const auto fieldIGNORE = clazz->getStaticField("IGNORE"); + static const auto fieldOBEY = clazz->getStaticField("OBEY"); + + switch (value) { + case IgnoreSilentSwitchMode::AUTO: + return clazz->getStaticFieldValue(fieldAUTO); + case IgnoreSilentSwitchMode::IGNORE: + return clazz->getStaticFieldValue(fieldIGNORE); + case IgnoreSilentSwitchMode::OBEY: + return clazz->getStaticFieldValue(fieldOBEY); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JLivePlaybackParams.hpp b/nitrogen/generated/android/c++/JLivePlaybackParams.hpp new file mode 100644 index 00000000..07db9d60 --- /dev/null +++ b/nitrogen/generated/android/c++/JLivePlaybackParams.hpp @@ -0,0 +1,69 @@ +/// +/// JLivePlaybackParams.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "LivePlaybackParams.hpp" + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "LivePlaybackParams" and the the Kotlin data class "LivePlaybackParams". + */ + struct JLivePlaybackParams final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/LivePlaybackParams;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct LivePlaybackParams by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + LivePlaybackParams toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldMinPlaybackSpeed = clazz->getField("minPlaybackSpeed"); + jni::local_ref minPlaybackSpeed = this->getFieldValue(fieldMinPlaybackSpeed); + static const auto fieldMaxPlaybackSpeed = clazz->getField("maxPlaybackSpeed"); + jni::local_ref maxPlaybackSpeed = this->getFieldValue(fieldMaxPlaybackSpeed); + static const auto fieldMaxOffsetMs = clazz->getField("maxOffsetMs"); + jni::local_ref maxOffsetMs = this->getFieldValue(fieldMaxOffsetMs); + static const auto fieldMinOffsetMs = clazz->getField("minOffsetMs"); + jni::local_ref minOffsetMs = this->getFieldValue(fieldMinOffsetMs); + static const auto fieldTargetOffsetMs = clazz->getField("targetOffsetMs"); + jni::local_ref targetOffsetMs = this->getFieldValue(fieldTargetOffsetMs); + return LivePlaybackParams( + minPlaybackSpeed != nullptr ? std::make_optional(minPlaybackSpeed->value()) : std::nullopt, + maxPlaybackSpeed != nullptr ? std::make_optional(maxPlaybackSpeed->value()) : std::nullopt, + maxOffsetMs != nullptr ? std::make_optional(maxOffsetMs->value()) : std::nullopt, + minOffsetMs != nullptr ? std::make_optional(minOffsetMs->value()) : std::nullopt, + targetOffsetMs != nullptr ? std::make_optional(targetOffsetMs->value()) : 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 LivePlaybackParams& value) { + return newInstance( + value.minPlaybackSpeed.has_value() ? jni::JDouble::valueOf(value.minPlaybackSpeed.value()) : nullptr, + value.maxPlaybackSpeed.has_value() ? jni::JDouble::valueOf(value.maxPlaybackSpeed.value()) : nullptr, + value.maxOffsetMs.has_value() ? jni::JDouble::valueOf(value.maxOffsetMs.value()) : nullptr, + value.minOffsetMs.has_value() ? jni::JDouble::valueOf(value.minOffsetMs.value()) : nullptr, + value.targetOffsetMs.has_value() ? jni::JDouble::valueOf(value.targetOffsetMs.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JMixAudioMode.hpp b/nitrogen/generated/android/c++/JMixAudioMode.hpp new file mode 100644 index 00000000..ef2aac4a --- /dev/null +++ b/nitrogen/generated/android/c++/JMixAudioMode.hpp @@ -0,0 +1,65 @@ +/// +/// JMixAudioMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "MixAudioMode.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "MixAudioMode" and the the Kotlin enum "MixAudioMode". + */ + struct JMixAudioMode final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/MixAudioMode;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum MixAudioMode. + */ + [[maybe_unused]] + [[nodiscard]] + MixAudioMode 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(MixAudioMode value) { + static const auto clazz = javaClassStatic(); + static const auto fieldMIXWITHOTHERS = clazz->getStaticField("MIXWITHOTHERS"); + static const auto fieldDONOTMIX = clazz->getStaticField("DONOTMIX"); + static const auto fieldDUCKOTHERS = clazz->getStaticField("DUCKOTHERS"); + static const auto fieldAUTO = clazz->getStaticField("AUTO"); + + switch (value) { + case MixAudioMode::MIXWITHOTHERS: + return clazz->getStaticFieldValue(fieldMIXWITHOTHERS); + case MixAudioMode::DONOTMIX: + return clazz->getStaticFieldValue(fieldDONOTMIX); + case MixAudioMode::DUCKOTHERS: + return clazz->getStaticFieldValue(fieldDUCKOTHERS); + case MixAudioMode::AUTO: + return clazz->getStaticFieldValue(fieldAUTO); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JNativeDrmParams.hpp b/nitrogen/generated/android/c++/JNativeDrmParams.hpp new file mode 100644 index 00000000..e227cd24 --- /dev/null +++ b/nitrogen/generated/android/c++/JNativeDrmParams.hpp @@ -0,0 +1,108 @@ +/// +/// JNativeDrmParams.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "NativeDrmParams.hpp" + +#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp" +#include "JOnGetLicensePayload.hpp" +#include "OnGetLicensePayload.hpp" +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "NativeDrmParams" and the the Kotlin data class "NativeDrmParams". + */ + struct JNativeDrmParams final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/NativeDrmParams;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct NativeDrmParams by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + NativeDrmParams toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldType = clazz->getField("type"); + jni::local_ref type = this->getFieldValue(fieldType); + static const auto fieldLicenseUrl = clazz->getField("licenseUrl"); + jni::local_ref licenseUrl = this->getFieldValue(fieldLicenseUrl); + static const auto fieldCertificateUrl = clazz->getField("certificateUrl"); + jni::local_ref certificateUrl = this->getFieldValue(fieldCertificateUrl); + static const auto fieldContentId = clazz->getField("contentId"); + jni::local_ref contentId = this->getFieldValue(fieldContentId); + static const auto fieldLicenseHeaders = clazz->getField>("licenseHeaders"); + jni::local_ref> licenseHeaders = this->getFieldValue(fieldLicenseHeaders); + static const auto fieldMultiSession = clazz->getField("multiSession"); + jni::local_ref multiSession = this->getFieldValue(fieldMultiSession); + static const auto fieldGetLicense = clazz->getField("getLicense"); + jni::local_ref getLicense = this->getFieldValue(fieldGetLicense); + return NativeDrmParams( + type != nullptr ? std::make_optional(type->toStdString()) : std::nullopt, + licenseUrl != nullptr ? std::make_optional(licenseUrl->toStdString()) : std::nullopt, + certificateUrl != nullptr ? std::make_optional(certificateUrl->toStdString()) : std::nullopt, + contentId != nullptr ? std::make_optional(contentId->toStdString()) : std::nullopt, + licenseHeaders != nullptr ? std::make_optional([&]() { + std::unordered_map __map; + __map.reserve(licenseHeaders->size()); + for (const auto& __entry : *licenseHeaders) { + __map.emplace(__entry.first->toStdString(), __entry.second->toStdString()); + } + return __map; + }()) : std::nullopt, + multiSession != nullptr ? std::make_optional(static_cast(multiSession->value())) : std::nullopt, + getLicense != nullptr ? std::make_optional([&]() -> std::function>>>(const OnGetLicensePayload& /* payload */)> { + if (getLicense->isInstanceOf(JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::javaClassStatic())) [[likely]] { + auto downcast = jni::static_ref_cast(getLicense); + return downcast->cthis()->getFunction(); + } else { + auto getLicenseRef = jni::make_global(getLicense); + return [getLicenseRef](OnGetLicensePayload payload) -> std::shared_ptr>>> { + return getLicenseRef->invoke(payload); + }; + } + }()) : 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 NativeDrmParams& value) { + return newInstance( + value.type.has_value() ? jni::make_jstring(value.type.value()) : nullptr, + value.licenseUrl.has_value() ? jni::make_jstring(value.licenseUrl.value()) : nullptr, + value.certificateUrl.has_value() ? jni::make_jstring(value.certificateUrl.value()) : nullptr, + value.contentId.has_value() ? jni::make_jstring(value.contentId.value()) : nullptr, + value.licenseHeaders.has_value() ? [&]() -> jni::local_ref> { + auto __map = jni::JHashMap::create(value.licenseHeaders.value().size()); + for (const auto& __entry : value.licenseHeaders.value()) { + __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second)); + } + return __map; + }() : nullptr, + value.multiSession.has_value() ? jni::JBoolean::valueOf(value.multiSession.value()) : nullptr, + value.getLicense.has_value() ? JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::fromCpp(value.getLicense.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JNativeExternalSubtitle.hpp b/nitrogen/generated/android/c++/JNativeExternalSubtitle.hpp new file mode 100644 index 00000000..6ecc6bdd --- /dev/null +++ b/nitrogen/generated/android/c++/JNativeExternalSubtitle.hpp @@ -0,0 +1,67 @@ +/// +/// JNativeExternalSubtitle.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "NativeExternalSubtitle.hpp" + +#include "JSubtitleType.hpp" +#include "SubtitleType.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "NativeExternalSubtitle" and the the Kotlin data class "NativeExternalSubtitle". + */ + struct JNativeExternalSubtitle final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/NativeExternalSubtitle;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct NativeExternalSubtitle by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + NativeExternalSubtitle toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldUri = clazz->getField("uri"); + jni::local_ref uri = this->getFieldValue(fieldUri); + static const auto fieldLabel = clazz->getField("label"); + jni::local_ref label = this->getFieldValue(fieldLabel); + static const auto fieldType = clazz->getField("type"); + jni::local_ref type = this->getFieldValue(fieldType); + static const auto fieldLanguage = clazz->getField("language"); + jni::local_ref language = this->getFieldValue(fieldLanguage); + return NativeExternalSubtitle( + uri->toStdString(), + label->toStdString(), + type->toCpp(), + language->toStdString() + ); + } + + 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 NativeExternalSubtitle& value) { + return newInstance( + jni::make_jstring(value.uri), + jni::make_jstring(value.label), + JSubtitleType::fromCpp(value.type), + jni::make_jstring(value.language) + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JNativeVideoConfig.hpp b/nitrogen/generated/android/c++/JNativeVideoConfig.hpp new file mode 100644 index 00000000..6bae0ffe --- /dev/null +++ b/nitrogen/generated/android/c++/JNativeVideoConfig.hpp @@ -0,0 +1,130 @@ +/// +/// JNativeVideoConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "NativeVideoConfig.hpp" + +#include "BufferConfig.hpp" +#include "CustomVideoMetadata.hpp" +#include "JBufferConfig.hpp" +#include "JCustomVideoMetadata.hpp" +#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp" +#include "JLivePlaybackParams.hpp" +#include "JNativeDrmParams.hpp" +#include "JNativeExternalSubtitle.hpp" +#include "JOnGetLicensePayload.hpp" +#include "JResolution.hpp" +#include "JSubtitleType.hpp" +#include "LivePlaybackParams.hpp" +#include "NativeDrmParams.hpp" +#include "NativeExternalSubtitle.hpp" +#include "OnGetLicensePayload.hpp" +#include "Resolution.hpp" +#include "SubtitleType.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "NativeVideoConfig" and the the Kotlin data class "NativeVideoConfig". + */ + struct JNativeVideoConfig final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/NativeVideoConfig;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct NativeVideoConfig by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + NativeVideoConfig toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldUri = clazz->getField("uri"); + jni::local_ref uri = this->getFieldValue(fieldUri); + static const auto fieldExternalSubtitles = clazz->getField>("externalSubtitles"); + jni::local_ref> externalSubtitles = this->getFieldValue(fieldExternalSubtitles); + static const auto fieldDrm = clazz->getField("drm"); + jni::local_ref drm = this->getFieldValue(fieldDrm); + static const auto fieldHeaders = clazz->getField>("headers"); + jni::local_ref> headers = this->getFieldValue(fieldHeaders); + static const auto fieldBufferConfig = clazz->getField("bufferConfig"); + jni::local_ref bufferConfig = this->getFieldValue(fieldBufferConfig); + static const auto fieldMetadata = clazz->getField("metadata"); + jni::local_ref metadata = this->getFieldValue(fieldMetadata); + static const auto fieldInitializeOnCreation = clazz->getField("initializeOnCreation"); + jni::local_ref initializeOnCreation = this->getFieldValue(fieldInitializeOnCreation); + return NativeVideoConfig( + uri->toStdString(), + externalSubtitles != nullptr ? std::make_optional([&]() { + size_t __size = externalSubtitles->size(); + std::vector __vector; + __vector.reserve(__size); + for (size_t __i = 0; __i < __size; __i++) { + auto __element = externalSubtitles->getElement(__i); + __vector.push_back(__element->toCpp()); + } + return __vector; + }()) : std::nullopt, + drm != nullptr ? std::make_optional(drm->toCpp()) : std::nullopt, + headers != nullptr ? std::make_optional([&]() { + std::unordered_map __map; + __map.reserve(headers->size()); + for (const auto& __entry : *headers) { + __map.emplace(__entry.first->toStdString(), __entry.second->toStdString()); + } + return __map; + }()) : std::nullopt, + bufferConfig != nullptr ? std::make_optional(bufferConfig->toCpp()) : std::nullopt, + metadata != nullptr ? std::make_optional(metadata->toCpp()) : std::nullopt, + initializeOnCreation != nullptr ? std::make_optional(static_cast(initializeOnCreation->value())) : 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 NativeVideoConfig& value) { + return newInstance( + jni::make_jstring(value.uri), + value.externalSubtitles.has_value() ? [&]() { + size_t __size = value.externalSubtitles.value().size(); + jni::local_ref> __array = jni::JArrayClass::newArray(__size); + for (size_t __i = 0; __i < __size; __i++) { + const auto& __element = value.externalSubtitles.value()[__i]; + __array->setElement(__i, *JNativeExternalSubtitle::fromCpp(__element)); + } + return __array; + }() : nullptr, + value.drm.has_value() ? JNativeDrmParams::fromCpp(value.drm.value()) : nullptr, + value.headers.has_value() ? [&]() -> jni::local_ref> { + auto __map = jni::JHashMap::create(value.headers.value().size()); + for (const auto& __entry : value.headers.value()) { + __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second)); + } + return __map; + }() : nullptr, + value.bufferConfig.has_value() ? JBufferConfig::fromCpp(value.bufferConfig.value()) : nullptr, + value.metadata.has_value() ? JCustomVideoMetadata::fromCpp(value.metadata.value()) : nullptr, + value.initializeOnCreation.has_value() ? jni::JBoolean::valueOf(value.initializeOnCreation.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JOnGetLicensePayload.hpp b/nitrogen/generated/android/c++/JOnGetLicensePayload.hpp new file mode 100644 index 00000000..feb0c859 --- /dev/null +++ b/nitrogen/generated/android/c++/JOnGetLicensePayload.hpp @@ -0,0 +1,65 @@ +/// +/// JOnGetLicensePayload.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "OnGetLicensePayload.hpp" + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "OnGetLicensePayload" and the the Kotlin data class "OnGetLicensePayload". + */ + struct JOnGetLicensePayload final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/OnGetLicensePayload;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct OnGetLicensePayload by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + OnGetLicensePayload toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldContentId = clazz->getField("contentId"); + jni::local_ref contentId = this->getFieldValue(fieldContentId); + static const auto fieldLicenseUrl = clazz->getField("licenseUrl"); + jni::local_ref licenseUrl = this->getFieldValue(fieldLicenseUrl); + static const auto fieldKeyUrl = clazz->getField("keyUrl"); + jni::local_ref keyUrl = this->getFieldValue(fieldKeyUrl); + static const auto fieldSpc = clazz->getField("spc"); + jni::local_ref spc = this->getFieldValue(fieldSpc); + return OnGetLicensePayload( + contentId->toStdString(), + licenseUrl->toStdString(), + keyUrl->toStdString(), + spc->toStdString() + ); + } + + 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 OnGetLicensePayload& value) { + return newInstance( + jni::make_jstring(value.contentId), + jni::make_jstring(value.licenseUrl), + jni::make_jstring(value.keyUrl), + jni::make_jstring(value.spc) + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JResizeMode.hpp b/nitrogen/generated/android/c++/JResizeMode.hpp new file mode 100644 index 00000000..18139b92 --- /dev/null +++ b/nitrogen/generated/android/c++/JResizeMode.hpp @@ -0,0 +1,65 @@ +/// +/// JResizeMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "ResizeMode.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "ResizeMode" and the the Kotlin enum "ResizeMode". + */ + struct JResizeMode final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/ResizeMode;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum ResizeMode. + */ + [[maybe_unused]] + [[nodiscard]] + ResizeMode 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(ResizeMode value) { + static const auto clazz = javaClassStatic(); + static const auto fieldCONTAIN = clazz->getStaticField("CONTAIN"); + static const auto fieldCOVER = clazz->getStaticField("COVER"); + static const auto fieldSTRETCH = clazz->getStaticField("STRETCH"); + static const auto fieldNONE = clazz->getStaticField("NONE"); + + switch (value) { + case ResizeMode::CONTAIN: + return clazz->getStaticFieldValue(fieldCONTAIN); + case ResizeMode::COVER: + return clazz->getStaticFieldValue(fieldCOVER); + case ResizeMode::STRETCH: + return clazz->getStaticFieldValue(fieldSTRETCH); + case ResizeMode::NONE: + return clazz->getStaticFieldValue(fieldNONE); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JResolution.hpp b/nitrogen/generated/android/c++/JResolution.hpp new file mode 100644 index 00000000..fe3b5b8b --- /dev/null +++ b/nitrogen/generated/android/c++/JResolution.hpp @@ -0,0 +1,57 @@ +/// +/// JResolution.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "Resolution.hpp" + + + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "Resolution" and the the Kotlin data class "Resolution". + */ + struct JResolution final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/Resolution;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct Resolution by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + Resolution toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldWidth = clazz->getField("width"); + double width = this->getFieldValue(fieldWidth); + static const auto fieldHeight = clazz->getField("height"); + double height = this->getFieldValue(fieldHeight); + return Resolution( + width, + height + ); + } + + 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 Resolution& value) { + return newInstance( + value.width, + value.height + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JSourceType.hpp b/nitrogen/generated/android/c++/JSourceType.hpp new file mode 100644 index 00000000..d79ea1f6 --- /dev/null +++ b/nitrogen/generated/android/c++/JSourceType.hpp @@ -0,0 +1,59 @@ +/// +/// JSourceType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "SourceType.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "SourceType" and the the Kotlin enum "SourceType". + */ + struct JSourceType final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/SourceType;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum SourceType. + */ + [[maybe_unused]] + [[nodiscard]] + SourceType 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(SourceType value) { + static const auto clazz = javaClassStatic(); + static const auto fieldLOCAL = clazz->getStaticField("LOCAL"); + static const auto fieldNETWORK = clazz->getStaticField("NETWORK"); + + switch (value) { + case SourceType::LOCAL: + return clazz->getStaticFieldValue(fieldLOCAL); + case SourceType::NETWORK: + return clazz->getStaticFieldValue(fieldNETWORK); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JSubtitleType.hpp b/nitrogen/generated/android/c++/JSubtitleType.hpp new file mode 100644 index 00000000..ed345295 --- /dev/null +++ b/nitrogen/generated/android/c++/JSubtitleType.hpp @@ -0,0 +1,68 @@ +/// +/// JSubtitleType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "SubtitleType.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "SubtitleType" and the the Kotlin enum "SubtitleType". + */ + struct JSubtitleType final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/SubtitleType;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum SubtitleType. + */ + [[maybe_unused]] + [[nodiscard]] + SubtitleType 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(SubtitleType value) { + static const auto clazz = javaClassStatic(); + static const auto fieldAUTO = clazz->getStaticField("AUTO"); + static const auto fieldVTT = clazz->getStaticField("VTT"); + static const auto fieldSRT = clazz->getStaticField("SRT"); + static const auto fieldSSA = clazz->getStaticField("SSA"); + static const auto fieldASS = clazz->getStaticField("ASS"); + + switch (value) { + case SubtitleType::AUTO: + return clazz->getStaticFieldValue(fieldAUTO); + case SubtitleType::VTT: + return clazz->getStaticFieldValue(fieldVTT); + case SubtitleType::SRT: + return clazz->getStaticFieldValue(fieldSRT); + case SubtitleType::SSA: + return clazz->getStaticFieldValue(fieldSSA); + case SubtitleType::ASS: + return clazz->getStaticFieldValue(fieldASS); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JSurfaceType.hpp b/nitrogen/generated/android/c++/JSurfaceType.hpp new file mode 100644 index 00000000..635bfd22 --- /dev/null +++ b/nitrogen/generated/android/c++/JSurfaceType.hpp @@ -0,0 +1,59 @@ +/// +/// JSurfaceType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "SurfaceType.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "SurfaceType" and the the Kotlin enum "SurfaceType". + */ + struct JSurfaceType final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/SurfaceType;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum SurfaceType. + */ + [[maybe_unused]] + [[nodiscard]] + SurfaceType 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(SurfaceType value) { + static const auto clazz = javaClassStatic(); + static const auto fieldSURFACE = clazz->getStaticField("SURFACE"); + static const auto fieldTEXTURE = clazz->getStaticField("TEXTURE"); + + switch (value) { + case SurfaceType::SURFACE: + return clazz->getStaticFieldValue(fieldSURFACE); + case SurfaceType::TEXTURE: + return clazz->getStaticFieldValue(fieldTEXTURE); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JTextTrack.hpp b/nitrogen/generated/android/c++/JTextTrack.hpp new file mode 100644 index 00000000..a6e6e177 --- /dev/null +++ b/nitrogen/generated/android/c++/JTextTrack.hpp @@ -0,0 +1,66 @@ +/// +/// JTextTrack.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "TextTrack.hpp" + +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "TextTrack" and the the Kotlin data class "TextTrack". + */ + struct JTextTrack final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/TextTrack;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct TextTrack by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + TextTrack toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldId = clazz->getField("id"); + jni::local_ref id = this->getFieldValue(fieldId); + static const auto fieldLabel = clazz->getField("label"); + jni::local_ref label = this->getFieldValue(fieldLabel); + static const auto fieldLanguage = clazz->getField("language"); + jni::local_ref language = this->getFieldValue(fieldLanguage); + static const auto fieldSelected = clazz->getField("selected"); + jboolean selected = this->getFieldValue(fieldSelected); + return TextTrack( + id->toStdString(), + label->toStdString(), + language != nullptr ? std::make_optional(language->toStdString()) : std::nullopt, + static_cast(selected) + ); + } + + 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 TextTrack& value) { + return newInstance( + jni::make_jstring(value.id), + jni::make_jstring(value.label), + value.language.has_value() ? jni::make_jstring(value.language.value()) : nullptr, + value.selected + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JTimedMetadata.hpp b/nitrogen/generated/android/c++/JTimedMetadata.hpp new file mode 100644 index 00000000..a0e4ae48 --- /dev/null +++ b/nitrogen/generated/android/c++/JTimedMetadata.hpp @@ -0,0 +1,73 @@ +/// +/// JTimedMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "TimedMetadata.hpp" + +#include "JTimedMetadataObject.hpp" +#include "TimedMetadataObject.hpp" +#include +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "TimedMetadata" and the the Kotlin data class "TimedMetadata". + */ + struct JTimedMetadata final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/TimedMetadata;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct TimedMetadata by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + TimedMetadata toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldMetadata = clazz->getField>("metadata"); + jni::local_ref> metadata = this->getFieldValue(fieldMetadata); + return TimedMetadata( + [&]() { + size_t __size = metadata->size(); + std::vector __vector; + __vector.reserve(__size); + for (size_t __i = 0; __i < __size; __i++) { + auto __element = metadata->getElement(__i); + __vector.push_back(__element->toCpp()); + } + return __vector; + }() + ); + } + + 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 TimedMetadata& value) { + return newInstance( + [&]() { + size_t __size = value.metadata.size(); + jni::local_ref> __array = jni::JArrayClass::newArray(__size); + for (size_t __i = 0; __i < __size; __i++) { + const auto& __element = value.metadata[__i]; + __array->setElement(__i, *JTimedMetadataObject::fromCpp(__element)); + } + return __array; + }() + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JTimedMetadataObject.hpp b/nitrogen/generated/android/c++/JTimedMetadataObject.hpp new file mode 100644 index 00000000..59e72c03 --- /dev/null +++ b/nitrogen/generated/android/c++/JTimedMetadataObject.hpp @@ -0,0 +1,57 @@ +/// +/// JTimedMetadataObject.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "TimedMetadataObject.hpp" + +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "TimedMetadataObject" and the the Kotlin data class "TimedMetadataObject". + */ + struct JTimedMetadataObject final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/TimedMetadataObject;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct TimedMetadataObject by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + TimedMetadataObject toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldValue = clazz->getField("value"); + jni::local_ref value = this->getFieldValue(fieldValue); + static const auto fieldIdentifier = clazz->getField("identifier"); + jni::local_ref identifier = this->getFieldValue(fieldIdentifier); + return TimedMetadataObject( + value->toStdString(), + identifier->toStdString() + ); + } + + 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 TimedMetadataObject& value) { + return newInstance( + jni::make_jstring(value.value), + jni::make_jstring(value.identifier) + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JVideoInformation.hpp b/nitrogen/generated/android/c++/JVideoInformation.hpp new file mode 100644 index 00000000..370f1169 --- /dev/null +++ b/nitrogen/generated/android/c++/JVideoInformation.hpp @@ -0,0 +1,82 @@ +/// +/// JVideoInformation.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "VideoInformation.hpp" + +#include "JVideoOrientation.hpp" +#include "VideoOrientation.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "VideoInformation" and the the Kotlin data class "VideoInformation". + */ + struct JVideoInformation final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/VideoInformation;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct VideoInformation by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + VideoInformation toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldBitrate = clazz->getField("bitrate"); + double bitrate = this->getFieldValue(fieldBitrate); + static const auto fieldWidth = clazz->getField("width"); + double width = this->getFieldValue(fieldWidth); + static const auto fieldHeight = clazz->getField("height"); + double height = this->getFieldValue(fieldHeight); + static const auto fieldDuration = clazz->getField("duration"); + int64_t duration = this->getFieldValue(fieldDuration); + static const auto fieldFileSize = clazz->getField("fileSize"); + int64_t fileSize = this->getFieldValue(fieldFileSize); + static const auto fieldIsHDR = clazz->getField("isHDR"); + jboolean isHDR = this->getFieldValue(fieldIsHDR); + static const auto fieldIsLive = clazz->getField("isLive"); + jboolean isLive = this->getFieldValue(fieldIsLive); + static const auto fieldOrientation = clazz->getField("orientation"); + jni::local_ref orientation = this->getFieldValue(fieldOrientation); + return VideoInformation( + bitrate, + width, + height, + duration, + fileSize, + static_cast(isHDR), + static_cast(isLive), + orientation->toCpp() + ); + } + + 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 VideoInformation& value) { + return newInstance( + value.bitrate, + value.width, + value.height, + value.duration, + value.fileSize, + value.isHDR, + value.isLive, + JVideoOrientation::fromCpp(value.orientation) + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JVideoOrientation.hpp b/nitrogen/generated/android/c++/JVideoOrientation.hpp new file mode 100644 index 00000000..118a1470 --- /dev/null +++ b/nitrogen/generated/android/c++/JVideoOrientation.hpp @@ -0,0 +1,74 @@ +/// +/// JVideoOrientation.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "VideoOrientation.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "VideoOrientation" and the the Kotlin enum "VideoOrientation". + */ + struct JVideoOrientation final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/VideoOrientation;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum VideoOrientation. + */ + [[maybe_unused]] + [[nodiscard]] + VideoOrientation 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(VideoOrientation value) { + static const auto clazz = javaClassStatic(); + static const auto fieldPORTRAIT = clazz->getStaticField("PORTRAIT"); + static const auto fieldLANDSCAPE = clazz->getStaticField("LANDSCAPE"); + static const auto fieldPORTRAIT_UPSIDE_DOWN = clazz->getStaticField("PORTRAIT_UPSIDE_DOWN"); + static const auto fieldLANDSCAPE_LEFT = clazz->getStaticField("LANDSCAPE_LEFT"); + static const auto fieldLANDSCAPE_RIGHT = clazz->getStaticField("LANDSCAPE_RIGHT"); + static const auto fieldSQUARE = clazz->getStaticField("SQUARE"); + static const auto fieldUNKNOWN = clazz->getStaticField("UNKNOWN"); + + switch (value) { + case VideoOrientation::PORTRAIT: + return clazz->getStaticFieldValue(fieldPORTRAIT); + case VideoOrientation::LANDSCAPE: + return clazz->getStaticFieldValue(fieldLANDSCAPE); + case VideoOrientation::PORTRAIT_UPSIDE_DOWN: + return clazz->getStaticFieldValue(fieldPORTRAIT_UPSIDE_DOWN); + case VideoOrientation::LANDSCAPE_LEFT: + return clazz->getStaticFieldValue(fieldLANDSCAPE_LEFT); + case VideoOrientation::LANDSCAPE_RIGHT: + return clazz->getStaticFieldValue(fieldLANDSCAPE_RIGHT); + case VideoOrientation::SQUARE: + return clazz->getStaticFieldValue(fieldSQUARE); + case VideoOrientation::UNKNOWN: + return clazz->getStaticFieldValue(fieldUNKNOWN); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JVideoPlayerStatus.hpp b/nitrogen/generated/android/c++/JVideoPlayerStatus.hpp new file mode 100644 index 00000000..efbd9cf0 --- /dev/null +++ b/nitrogen/generated/android/c++/JVideoPlayerStatus.hpp @@ -0,0 +1,65 @@ +/// +/// JVideoPlayerStatus.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "VideoPlayerStatus.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "VideoPlayerStatus" and the the Kotlin enum "VideoPlayerStatus". + */ + struct JVideoPlayerStatus final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/VideoPlayerStatus;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum VideoPlayerStatus. + */ + [[maybe_unused]] + [[nodiscard]] + VideoPlayerStatus 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(VideoPlayerStatus value) { + static const auto clazz = javaClassStatic(); + static const auto fieldIDLE = clazz->getStaticField("IDLE"); + static const auto fieldLOADING = clazz->getStaticField("LOADING"); + static const auto fieldREADYTOPLAY = clazz->getStaticField("READYTOPLAY"); + static const auto fieldERROR = clazz->getStaticField("ERROR"); + + switch (value) { + case VideoPlayerStatus::IDLE: + return clazz->getStaticFieldValue(fieldIDLE); + case VideoPlayerStatus::LOADING: + return clazz->getStaticFieldValue(fieldLOADING); + case VideoPlayerStatus::READYTOPLAY: + return clazz->getStaticFieldValue(fieldREADYTOPLAY); + case VideoPlayerStatus::ERROR: + return clazz->getStaticFieldValue(fieldERROR); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JonLoadData.hpp b/nitrogen/generated/android/c++/JonLoadData.hpp new file mode 100644 index 00000000..123cbfbc --- /dev/null +++ b/nitrogen/generated/android/c++/JonLoadData.hpp @@ -0,0 +1,70 @@ +/// +/// JonLoadData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "onLoadData.hpp" + +#include "JVideoOrientation.hpp" +#include "VideoOrientation.hpp" + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "onLoadData" and the the Kotlin data class "onLoadData". + */ + struct JonLoadData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/onLoadData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct onLoadData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + onLoadData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldCurrentTime = clazz->getField("currentTime"); + double currentTime = this->getFieldValue(fieldCurrentTime); + static const auto fieldDuration = clazz->getField("duration"); + double duration = this->getFieldValue(fieldDuration); + static const auto fieldHeight = clazz->getField("height"); + double height = this->getFieldValue(fieldHeight); + static const auto fieldWidth = clazz->getField("width"); + double width = this->getFieldValue(fieldWidth); + static const auto fieldOrientation = clazz->getField("orientation"); + jni::local_ref orientation = this->getFieldValue(fieldOrientation); + return onLoadData( + currentTime, + duration, + height, + width, + orientation->toCpp() + ); + } + + 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 onLoadData& value) { + return newInstance( + value.currentTime, + value.duration, + value.height, + value.width, + JVideoOrientation::fromCpp(value.orientation) + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JonLoadStartData.hpp b/nitrogen/generated/android/c++/JonLoadStartData.hpp new file mode 100644 index 00000000..ee1297fe --- /dev/null +++ b/nitrogen/generated/android/c++/JonLoadStartData.hpp @@ -0,0 +1,61 @@ +/// +/// JonLoadStartData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "onLoadStartData.hpp" + +#include "HybridVideoPlayerSourceSpec.hpp" +#include "JHybridVideoPlayerSourceSpec.hpp" +#include "JSourceType.hpp" +#include "SourceType.hpp" +#include + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "onLoadStartData" and the the Kotlin data class "onLoadStartData". + */ + struct JonLoadStartData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/onLoadStartData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct onLoadStartData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + onLoadStartData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldSourceType = clazz->getField("sourceType"); + jni::local_ref sourceType = this->getFieldValue(fieldSourceType); + static const auto fieldSource = clazz->getField("source"); + jni::local_ref source = this->getFieldValue(fieldSource); + return onLoadStartData( + sourceType->toCpp(), + source->cthis()->shared_cast() + ); + } + + 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 onLoadStartData& value) { + return newInstance( + JSourceType::fromCpp(value.sourceType), + std::dynamic_pointer_cast(value.source)->getJavaPart() + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JonPlaybackStateChangeData.hpp b/nitrogen/generated/android/c++/JonPlaybackStateChangeData.hpp new file mode 100644 index 00000000..85cd53d6 --- /dev/null +++ b/nitrogen/generated/android/c++/JonPlaybackStateChangeData.hpp @@ -0,0 +1,57 @@ +/// +/// JonPlaybackStateChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "onPlaybackStateChangeData.hpp" + + + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "onPlaybackStateChangeData" and the the Kotlin data class "onPlaybackStateChangeData". + */ + struct JonPlaybackStateChangeData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/onPlaybackStateChangeData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct onPlaybackStateChangeData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + onPlaybackStateChangeData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldIsPlaying = clazz->getField("isPlaying"); + jboolean isPlaying = this->getFieldValue(fieldIsPlaying); + static const auto fieldIsBuffering = clazz->getField("isBuffering"); + jboolean isBuffering = this->getFieldValue(fieldIsBuffering); + return onPlaybackStateChangeData( + static_cast(isPlaying), + static_cast(isBuffering) + ); + } + + 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 onPlaybackStateChangeData& value) { + return newInstance( + value.isPlaying, + value.isBuffering + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JonProgressData.hpp b/nitrogen/generated/android/c++/JonProgressData.hpp new file mode 100644 index 00000000..e470d9c7 --- /dev/null +++ b/nitrogen/generated/android/c++/JonProgressData.hpp @@ -0,0 +1,57 @@ +/// +/// JonProgressData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "onProgressData.hpp" + + + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "onProgressData" and the the Kotlin data class "onProgressData". + */ + struct JonProgressData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/onProgressData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct onProgressData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + onProgressData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldCurrentTime = clazz->getField("currentTime"); + double currentTime = this->getFieldValue(fieldCurrentTime); + static const auto fieldBufferDuration = clazz->getField("bufferDuration"); + double bufferDuration = this->getFieldValue(fieldBufferDuration); + return onProgressData( + currentTime, + bufferDuration + ); + } + + 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 onProgressData& value) { + return newInstance( + value.currentTime, + value.bufferDuration + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/c++/JonVolumeChangeData.hpp b/nitrogen/generated/android/c++/JonVolumeChangeData.hpp new file mode 100644 index 00000000..81247dff --- /dev/null +++ b/nitrogen/generated/android/c++/JonVolumeChangeData.hpp @@ -0,0 +1,57 @@ +/// +/// JonVolumeChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "onVolumeChangeData.hpp" + + + +namespace margelo::nitro::video { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "onVolumeChangeData" and the the Kotlin data class "onVolumeChangeData". + */ + struct JonVolumeChangeData final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/video/onVolumeChangeData;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct onVolumeChangeData by copying all values to C++. + */ + [[maybe_unused]] + [[nodiscard]] + onVolumeChangeData toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldVolume = clazz->getField("volume"); + double volume = this->getFieldValue(fieldVolume); + static const auto fieldMuted = clazz->getField("muted"); + jboolean muted = this->getFieldValue(fieldMuted); + return onVolumeChangeData( + volume, + static_cast(muted) + ); + } + + 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 onVolumeChangeData& value) { + return newInstance( + value.volume, + value.muted + ); + } + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BandwidthData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BandwidthData.kt new file mode 100644 index 00000000..62618bd0 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BandwidthData.kt @@ -0,0 +1,35 @@ +/// +/// BandwidthData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "BandwidthData". + */ +@DoNotStrip +@Keep +data class BandwidthData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val bitrate: Double, + @DoNotStrip + @Keep + val width: Double?, + @DoNotStrip + @Keep + val height: Double? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BufferConfig.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BufferConfig.kt new file mode 100644 index 00000000..9eae4d44 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BufferConfig.kt @@ -0,0 +1,59 @@ +/// +/// BufferConfig.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "BufferConfig". + */ +@DoNotStrip +@Keep +data class BufferConfig + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val livePlayback: LivePlaybackParams?, + @DoNotStrip + @Keep + val minBufferMs: Double?, + @DoNotStrip + @Keep + val maxBufferMs: Double?, + @DoNotStrip + @Keep + val bufferForPlaybackMs: Double?, + @DoNotStrip + @Keep + val bufferForPlaybackAfterRebufferMs: Double?, + @DoNotStrip + @Keep + val backBufferDurationMs: Double?, + @DoNotStrip + @Keep + val preferredForwardBufferDurationMs: Double?, + @DoNotStrip + @Keep + val preferredPeakBitRate: Double?, + @DoNotStrip + @Keep + val preferredMaximumResolution: Resolution?, + @DoNotStrip + @Keep + val preferredPeakBitRateForExpensiveNetworks: Double?, + @DoNotStrip + @Keep + val preferredMaximumResolutionForExpensiveNetworks: Resolution? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/CustomVideoMetadata.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/CustomVideoMetadata.kt new file mode 100644 index 00000000..0073c60c --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/CustomVideoMetadata.kt @@ -0,0 +1,41 @@ +/// +/// CustomVideoMetadata.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "CustomVideoMetadata". + */ +@DoNotStrip +@Keep +data class CustomVideoMetadata + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val title: String?, + @DoNotStrip + @Keep + val subtitle: String?, + @DoNotStrip + @Keep + val description: String?, + @DoNotStrip + @Keep + val artist: String?, + @DoNotStrip + @Keep + val imageUri: String? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt new file mode 100644 index 00000000..e0cf724b --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt @@ -0,0 +1,81 @@ +/// +/// Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(payload: struct) => std::shared_ptr>>>`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload: (OnGetLicensePayload) -> Promise> { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(payload: OnGetLicensePayload): Promise> +} + +/** + * Represents the JavaScript callback `(payload: struct) => std::shared_ptr>>>`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(payload: OnGetLicensePayload): Promise> + = invoke_cxx(payload) + + @FastNative + private external fun invoke_cxx(payload: OnGetLicensePayload): Promise> +} + +/** + * Represents the JavaScript callback `(payload: struct) => std::shared_ptr>>>`. + * This is implemented in Java/Kotlin, via a `(OnGetLicensePayload) -> Promise>`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_java(private val function: (OnGetLicensePayload) -> Promise>): Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload { + @DoNotStrip + @Keep + override fun invoke(payload: OnGetLicensePayload): Promise> { + return this.function(payload) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void.kt new file mode 100644 index 00000000..24177f63 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void.kt @@ -0,0 +1,81 @@ +/// +/// Func_void.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `() => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void: () -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(): Unit +} + +/** + * Represents the JavaScript callback `() => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_cxx: Func_void { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(): Unit + = invoke_cxx() + + @FastNative + private external fun invoke_cxx(): Unit +} + +/** + * Represents the JavaScript callback `() => void`. + * This is implemented in Java/Kotlin, via a `() -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_java(private val function: () -> Unit): Func_void { + @DoNotStrip + @Keep + override fun invoke(): Unit { + return this.function() + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_BandwidthData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_BandwidthData.kt new file mode 100644 index 00000000..546d3218 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_BandwidthData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_BandwidthData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_BandwidthData: (BandwidthData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: BandwidthData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_BandwidthData_cxx: Func_void_BandwidthData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: BandwidthData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: BandwidthData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(BandwidthData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_BandwidthData_java(private val function: (BandwidthData) -> Unit): Func_void_BandwidthData { + @DoNotStrip + @Keep + override fun invoke(data: BandwidthData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_TimedMetadata.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_TimedMetadata.kt new file mode 100644 index 00000000..ba18b023 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_TimedMetadata.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_TimedMetadata.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(metadata: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_TimedMetadata: (TimedMetadata) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(metadata: TimedMetadata): Unit +} + +/** + * Represents the JavaScript callback `(metadata: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_TimedMetadata_cxx: Func_void_TimedMetadata { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(metadata: TimedMetadata): Unit + = invoke_cxx(metadata) + + @FastNative + private external fun invoke_cxx(metadata: TimedMetadata): Unit +} + +/** + * Represents the JavaScript callback `(metadata: struct) => void`. + * This is implemented in Java/Kotlin, via a `(TimedMetadata) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_TimedMetadata_java(private val function: (TimedMetadata) -> Unit): Func_void_TimedMetadata { + @DoNotStrip + @Keep + override fun invoke(metadata: TimedMetadata): Unit { + return this.function(metadata) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_VideoPlayerStatus.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_VideoPlayerStatus.kt new file mode 100644 index 00000000..b6a3640e --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_VideoPlayerStatus.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_VideoPlayerStatus.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(status: enum) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_VideoPlayerStatus: (VideoPlayerStatus) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(status: VideoPlayerStatus): Unit +} + +/** + * Represents the JavaScript callback `(status: enum) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_VideoPlayerStatus_cxx: Func_void_VideoPlayerStatus { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(status: VideoPlayerStatus): Unit + = invoke_cxx(status) + + @FastNative + private external fun invoke_cxx(status: VideoPlayerStatus): Unit +} + +/** + * Represents the JavaScript callback `(status: enum) => void`. + * This is implemented in Java/Kotlin, via a `(VideoPlayerStatus) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_VideoPlayerStatus_java(private val function: (VideoPlayerStatus) -> Unit): Func_void_VideoPlayerStatus { + @DoNotStrip + @Keep + override fun invoke(status: VideoPlayerStatus): Unit { + return this.function(status) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_bool.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_bool.kt new file mode 100644 index 00000000..941330d2 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_bool.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_bool.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_bool: (Boolean) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(isInPictureInPicture: Boolean): Unit +} + +/** + * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_bool_cxx: Func_void_bool { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(isInPictureInPicture: Boolean): Unit + = invoke_cxx(isInPictureInPicture) + + @FastNative + private external fun invoke_cxx(isInPictureInPicture: Boolean): Unit +} + +/** + * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`. + * This is implemented in Java/Kotlin, via a `(Boolean) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_bool_java(private val function: (Boolean) -> Unit): Func_void_bool { + @DoNotStrip + @Keep + override fun invoke(isInPictureInPicture: Boolean): Unit { + return this.function(isInPictureInPicture) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_double.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_double.kt new file mode 100644 index 00000000..743f10bc --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_double.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_double.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(rate: number) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_double: (Double) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(rate: Double): Unit +} + +/** + * Represents the JavaScript callback `(rate: number) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_double_cxx: Func_void_double { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(rate: Double): Unit + = invoke_cxx(rate) + + @FastNative + private external fun invoke_cxx(rate: Double): Unit +} + +/** + * Represents the JavaScript callback `(rate: number) => void`. + * This is implemented in Java/Kotlin, via a `(Double) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_double_java(private val function: (Double) -> Unit): Func_void_double { + @DoNotStrip + @Keep + override fun invoke(rate: Double): Unit { + return this.function(rate) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadData.kt new file mode 100644 index 00000000..d3e74dc3 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_onLoadData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_onLoadData: (onLoadData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: onLoadData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_onLoadData_cxx: Func_void_onLoadData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: onLoadData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: onLoadData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(onLoadData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_onLoadData_java(private val function: (onLoadData) -> Unit): Func_void_onLoadData { + @DoNotStrip + @Keep + override fun invoke(data: onLoadData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadStartData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadStartData.kt new file mode 100644 index 00000000..81b37930 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadStartData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_onLoadStartData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_onLoadStartData: (onLoadStartData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: onLoadStartData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_onLoadStartData_cxx: Func_void_onLoadStartData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: onLoadStartData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: onLoadStartData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(onLoadStartData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_onLoadStartData_java(private val function: (onLoadStartData) -> Unit): Func_void_onLoadStartData { + @DoNotStrip + @Keep + override fun invoke(data: onLoadStartData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onPlaybackStateChangeData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onPlaybackStateChangeData.kt new file mode 100644 index 00000000..50a948d2 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onPlaybackStateChangeData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_onPlaybackStateChangeData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_onPlaybackStateChangeData: (onPlaybackStateChangeData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: onPlaybackStateChangeData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_onPlaybackStateChangeData_cxx: Func_void_onPlaybackStateChangeData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: onPlaybackStateChangeData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: onPlaybackStateChangeData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(onPlaybackStateChangeData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_onPlaybackStateChangeData_java(private val function: (onPlaybackStateChangeData) -> Unit): Func_void_onPlaybackStateChangeData { + @DoNotStrip + @Keep + override fun invoke(data: onPlaybackStateChangeData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onProgressData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onProgressData.kt new file mode 100644 index 00000000..8248c5ad --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onProgressData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_onProgressData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_onProgressData: (onProgressData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: onProgressData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_onProgressData_cxx: Func_void_onProgressData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: onProgressData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: onProgressData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(onProgressData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_onProgressData_java(private val function: (onProgressData) -> Unit): Func_void_onProgressData { + @DoNotStrip + @Keep + override fun invoke(data: onProgressData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onVolumeChangeData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onVolumeChangeData.kt new file mode 100644 index 00000000..62342d99 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onVolumeChangeData.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_onVolumeChangeData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_onVolumeChangeData: (onVolumeChangeData) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(data: onVolumeChangeData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_onVolumeChangeData_cxx: Func_void_onVolumeChangeData { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(data: onVolumeChangeData): Unit + = invoke_cxx(data) + + @FastNative + private external fun invoke_cxx(data: onVolumeChangeData): Unit +} + +/** + * Represents the JavaScript callback `(data: struct) => void`. + * This is implemented in Java/Kotlin, via a `(onVolumeChangeData) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_onVolumeChangeData_java(private val function: (onVolumeChangeData) -> Unit): Func_void_onVolumeChangeData { + @DoNotStrip + @Keep + override fun invoke(data: onVolumeChangeData): Unit { + return this.function(data) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__optional_TextTrack_.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__optional_TextTrack_.kt new file mode 100644 index 00000000..02c0851e --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__optional_TextTrack_.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_std__optional_TextTrack_.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(track: optional) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_std__optional_TextTrack_: (TextTrack?) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(track: TextTrack?): Unit +} + +/** + * Represents the JavaScript callback `(track: optional) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_std__optional_TextTrack__cxx: Func_void_std__optional_TextTrack_ { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(track: TextTrack?): Unit + = invoke_cxx(track) + + @FastNative + private external fun invoke_cxx(track: TextTrack?): Unit +} + +/** + * Represents the JavaScript callback `(track: optional) => void`. + * This is implemented in Java/Kotlin, via a `(TextTrack?) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_std__optional_TextTrack__java(private val function: (TextTrack?) -> Unit): Func_void_std__optional_TextTrack_ { + @DoNotStrip + @Keep + override fun invoke(track: TextTrack?): Unit { + return this.function(track) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__vector_std__string_.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__vector_std__string_.kt new file mode 100644 index 00000000..560c4ddc --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__vector_std__string_.kt @@ -0,0 +1,81 @@ +/// +/// Func_void_std__vector_std__string_.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* +import dalvik.annotation.optimization.FastNative + + +/** + * Represents the JavaScript callback `(texts: array) => void`. + * This can be either implemented in C++ (in which case it might be a callback coming from JS), + * or in Kotlin/Java (in which case it is a native callback). + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType") +fun interface Func_void_std__vector_std__string_: (Array) -> Unit { + /** + * Call the given JS callback. + * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. + */ + @DoNotStrip + @Keep + override fun invoke(texts: Array): Unit +} + +/** + * Represents the JavaScript callback `(texts: array) => void`. + * This is implemented in C++, via a `std::function<...>`. + * The callback might be coming from JS. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", +) +class Func_void_std__vector_std__string__cxx: Func_void_std__vector_std__string_ { + @DoNotStrip + @Keep + private val mHybridData: HybridData + + @DoNotStrip + @Keep + private constructor(hybridData: HybridData) { + mHybridData = hybridData + } + + @DoNotStrip + @Keep + override fun invoke(texts: Array): Unit + = invoke_cxx(texts) + + @FastNative + private external fun invoke_cxx(texts: Array): Unit +} + +/** + * Represents the JavaScript callback `(texts: array) => void`. + * This is implemented in Java/Kotlin, via a `(Array) -> Unit`. + * The callback is always coming from native. + */ +@DoNotStrip +@Keep +@Suppress("ClassName", "RedundantUnitReturnType", "unused") +class Func_void_std__vector_std__string__java(private val function: (Array) -> Unit): Func_void_std__vector_std__string_ { + @DoNotStrip + @Keep + override fun invoke(texts: Array): Unit { + return this.function(texts) + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec.kt new file mode 100644 index 00000000..6ba28f19 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec.kt @@ -0,0 +1,314 @@ +/// +/// HybridVideoPlayerEventEmitterSpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoPlayerEventEmitter HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoPlayerEventEmitter. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoPlayerEventEmitterSpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + abstract var onAudioBecomingNoisy: () -> Unit + + private var onAudioBecomingNoisy_cxx: Func_void + @Keep + @DoNotStrip + get() { + return Func_void_java(onAudioBecomingNoisy) + } + @Keep + @DoNotStrip + set(value) { + onAudioBecomingNoisy = value + } + + abstract var onAudioFocusChange: (hasAudioFocus: Boolean) -> Unit + + private var onAudioFocusChange_cxx: Func_void_bool + @Keep + @DoNotStrip + get() { + return Func_void_bool_java(onAudioFocusChange) + } + @Keep + @DoNotStrip + set(value) { + onAudioFocusChange = value + } + + abstract var onBandwidthUpdate: (data: BandwidthData) -> Unit + + private var onBandwidthUpdate_cxx: Func_void_BandwidthData + @Keep + @DoNotStrip + get() { + return Func_void_BandwidthData_java(onBandwidthUpdate) + } + @Keep + @DoNotStrip + set(value) { + onBandwidthUpdate = value + } + + abstract var onBuffer: (buffering: Boolean) -> Unit + + private var onBuffer_cxx: Func_void_bool + @Keep + @DoNotStrip + get() { + return Func_void_bool_java(onBuffer) + } + @Keep + @DoNotStrip + set(value) { + onBuffer = value + } + + abstract var onControlsVisibleChange: (visible: Boolean) -> Unit + + private var onControlsVisibleChange_cxx: Func_void_bool + @Keep + @DoNotStrip + get() { + return Func_void_bool_java(onControlsVisibleChange) + } + @Keep + @DoNotStrip + set(value) { + onControlsVisibleChange = value + } + + abstract var onEnd: () -> Unit + + private var onEnd_cxx: Func_void + @Keep + @DoNotStrip + get() { + return Func_void_java(onEnd) + } + @Keep + @DoNotStrip + set(value) { + onEnd = value + } + + abstract var onExternalPlaybackChange: (externalPlaybackActive: Boolean) -> Unit + + private var onExternalPlaybackChange_cxx: Func_void_bool + @Keep + @DoNotStrip + get() { + return Func_void_bool_java(onExternalPlaybackChange) + } + @Keep + @DoNotStrip + set(value) { + onExternalPlaybackChange = value + } + + abstract var onLoad: (data: onLoadData) -> Unit + + private var onLoad_cxx: Func_void_onLoadData + @Keep + @DoNotStrip + get() { + return Func_void_onLoadData_java(onLoad) + } + @Keep + @DoNotStrip + set(value) { + onLoad = value + } + + abstract var onLoadStart: (data: onLoadStartData) -> Unit + + private var onLoadStart_cxx: Func_void_onLoadStartData + @Keep + @DoNotStrip + get() { + return Func_void_onLoadStartData_java(onLoadStart) + } + @Keep + @DoNotStrip + set(value) { + onLoadStart = value + } + + abstract var onPlaybackStateChange: (data: onPlaybackStateChangeData) -> Unit + + private var onPlaybackStateChange_cxx: Func_void_onPlaybackStateChangeData + @Keep + @DoNotStrip + get() { + return Func_void_onPlaybackStateChangeData_java(onPlaybackStateChange) + } + @Keep + @DoNotStrip + set(value) { + onPlaybackStateChange = value + } + + abstract var onPlaybackRateChange: (rate: Double) -> Unit + + private var onPlaybackRateChange_cxx: Func_void_double + @Keep + @DoNotStrip + get() { + return Func_void_double_java(onPlaybackRateChange) + } + @Keep + @DoNotStrip + set(value) { + onPlaybackRateChange = value + } + + abstract var onProgress: (data: onProgressData) -> Unit + + private var onProgress_cxx: Func_void_onProgressData + @Keep + @DoNotStrip + get() { + return Func_void_onProgressData_java(onProgress) + } + @Keep + @DoNotStrip + set(value) { + onProgress = value + } + + abstract var onReadyToDisplay: () -> Unit + + private var onReadyToDisplay_cxx: Func_void + @Keep + @DoNotStrip + get() { + return Func_void_java(onReadyToDisplay) + } + @Keep + @DoNotStrip + set(value) { + onReadyToDisplay = value + } + + abstract var onSeek: (seekTime: Double) -> Unit + + private var onSeek_cxx: Func_void_double + @Keep + @DoNotStrip + get() { + return Func_void_double_java(onSeek) + } + @Keep + @DoNotStrip + set(value) { + onSeek = value + } + + abstract var onTimedMetadata: (metadata: TimedMetadata) -> Unit + + private var onTimedMetadata_cxx: Func_void_TimedMetadata + @Keep + @DoNotStrip + get() { + return Func_void_TimedMetadata_java(onTimedMetadata) + } + @Keep + @DoNotStrip + set(value) { + onTimedMetadata = value + } + + abstract var onTextTrackDataChanged: (texts: Array) -> Unit + + private var onTextTrackDataChanged_cxx: Func_void_std__vector_std__string_ + @Keep + @DoNotStrip + get() { + return Func_void_std__vector_std__string__java(onTextTrackDataChanged) + } + @Keep + @DoNotStrip + set(value) { + onTextTrackDataChanged = value + } + + abstract var onTrackChange: (track: TextTrack?) -> Unit + + private var onTrackChange_cxx: Func_void_std__optional_TextTrack_ + @Keep + @DoNotStrip + get() { + return Func_void_std__optional_TextTrack__java(onTrackChange) + } + @Keep + @DoNotStrip + set(value) { + onTrackChange = value + } + + abstract var onVolumeChange: (data: onVolumeChangeData) -> Unit + + private var onVolumeChange_cxx: Func_void_onVolumeChangeData + @Keep + @DoNotStrip + get() { + return Func_void_onVolumeChangeData_java(onVolumeChange) + } + @Keep + @DoNotStrip + set(value) { + onVolumeChange = value + } + + abstract var onStatusChange: (status: VideoPlayerStatus) -> Unit + + private var onStatusChange_cxx: Func_void_VideoPlayerStatus + @Keep + @DoNotStrip + get() { + return Func_void_VideoPlayerStatus_java(onStatusChange) + } + @Keep + @DoNotStrip + set(value) { + onStatusChange = value + } + + // Methods + + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoPlayerEventEmitterSpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerFactorySpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerFactorySpec.kt new file mode 100644 index 00000000..d31cc52a --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerFactorySpec.kt @@ -0,0 +1,52 @@ +/// +/// HybridVideoPlayerFactorySpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoPlayerFactory HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoPlayerFactory. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoPlayerFactorySpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + + + // Methods + @DoNotStrip + @Keep + abstract fun createPlayer(source: HybridVideoPlayerSourceSpec): HybridVideoPlayerSpec + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoPlayerFactorySpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec.kt new file mode 100644 index 00000000..0eff8294 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec.kt @@ -0,0 +1,56 @@ +/// +/// HybridVideoPlayerSourceFactorySpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoPlayerSourceFactory HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoPlayerSourceFactory. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoPlayerSourceFactorySpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + + + // Methods + @DoNotStrip + @Keep + abstract fun fromUri(uri: String): HybridVideoPlayerSourceSpec + + @DoNotStrip + @Keep + abstract fun fromVideoConfig(config: NativeVideoConfig): HybridVideoPlayerSourceSpec + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoPlayerSourceFactorySpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceSpec.kt new file mode 100644 index 00000000..b7fe7344 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceSpec.kt @@ -0,0 +1,58 @@ +/// +/// HybridVideoPlayerSourceSpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoPlayerSource HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoPlayerSource. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoPlayerSourceSpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + @get:DoNotStrip + @get:Keep + abstract val uri: String + + @get:DoNotStrip + @get:Keep + abstract val config: NativeVideoConfig + + // Methods + @DoNotStrip + @Keep + abstract fun getAssetInformationAsync(): Promise + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoPlayerSourceSpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSpec.kt new file mode 100644 index 00000000..e5565b58 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSpec.kt @@ -0,0 +1,166 @@ +/// +/// HybridVideoPlayerSpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoPlayer HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoPlayer. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoPlayerSpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + @get:DoNotStrip + @get:Keep + abstract val source: HybridVideoPlayerSourceSpec + + @get:DoNotStrip + @get:Keep + abstract val eventEmitter: HybridVideoPlayerEventEmitterSpec + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var showNotificationControls: Boolean + + @get:DoNotStrip + @get:Keep + abstract val status: VideoPlayerStatus + + @get:DoNotStrip + @get:Keep + abstract val duration: Double + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var volume: Double + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var currentTime: Double + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var muted: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var loop: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var rate: Double + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var mixAudioMode: MixAudioMode + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var ignoreSilentSwitchMode: IgnoreSilentSwitchMode + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var playInBackground: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var playWhenInactive: Boolean + + @get:DoNotStrip + @get:Keep + abstract val isPlaying: Boolean + + @get:DoNotStrip + @get:Keep + abstract val selectedTrack: TextTrack? + + // Methods + @DoNotStrip + @Keep + abstract fun replaceSourceAsync(source: HybridVideoPlayerSourceSpec?): Promise + + @DoNotStrip + @Keep + abstract fun getAvailableTextTracks(): Array + + @DoNotStrip + @Keep + abstract fun selectTextTrack(textTrack: TextTrack?): Unit + + @DoNotStrip + @Keep + abstract fun initialize(): Promise + + @DoNotStrip + @Keep + abstract fun preload(): Promise + + @DoNotStrip + @Keep + abstract fun play(): Unit + + @DoNotStrip + @Keep + abstract fun pause(): Unit + + @DoNotStrip + @Keep + abstract fun seekBy(time: Double): Unit + + @DoNotStrip + @Keep + abstract fun seekTo(time: Double): Unit + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoPlayerSpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec.kt new file mode 100644 index 00000000..62e75023 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec.kt @@ -0,0 +1,52 @@ +/// +/// HybridVideoViewViewManagerFactorySpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoViewViewManagerFactory HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoViewViewManagerFactory. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoViewViewManagerFactorySpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + + + // Methods + @DoNotStrip + @Keep + abstract fun createViewManager(nitroId: Double): HybridVideoViewViewManagerSpec + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoViewViewManagerFactorySpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerSpec.kt new file mode 100644 index 00000000..9d7234f6 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerSpec.kt @@ -0,0 +1,192 @@ +/// +/// HybridVideoViewViewManagerSpec.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * A Kotlin class representing the VideoViewViewManager HybridObject. + * Implement this abstract class to create Kotlin-based instances of VideoViewViewManager. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", + "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" +) +abstract class HybridVideoViewViewManagerSpec: HybridObject() { + @DoNotStrip + private var mHybridData: HybridData = initHybrid() + + init { + super.updateNative(mHybridData) + } + + override fun updateNative(hybridData: HybridData) { + mHybridData = hybridData + super.updateNative(hybridData) + } + + // Properties + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var player: HybridVideoPlayerSpec? + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var controls: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var pictureInPicture: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var autoEnterPictureInPicture: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var resizeMode: ResizeMode + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var keepScreenAwake: Boolean + + @get:DoNotStrip + @get:Keep + @set:DoNotStrip + @set:Keep + abstract var surfaceType: SurfaceType + + abstract var onPictureInPictureChange: ((isInPictureInPicture: Boolean) -> Unit)? + + private var onPictureInPictureChange_cxx: Func_void_bool? + @Keep + @DoNotStrip + get() { + return onPictureInPictureChange?.let { Func_void_bool_java(it) } + } + @Keep + @DoNotStrip + set(value) { + onPictureInPictureChange = value?.let { it } + } + + abstract var onFullscreenChange: ((fullscreen: Boolean) -> Unit)? + + private var onFullscreenChange_cxx: Func_void_bool? + @Keep + @DoNotStrip + get() { + return onFullscreenChange?.let { Func_void_bool_java(it) } + } + @Keep + @DoNotStrip + set(value) { + onFullscreenChange = value?.let { it } + } + + abstract var willEnterFullscreen: (() -> Unit)? + + private var willEnterFullscreen_cxx: Func_void? + @Keep + @DoNotStrip + get() { + return willEnterFullscreen?.let { Func_void_java(it) } + } + @Keep + @DoNotStrip + set(value) { + willEnterFullscreen = value?.let { it } + } + + abstract var willExitFullscreen: (() -> Unit)? + + private var willExitFullscreen_cxx: Func_void? + @Keep + @DoNotStrip + get() { + return willExitFullscreen?.let { Func_void_java(it) } + } + @Keep + @DoNotStrip + set(value) { + willExitFullscreen = value?.let { it } + } + + abstract var willEnterPictureInPicture: (() -> Unit)? + + private var willEnterPictureInPicture_cxx: Func_void? + @Keep + @DoNotStrip + get() { + return willEnterPictureInPicture?.let { Func_void_java(it) } + } + @Keep + @DoNotStrip + set(value) { + willEnterPictureInPicture = value?.let { it } + } + + abstract var willExitPictureInPicture: (() -> Unit)? + + private var willExitPictureInPicture_cxx: Func_void? + @Keep + @DoNotStrip + get() { + return willExitPictureInPicture?.let { Func_void_java(it) } + } + @Keep + @DoNotStrip + set(value) { + willExitPictureInPicture = value?.let { it } + } + + // Methods + @DoNotStrip + @Keep + abstract fun enterFullscreen(): Unit + + @DoNotStrip + @Keep + abstract fun exitFullscreen(): Unit + + @DoNotStrip + @Keep + abstract fun enterPictureInPicture(): Unit + + @DoNotStrip + @Keep + abstract fun exitPictureInPicture(): Unit + + @DoNotStrip + @Keep + abstract fun canEnterPictureInPicture(): Boolean + + private external fun initHybrid(): HybridData + + companion object { + private const val TAG = "HybridVideoViewViewManagerSpec" + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/IgnoreSilentSwitchMode.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/IgnoreSilentSwitchMode.kt new file mode 100644 index 00000000..e5c70f94 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/IgnoreSilentSwitchMode.kt @@ -0,0 +1,22 @@ +/// +/// IgnoreSilentSwitchMode.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "IgnoreSilentSwitchMode". + */ +@DoNotStrip +@Keep +enum class IgnoreSilentSwitchMode(@DoNotStrip @Keep val value: Int) { + AUTO(0), + IGNORE(1), + OBEY(2); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/LivePlaybackParams.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/LivePlaybackParams.kt new file mode 100644 index 00000000..7ccc16b1 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/LivePlaybackParams.kt @@ -0,0 +1,41 @@ +/// +/// LivePlaybackParams.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "LivePlaybackParams". + */ +@DoNotStrip +@Keep +data class LivePlaybackParams + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val minPlaybackSpeed: Double?, + @DoNotStrip + @Keep + val maxPlaybackSpeed: Double?, + @DoNotStrip + @Keep + val maxOffsetMs: Double?, + @DoNotStrip + @Keep + val minOffsetMs: Double?, + @DoNotStrip + @Keep + val targetOffsetMs: Double? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/MixAudioMode.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/MixAudioMode.kt new file mode 100644 index 00000000..74c5cd99 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/MixAudioMode.kt @@ -0,0 +1,23 @@ +/// +/// MixAudioMode.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "MixAudioMode". + */ +@DoNotStrip +@Keep +enum class MixAudioMode(@DoNotStrip @Keep val value: Int) { + MIXWITHOTHERS(0), + DONOTMIX(1), + DUCKOTHERS(2), + AUTO(3); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeDrmParams.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeDrmParams.kt new file mode 100644 index 00000000..6c885813 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeDrmParams.kt @@ -0,0 +1,51 @@ +/// +/// NativeDrmParams.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "NativeDrmParams". + */ +@DoNotStrip +@Keep +data class NativeDrmParams + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val type: String?, + @DoNotStrip + @Keep + val licenseUrl: String?, + @DoNotStrip + @Keep + val certificateUrl: String?, + @DoNotStrip + @Keep + val contentId: String?, + @DoNotStrip + @Keep + val licenseHeaders: Map?, + @DoNotStrip + @Keep + val multiSession: Boolean?, + @DoNotStrip + @Keep + val getLicense: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload? + ) { + /** + * Initialize a new instance of `NativeDrmParams` from Kotlin. + */ + constructor(type: String?, licenseUrl: String?, certificateUrl: String?, contentId: String?, licenseHeaders: Map?, multiSession: Boolean?, getLicense: ((payload: OnGetLicensePayload) -> Promise>)?) + : this(type, licenseUrl, certificateUrl, contentId, licenseHeaders, multiSession, getLicense?.let { Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_java(it) }) +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeExternalSubtitle.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeExternalSubtitle.kt new file mode 100644 index 00000000..75ff9133 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeExternalSubtitle.kt @@ -0,0 +1,38 @@ +/// +/// NativeExternalSubtitle.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "NativeExternalSubtitle". + */ +@DoNotStrip +@Keep +data class NativeExternalSubtitle + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val uri: String, + @DoNotStrip + @Keep + val label: String, + @DoNotStrip + @Keep + val type: SubtitleType, + @DoNotStrip + @Keep + val language: String + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeVideoConfig.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeVideoConfig.kt new file mode 100644 index 00000000..c3452ca0 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeVideoConfig.kt @@ -0,0 +1,47 @@ +/// +/// NativeVideoConfig.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "NativeVideoConfig". + */ +@DoNotStrip +@Keep +data class NativeVideoConfig + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val uri: String, + @DoNotStrip + @Keep + val externalSubtitles: Array?, + @DoNotStrip + @Keep + val drm: NativeDrmParams?, + @DoNotStrip + @Keep + val headers: Map?, + @DoNotStrip + @Keep + val bufferConfig: BufferConfig?, + @DoNotStrip + @Keep + val metadata: CustomVideoMetadata?, + @DoNotStrip + @Keep + val initializeOnCreation: Boolean? + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/OnGetLicensePayload.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/OnGetLicensePayload.kt new file mode 100644 index 00000000..a22512d7 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/OnGetLicensePayload.kt @@ -0,0 +1,38 @@ +/// +/// OnGetLicensePayload.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "OnGetLicensePayload". + */ +@DoNotStrip +@Keep +data class OnGetLicensePayload + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val contentId: String, + @DoNotStrip + @Keep + val licenseUrl: String, + @DoNotStrip + @Keep + val keyUrl: String, + @DoNotStrip + @Keep + val spc: String + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ReactNativeVideoOnLoad.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ReactNativeVideoOnLoad.kt new file mode 100644 index 00000000..86000ecb --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ReactNativeVideoOnLoad.kt @@ -0,0 +1,35 @@ +/// +/// ReactNativeVideoOnLoad.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import android.util.Log + +internal class ReactNativeVideoOnLoad { + companion object { + private const val TAG = "ReactNativeVideoOnLoad" + private var didLoad = false + /** + * Initializes the native part of "ReactNativeVideo". + * This method is idempotent and can be called more than once. + */ + @JvmStatic + fun initializeNative() { + if (didLoad) return + try { + Log.i(TAG, "Loading ReactNativeVideo C++ library...") + System.loadLibrary("ReactNativeVideo") + Log.i(TAG, "Successfully loaded ReactNativeVideo C++ library!") + didLoad = true + } catch (e: Error) { + Log.e(TAG, "Failed to load ReactNativeVideo C++ library! Is it properly installed and linked? " + + "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e) + throw e + } + } + } +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ResizeMode.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ResizeMode.kt new file mode 100644 index 00000000..1d712918 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ResizeMode.kt @@ -0,0 +1,23 @@ +/// +/// ResizeMode.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "ResizeMode". + */ +@DoNotStrip +@Keep +enum class ResizeMode(@DoNotStrip @Keep val value: Int) { + CONTAIN(0), + COVER(1), + STRETCH(2), + NONE(3); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Resolution.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Resolution.kt new file mode 100644 index 00000000..ea5404e9 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Resolution.kt @@ -0,0 +1,32 @@ +/// +/// Resolution.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "Resolution". + */ +@DoNotStrip +@Keep +data class Resolution + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val width: Double, + @DoNotStrip + @Keep + val height: Double + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SourceType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SourceType.kt new file mode 100644 index 00000000..eea4e3f3 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SourceType.kt @@ -0,0 +1,21 @@ +/// +/// SourceType.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "SourceType". + */ +@DoNotStrip +@Keep +enum class SourceType(@DoNotStrip @Keep val value: Int) { + LOCAL(0), + NETWORK(1); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SubtitleType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SubtitleType.kt new file mode 100644 index 00000000..486ddcda --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SubtitleType.kt @@ -0,0 +1,24 @@ +/// +/// SubtitleType.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "SubtitleType". + */ +@DoNotStrip +@Keep +enum class SubtitleType(@DoNotStrip @Keep val value: Int) { + AUTO(0), + VTT(1), + SRT(2), + SSA(3), + ASS(4); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt new file mode 100644 index 00000000..cb6bb0ee --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt @@ -0,0 +1,21 @@ +/// +/// SurfaceType.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "SurfaceType". + */ +@DoNotStrip +@Keep +enum class SurfaceType(@DoNotStrip @Keep val value: Int) { + SURFACE(0), + TEXTURE(1); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TextTrack.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TextTrack.kt new file mode 100644 index 00000000..8cc27887 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TextTrack.kt @@ -0,0 +1,38 @@ +/// +/// TextTrack.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "TextTrack". + */ +@DoNotStrip +@Keep +data class TextTrack + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val id: String, + @DoNotStrip + @Keep + val label: String, + @DoNotStrip + @Keep + val language: String?, + @DoNotStrip + @Keep + val selected: Boolean + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadata.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadata.kt new file mode 100644 index 00000000..278f4bd0 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadata.kt @@ -0,0 +1,29 @@ +/// +/// TimedMetadata.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "TimedMetadata". + */ +@DoNotStrip +@Keep +data class TimedMetadata + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val metadata: Array + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadataObject.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadataObject.kt new file mode 100644 index 00000000..a4a4a295 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadataObject.kt @@ -0,0 +1,32 @@ +/// +/// TimedMetadataObject.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "TimedMetadataObject". + */ +@DoNotStrip +@Keep +data class TimedMetadataObject + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val value: String, + @DoNotStrip + @Keep + val identifier: String + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoInformation.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoInformation.kt new file mode 100644 index 00000000..d9b90dd1 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoInformation.kt @@ -0,0 +1,50 @@ +/// +/// VideoInformation.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "VideoInformation". + */ +@DoNotStrip +@Keep +data class VideoInformation + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val bitrate: Double, + @DoNotStrip + @Keep + val width: Double, + @DoNotStrip + @Keep + val height: Double, + @DoNotStrip + @Keep + val duration: Long, + @DoNotStrip + @Keep + val fileSize: Long, + @DoNotStrip + @Keep + val isHDR: Boolean, + @DoNotStrip + @Keep + val isLive: Boolean, + @DoNotStrip + @Keep + val orientation: VideoOrientation + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoOrientation.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoOrientation.kt new file mode 100644 index 00000000..aff941ba --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoOrientation.kt @@ -0,0 +1,26 @@ +/// +/// VideoOrientation.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "VideoOrientation". + */ +@DoNotStrip +@Keep +enum class VideoOrientation(@DoNotStrip @Keep val value: Int) { + PORTRAIT(0), + LANDSCAPE(1), + PORTRAIT_UPSIDE_DOWN(2), + LANDSCAPE_LEFT(3), + LANDSCAPE_RIGHT(4), + SQUARE(5), + UNKNOWN(6); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoPlayerStatus.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoPlayerStatus.kt new file mode 100644 index 00000000..a7a767ba --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoPlayerStatus.kt @@ -0,0 +1,23 @@ +/// +/// VideoPlayerStatus.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "VideoPlayerStatus". + */ +@DoNotStrip +@Keep +enum class VideoPlayerStatus(@DoNotStrip @Keep val value: Int) { + IDLE(0), + LOADING(1), + READYTOPLAY(2), + ERROR(3); +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadData.kt new file mode 100644 index 00000000..c993160e --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadData.kt @@ -0,0 +1,41 @@ +/// +/// onLoadData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "onLoadData". + */ +@DoNotStrip +@Keep +data class onLoadData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val currentTime: Double, + @DoNotStrip + @Keep + val duration: Double, + @DoNotStrip + @Keep + val height: Double, + @DoNotStrip + @Keep + val width: Double, + @DoNotStrip + @Keep + val orientation: VideoOrientation + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadStartData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadStartData.kt new file mode 100644 index 00000000..b181951c --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadStartData.kt @@ -0,0 +1,32 @@ +/// +/// onLoadStartData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "onLoadStartData". + */ +@DoNotStrip +@Keep +data class onLoadStartData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val sourceType: SourceType, + @DoNotStrip + @Keep + val source: HybridVideoPlayerSourceSpec + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onPlaybackStateChangeData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onPlaybackStateChangeData.kt new file mode 100644 index 00000000..c8b6eb87 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onPlaybackStateChangeData.kt @@ -0,0 +1,32 @@ +/// +/// onPlaybackStateChangeData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "onPlaybackStateChangeData". + */ +@DoNotStrip +@Keep +data class onPlaybackStateChangeData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val isPlaying: Boolean, + @DoNotStrip + @Keep + val isBuffering: Boolean + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onProgressData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onProgressData.kt new file mode 100644 index 00000000..446136c7 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onProgressData.kt @@ -0,0 +1,32 @@ +/// +/// onProgressData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "onProgressData". + */ +@DoNotStrip +@Keep +data class onProgressData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val currentTime: Double, + @DoNotStrip + @Keep + val bufferDuration: Double + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onVolumeChangeData.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onVolumeChangeData.kt new file mode 100644 index 00000000..24d75134 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onVolumeChangeData.kt @@ -0,0 +1,32 @@ +/// +/// onVolumeChangeData.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.video + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + + +/** + * Represents the JavaScript object/struct "onVolumeChangeData". + */ +@DoNotStrip +@Keep +data class onVolumeChangeData + @DoNotStrip + @Keep + constructor( + @DoNotStrip + @Keep + val volume: Double, + @DoNotStrip + @Keep + val muted: Boolean + ) { + /* main constructor */ +} diff --git a/nitrogen/generated/ios/ReactNativeVideo+autolinking.rb b/nitrogen/generated/ios/ReactNativeVideo+autolinking.rb new file mode 100644 index 00000000..42d45d45 --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideo+autolinking.rb @@ -0,0 +1,60 @@ +# +# ReactNativeVideo+autolinking.rb +# This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +# https://github.com/mrousavy/nitro +# Copyright © 2025 Marc Rousavy @ Margelo +# + +# This is a Ruby script that adds all files generated by Nitrogen +# to the given podspec. +# +# To use it, add this to your .podspec: +# ```ruby +# Pod::Spec.new do |spec| +# # ... +# +# # Add all files generated by Nitrogen +# load 'nitrogen/generated/ios/ReactNativeVideo+autolinking.rb' +# add_nitrogen_files(spec) +# end +# ``` + +def add_nitrogen_files(spec) + Pod::UI.puts "[NitroModules] 🔥 ReactNativeVideo is boosted by nitro!" + + spec.dependency "NitroModules" + + current_source_files = Array(spec.attributes_hash['source_files']) + spec.source_files = current_source_files + [ + # Generated cross-platform specs + "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}", + # Generated bridges for the cross-platform specs + "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}", + ] + + current_public_header_files = Array(spec.attributes_hash['public_header_files']) + spec.public_header_files = current_public_header_files + [ + # Generated specs + "nitrogen/generated/shared/**/*.{h,hpp}", + # Swift to C++ bridging helpers + "nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp" + ] + + current_private_header_files = Array(spec.attributes_hash['private_header_files']) + spec.private_header_files = current_private_header_files + [ + # iOS specific specs + "nitrogen/generated/ios/c++/**/*.{h,hpp}", + # Views are framework-specific and should be private + "nitrogen/generated/shared/**/views/**/*" + ] + + current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {} + spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({ + # Use C++ 20 + "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", + # Enables C++ <-> Swift interop (by default it's only C) + "SWIFT_OBJC_INTEROP_MODE" => "objcxx", + # Enables stricter modular headers + "DEFINES_MODULE" => "YES", + }) +end diff --git a/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.cpp b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.cpp new file mode 100644 index 00000000..aca622f9 --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.cpp @@ -0,0 +1,279 @@ +/// +/// ReactNativeVideo-Swift-Cxx-Bridge.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "ReactNativeVideo-Swift-Cxx-Bridge.hpp" + +// Include C++ implementation defined types +#include "HybridVideoPlayerEventEmitterSpecSwift.hpp" +#include "HybridVideoPlayerFactorySpecSwift.hpp" +#include "HybridVideoPlayerSourceFactorySpecSwift.hpp" +#include "HybridVideoPlayerSourceSpecSwift.hpp" +#include "HybridVideoPlayerSpecSwift.hpp" +#include "HybridVideoViewViewManagerFactorySpecSwift.hpp" +#include "HybridVideoViewViewManagerSpecSwift.hpp" +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video::bridge::swift { + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoPlayerSourceSpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoPlayerEventEmitterSpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::function + Func_void create_Func_void(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)]() mutable -> void { + swiftClosure.call(); + }; + } + + // pragma MARK: std::function + Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_std__exception_ptr::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::exception_ptr& error) mutable -> void { + swiftClosure.call(error); + }; + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoPlayerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoPlayerSpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoPlayerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoPlayerFactorySpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::function + Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_bool::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](bool hasAudioFocus) mutable -> void { + swiftClosure.call(hasAudioFocus); + }; + } + + // pragma MARK: std::function + Func_void_BandwidthData create_Func_void_BandwidthData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_BandwidthData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const BandwidthData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_onLoadData create_Func_void_onLoadData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_onLoadData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const onLoadData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_onLoadStartData create_Func_void_onLoadStartData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_onLoadStartData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const onLoadStartData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_onPlaybackStateChangeData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const onPlaybackStateChangeData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_double::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](double rate) mutable -> void { + swiftClosure.call(rate); + }; + } + + // pragma MARK: std::function + Func_void_onProgressData create_Func_void_onProgressData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_onProgressData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const onProgressData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_TimedMetadata create_Func_void_TimedMetadata(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_TimedMetadata::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const TimedMetadata& metadata) mutable -> void { + swiftClosure.call(metadata); + }; + } + + // pragma MARK: std::function& /* texts */)> + Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_std__vector_std__string_::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::vector& texts) mutable -> void { + swiftClosure.call(texts); + }; + } + + // pragma MARK: std::function& /* track */)> + Func_void_std__optional_TextTrack_ create_Func_void_std__optional_TextTrack_(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_std__optional_TextTrack_::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::optional& track) mutable -> void { + swiftClosure.call(track); + }; + } + + // pragma MARK: std::function + Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_onVolumeChangeData::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const onVolumeChangeData& data) mutable -> void { + swiftClosure.call(data); + }; + } + + // pragma MARK: std::function + Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_VideoPlayerStatus::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](VideoPlayerStatus status) mutable -> void { + swiftClosure.call(static_cast(status)); + }; + } + + // pragma MARK: std::function + Func_void_std__string create_Func_void_std__string(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_std__string::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::string& result) mutable -> void { + swiftClosure.call(result); + }; + } + + // pragma MARK: std::function>>>(const OnGetLicensePayload& /* payload */)> + Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const OnGetLicensePayload& payload) mutable -> std::shared_ptr>>> { + auto __result = swiftClosure.call(payload); + return __result; + }; + } + + // pragma MARK: std::function>& /* result */)> + Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_std__shared_ptr_Promise_std__string__::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr>& result) mutable -> void { + swiftClosure.call(result); + }; + } + + // pragma MARK: std::function + Func_void_VideoInformation create_Func_void_VideoInformation(void* NON_NULL swiftClosureWrapper) noexcept { + auto swiftClosure = ReactNativeVideo::Func_void_VideoInformation::fromUnsafe(swiftClosureWrapper); + return [swiftClosure = std::move(swiftClosure)](const VideoInformation& result) mutable -> void { + swiftClosure.call(result); + }; + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoPlayerSourceFactorySpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoViewViewManagerSpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + + // pragma MARK: std::shared_ptr + std::shared_ptr create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept { + ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer); + return std::make_shared(swiftPart); + } + void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType) noexcept { + std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); + #ifdef NITRO_DEBUG + if (swiftWrapper == nullptr) [[unlikely]] { + throw std::runtime_error("Class \"HybridVideoViewViewManagerFactorySpec\" is not implemented in Swift!"); + } + #endif + ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); + return swiftPart.toUnsafe(); + } + +} // namespace margelo::nitro::video::bridge::swift diff --git a/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp new file mode 100644 index 00000000..531b4de2 --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp @@ -0,0 +1,1053 @@ +/// +/// ReactNativeVideo-Swift-Cxx-Bridge.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +// Forward declarations of C++ defined types +// Forward declaration of `BandwidthData` to properly resolve imports. +namespace margelo::nitro::video { struct BandwidthData; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } +// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; } +// Forward declaration of `HybridVideoPlayerFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerFactorySpec; } +// Forward declaration of `HybridVideoPlayerSourceFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceFactorySpec; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `HybridVideoViewViewManagerFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerFactorySpec; } +// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `SourceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SourceType; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } +// Forward declaration of `TimedMetadataObject` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadataObject; } +// Forward declaration of `TimedMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadata; } +// Forward declaration of `VideoInformation` to properly resolve imports. +namespace margelo::nitro::video { struct VideoInformation; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } +// Forward declaration of `onLoadData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadData; } +// Forward declaration of `onLoadStartData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadStartData; } +// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onPlaybackStateChangeData; } +// Forward declaration of `onProgressData` to properly resolve imports. +namespace margelo::nitro::video { struct onProgressData; } +// Forward declaration of `onVolumeChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onVolumeChangeData; } + +// Forward declarations of Swift defined types +// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; } +// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; } +// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; } +// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; } +// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; } +// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; } +// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; } + +// Include C++ defined types +#include "BandwidthData.hpp" +#include "BufferConfig.hpp" +#include "CustomVideoMetadata.hpp" +#include "HybridVideoPlayerEventEmitterSpec.hpp" +#include "HybridVideoPlayerFactorySpec.hpp" +#include "HybridVideoPlayerSourceFactorySpec.hpp" +#include "HybridVideoPlayerSourceSpec.hpp" +#include "HybridVideoPlayerSpec.hpp" +#include "HybridVideoViewViewManagerFactorySpec.hpp" +#include "HybridVideoViewViewManagerSpec.hpp" +#include "LivePlaybackParams.hpp" +#include "NativeDrmParams.hpp" +#include "NativeExternalSubtitle.hpp" +#include "OnGetLicensePayload.hpp" +#include "Resolution.hpp" +#include "SourceType.hpp" +#include "SubtitleType.hpp" +#include "TextTrack.hpp" +#include "TimedMetadata.hpp" +#include "TimedMetadataObject.hpp" +#include "VideoInformation.hpp" +#include "VideoOrientation.hpp" +#include "VideoPlayerStatus.hpp" +#include "onLoadData.hpp" +#include "onLoadStartData.hpp" +#include "onPlaybackStateChangeData.hpp" +#include "onProgressData.hpp" +#include "onVolumeChangeData.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Contains specialized versions of C++ templated types so they can be accessed from Swift, + * as well as helper functions to interact with those C++ types from Swift. + */ +namespace margelo::nitro::video::bridge::swift { + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoPlayerSourceSpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoPlayerSourceSpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoPlayerSourceSpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: std::shared_ptr> + /** + * Specialized version of `std::shared_ptr>`. + */ + using std__shared_ptr_Promise_void__ = std::shared_ptr>; + inline std::shared_ptr> create_std__shared_ptr_Promise_void__() noexcept { + return Promise::create(); + } + inline PromiseHolder wrap_std__shared_ptr_Promise_void__(std::shared_ptr> promise) noexcept { + return PromiseHolder(std::move(promise)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_Wrapper final { + public: + explicit Func_void_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call() const noexcept { + _function->operator()(); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void create_Func_void(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_Wrapper wrap_Func_void(Func_void value) noexcept { + return Func_void_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_std__exception_ptr = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_std__exception_ptr_Wrapper final { + public: + explicit Func_void_std__exception_ptr_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(std::exception_ptr error) const noexcept { + _function->operator()(error); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__exception_ptr_Wrapper wrap_Func_void_std__exception_ptr(Func_void_std__exception_ptr value) noexcept { + return Func_void_std__exception_ptr_Wrapper(std::move(value)); + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__ = std::optional>; + inline std::optional> create_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::shared_ptr get_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_std__string_ = std::optional; + inline std::optional create_std__optional_std__string_(const std::string& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_std__string_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline std::string get_std__optional_std__string_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::vector + /** + * Specialized version of `std::vector`. + */ + using std__vector_TextTrack_ = std::vector; + inline std::vector copy_std__vector_TextTrack_(const TextTrack* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept { + return margelo::nitro::FastVectorCopy(data, size); + } + inline const TextTrack* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_TextTrack_(const std::vector& vector) noexcept { + return vector.data(); + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_TextTrack_ = std::optional; + inline std::optional create_std__optional_TextTrack_(const TextTrack& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_TextTrack_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline TextTrack get_std__optional_TextTrack_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoPlayerSpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoPlayerSpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoPlayerSpec_ weakify_std__shared_ptr_HybridVideoPlayerSpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: Result>> + using Result_std__shared_ptr_Promise_void___ = Result>>; + inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr>& value) noexcept { + return Result>>::withValue(value); + } + inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::exception_ptr& error) noexcept { + return Result>>::withError(error); + } + + // pragma MARK: Result> + using Result_std__vector_TextTrack__ = Result>; + inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::vector& value) noexcept { + return Result>::withValue(value); + } + inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::exception_ptr& error) noexcept { + return Result>::withError(error); + } + + // pragma MARK: Result + using Result_void_ = Result; + inline Result_void_ create_Result_void_() noexcept { + return Result::withValue(); + } + inline Result_void_ create_Result_void_(const std::exception_ptr& error) noexcept { + return Result::withError(error); + } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoPlayerFactorySpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoPlayerFactorySpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoPlayerFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: Result> + using Result_std__shared_ptr_HybridVideoPlayerSpec__ = Result>; + inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr& value) noexcept { + return Result>::withValue(value); + } + inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::exception_ptr& error) noexcept { + return Result>::withError(error); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_bool = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_bool_Wrapper final { + public: + explicit Func_void_bool_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(bool hasAudioFocus) const noexcept { + _function->operator()(hasAudioFocus); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_bool_Wrapper wrap_Func_void_bool(Func_void_bool value) noexcept { + return Func_void_bool_Wrapper(std::move(value)); + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_double_ = std::optional; + inline std::optional create_std__optional_double_(const double& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_double_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline double get_std__optional_double_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_BandwidthData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_BandwidthData_Wrapper final { + public: + explicit Func_void_BandwidthData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(BandwidthData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_BandwidthData create_Func_void_BandwidthData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_BandwidthData_Wrapper wrap_Func_void_BandwidthData(Func_void_BandwidthData value) noexcept { + return Func_void_BandwidthData_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_onLoadData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_onLoadData_Wrapper final { + public: + explicit Func_void_onLoadData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(onLoadData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_onLoadData create_Func_void_onLoadData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_onLoadData_Wrapper wrap_Func_void_onLoadData(Func_void_onLoadData value) noexcept { + return Func_void_onLoadData_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_onLoadStartData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_onLoadStartData_Wrapper final { + public: + explicit Func_void_onLoadStartData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(onLoadStartData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_onLoadStartData create_Func_void_onLoadStartData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_onLoadStartData_Wrapper wrap_Func_void_onLoadStartData(Func_void_onLoadStartData value) noexcept { + return Func_void_onLoadStartData_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_onPlaybackStateChangeData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_onPlaybackStateChangeData_Wrapper final { + public: + explicit Func_void_onPlaybackStateChangeData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(onPlaybackStateChangeData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_onPlaybackStateChangeData_Wrapper wrap_Func_void_onPlaybackStateChangeData(Func_void_onPlaybackStateChangeData value) noexcept { + return Func_void_onPlaybackStateChangeData_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_double = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_double_Wrapper final { + public: + explicit Func_void_double_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(double rate) const noexcept { + _function->operator()(rate); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_double_Wrapper wrap_Func_void_double(Func_void_double value) noexcept { + return Func_void_double_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_onProgressData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_onProgressData_Wrapper final { + public: + explicit Func_void_onProgressData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(onProgressData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_onProgressData create_Func_void_onProgressData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_onProgressData_Wrapper wrap_Func_void_onProgressData(Func_void_onProgressData value) noexcept { + return Func_void_onProgressData_Wrapper(std::move(value)); + } + + // pragma MARK: std::vector + /** + * Specialized version of `std::vector`. + */ + using std__vector_TimedMetadataObject_ = std::vector; + inline std::vector copy_std__vector_TimedMetadataObject_(const TimedMetadataObject* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept { + return margelo::nitro::FastVectorCopy(data, size); + } + inline const TimedMetadataObject* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_TimedMetadataObject_(const std::vector& vector) noexcept { + return vector.data(); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_TimedMetadata = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_TimedMetadata_Wrapper final { + public: + explicit Func_void_TimedMetadata_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(TimedMetadata metadata) const noexcept { + _function->operator()(metadata); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_TimedMetadata create_Func_void_TimedMetadata(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_TimedMetadata_Wrapper wrap_Func_void_TimedMetadata(Func_void_TimedMetadata value) noexcept { + return Func_void_TimedMetadata_Wrapper(std::move(value)); + } + + // pragma MARK: std::vector + /** + * Specialized version of `std::vector`. + */ + using std__vector_std__string_ = std::vector; + inline std::vector create_std__vector_std__string_(size_t size) noexcept { + std::vector vector; + vector.reserve(size); + return vector; + } + + // pragma MARK: std::function& /* texts */)> + /** + * Specialized version of `std::function&)>`. + */ + using Func_void_std__vector_std__string_ = std::function& /* texts */)>; + /** + * Wrapper class for a `std::function& / * texts * /)>`, this can be used from Swift. + */ + class Func_void_std__vector_std__string__Wrapper final { + public: + explicit Func_void_std__vector_std__string__Wrapper(std::function& /* texts */)>&& func): _function(std::make_unique& /* texts */)>>(std::move(func))) {} + inline void call(std::vector texts) const noexcept { + _function->operator()(texts); + } + private: + std::unique_ptr& /* texts */)>> _function; + } SWIFT_NONCOPYABLE; + Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__vector_std__string__Wrapper wrap_Func_void_std__vector_std__string_(Func_void_std__vector_std__string_ value) noexcept { + return Func_void_std__vector_std__string__Wrapper(std::move(value)); + } + + // pragma MARK: std::function& /* track */)> + /** + * Specialized version of `std::function&)>`. + */ + using Func_void_std__optional_TextTrack_ = std::function& /* track */)>; + /** + * Wrapper class for a `std::function& / * track * /)>`, this can be used from Swift. + */ + class Func_void_std__optional_TextTrack__Wrapper final { + public: + explicit Func_void_std__optional_TextTrack__Wrapper(std::function& /* track */)>&& func): _function(std::make_unique& /* track */)>>(std::move(func))) {} + inline void call(std::optional track) const noexcept { + _function->operator()(track); + } + private: + std::unique_ptr& /* track */)>> _function; + } SWIFT_NONCOPYABLE; + Func_void_std__optional_TextTrack_ create_Func_void_std__optional_TextTrack_(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__optional_TextTrack__Wrapper wrap_Func_void_std__optional_TextTrack_(Func_void_std__optional_TextTrack_ value) noexcept { + return Func_void_std__optional_TextTrack__Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_onVolumeChangeData = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_onVolumeChangeData_Wrapper final { + public: + explicit Func_void_onVolumeChangeData_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(onVolumeChangeData data) const noexcept { + _function->operator()(data); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_onVolumeChangeData_Wrapper wrap_Func_void_onVolumeChangeData(Func_void_onVolumeChangeData value) noexcept { + return Func_void_onVolumeChangeData_Wrapper(std::move(value)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_VideoPlayerStatus = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_VideoPlayerStatus_Wrapper final { + public: + explicit Func_void_VideoPlayerStatus_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(int status) const noexcept { + _function->operator()(static_cast(status)); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_VideoPlayerStatus_Wrapper wrap_Func_void_VideoPlayerStatus(Func_void_VideoPlayerStatus value) noexcept { + return Func_void_VideoPlayerStatus_Wrapper(std::move(value)); + } + + // pragma MARK: std::vector + /** + * Specialized version of `std::vector`. + */ + using std__vector_NativeExternalSubtitle_ = std::vector; + inline std::vector copy_std__vector_NativeExternalSubtitle_(const NativeExternalSubtitle* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept { + return margelo::nitro::FastVectorCopy(data, size); + } + inline const NativeExternalSubtitle* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_NativeExternalSubtitle_(const std::vector& vector) noexcept { + return vector.data(); + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__vector_NativeExternalSubtitle__ = std::optional>; + inline std::optional> create_std__optional_std__vector_NativeExternalSubtitle__(const std::vector& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__vector_NativeExternalSubtitle__(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::vector get_std__optional_std__vector_NativeExternalSubtitle__(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::unordered_map + /** + * Specialized version of `std::unordered_map`. + */ + using std__unordered_map_std__string__std__string_ = std::unordered_map; + inline std::unordered_map create_std__unordered_map_std__string__std__string_(size_t size) noexcept { + std::unordered_map map; + map.reserve(size); + return map; + } + inline std::vector get_std__unordered_map_std__string__std__string__keys(const std__unordered_map_std__string__std__string_& map) noexcept { + std::vector keys; + keys.reserve(map.size()); + for (const auto& entry : map) { + keys.push_back(entry.first); + } + return keys; + } + inline std::string get_std__unordered_map_std__string__std__string__value(const std__unordered_map_std__string__std__string_& map, const std::string& key) noexcept { + return map.find(key)->second; + } + inline void emplace_std__unordered_map_std__string__std__string_(std__unordered_map_std__string__std__string_& map, const std::string& key, const std::string& value) noexcept { + map.emplace(key, value); + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__unordered_map_std__string__std__string__ = std::optional>; + inline std::optional> create_std__optional_std__unordered_map_std__string__std__string__(const std::unordered_map& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__unordered_map_std__string__std__string__(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::unordered_map get_std__optional_std__unordered_map_std__string__std__string__(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_bool_ = std::optional; + inline std::optional create_std__optional_bool_(const bool& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_bool_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline bool get_std__optional_bool_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::shared_ptr> + /** + * Specialized version of `std::shared_ptr>`. + */ + using std__shared_ptr_Promise_std__string__ = std::shared_ptr>; + inline std::shared_ptr> create_std__shared_ptr_Promise_std__string__() noexcept { + return Promise::create(); + } + inline PromiseHolder wrap_std__shared_ptr_Promise_std__string__(std::shared_ptr> promise) noexcept { + return PromiseHolder(std::move(promise)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_std__string = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_std__string_Wrapper final { + public: + explicit Func_void_std__string_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(std::string result) const noexcept { + _function->operator()(result); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_std__string create_Func_void_std__string(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__string_Wrapper wrap_Func_void_std__string(Func_void_std__string value) noexcept { + return Func_void_std__string_Wrapper(std::move(value)); + } + + // pragma MARK: std::function>>>(const OnGetLicensePayload& /* payload */)> + /** + * Specialized version of `std::function>>>(const OnGetLicensePayload&)>`. + */ + using Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload = std::function>>>(const OnGetLicensePayload& /* payload */)>; + /** + * Wrapper class for a `std::function>>>(const OnGetLicensePayload& / * payload * /)>`, this can be used from Swift. + */ + class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper final { + public: + explicit Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper(std::function>>>(const OnGetLicensePayload& /* payload */)>&& func): _function(std::make_unique>>>(const OnGetLicensePayload& /* payload */)>>(std::move(func))) {} + inline std::shared_ptr>>> call(OnGetLicensePayload payload) const noexcept { + auto __result = _function->operator()(payload); + return __result; + } + private: + std::unique_ptr>>>(const OnGetLicensePayload& /* payload */)>> _function; + } SWIFT_NONCOPYABLE; + Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper wrap_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload value) noexcept { + return Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper(std::move(value)); + } + + // pragma MARK: std::shared_ptr>>> + /** + * Specialized version of `std::shared_ptr>>>`. + */ + using std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ = std::shared_ptr>>>; + inline std::shared_ptr>>> create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____() noexcept { + return Promise>>::create(); + } + inline PromiseHolder>> wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(std::shared_ptr>>> promise) noexcept { + return PromiseHolder>>(std::move(promise)); + } + + // pragma MARK: std::function>& /* result */)> + /** + * Specialized version of `std::function>&)>`. + */ + using Func_void_std__shared_ptr_Promise_std__string__ = std::function>& /* result */)>; + /** + * Wrapper class for a `std::function>& / * result * /)>`, this can be used from Swift. + */ + class Func_void_std__shared_ptr_Promise_std__string___Wrapper final { + public: + explicit Func_void_std__shared_ptr_Promise_std__string___Wrapper(std::function>& /* result */)>&& func): _function(std::make_unique>& /* result */)>>(std::move(func))) {} + inline void call(std::shared_ptr> result) const noexcept { + _function->operator()(result); + } + private: + std::unique_ptr>& /* result */)>> _function; + } SWIFT_NONCOPYABLE; + Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_std__shared_ptr_Promise_std__string___Wrapper wrap_Func_void_std__shared_ptr_Promise_std__string__(Func_void_std__shared_ptr_Promise_std__string__ value) noexcept { + return Func_void_std__shared_ptr_Promise_std__string___Wrapper(std::move(value)); + } + + // pragma MARK: std::optional>>>(const OnGetLicensePayload& /* payload */)>> + /** + * Specialized version of `std::optional>>>(const OnGetLicensePayload& / * payload * /)>>`. + */ + using std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ = std::optional>>>(const OnGetLicensePayload& /* payload */)>>; + inline std::optional>>>(const OnGetLicensePayload& /* payload */)>> create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::function>>>(const OnGetLicensePayload& /* payload */)>& value) noexcept { + return std::optional>>>(const OnGetLicensePayload& /* payload */)>>(value); + } + inline bool has_value_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::optional>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept { + return optional.has_value(); + } + inline std::function>>>(const OnGetLicensePayload& /* payload */)> get_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::optional>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_NativeDrmParams_ = std::optional; + inline std::optional create_std__optional_NativeDrmParams_(const NativeDrmParams& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_NativeDrmParams_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline NativeDrmParams get_std__optional_NativeDrmParams_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_LivePlaybackParams_ = std::optional; + inline std::optional create_std__optional_LivePlaybackParams_(const LivePlaybackParams& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_LivePlaybackParams_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline LivePlaybackParams get_std__optional_LivePlaybackParams_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_Resolution_ = std::optional; + inline std::optional create_std__optional_Resolution_(const Resolution& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_Resolution_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline Resolution get_std__optional_Resolution_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_BufferConfig_ = std::optional; + inline std::optional create_std__optional_BufferConfig_(const BufferConfig& value) noexcept { + return std::optional(value); + } + inline bool has_value_std__optional_BufferConfig_(const std::optional& optional) noexcept { + return optional.has_value(); + } + inline BufferConfig get_std__optional_BufferConfig_(const std::optional& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_CustomVideoMetadata_ = std::optional; + inline std::optional create_std__optional_CustomVideoMetadata_(const CustomVideoMetadata& value) { + return std::optional(value); + } + + // pragma MARK: std::shared_ptr> + /** + * Specialized version of `std::shared_ptr>`. + */ + using std__shared_ptr_Promise_VideoInformation__ = std::shared_ptr>; + inline std::shared_ptr> create_std__shared_ptr_Promise_VideoInformation__() noexcept { + return Promise::create(); + } + inline PromiseHolder wrap_std__shared_ptr_Promise_VideoInformation__(std::shared_ptr> promise) noexcept { + return PromiseHolder(std::move(promise)); + } + + // pragma MARK: std::function + /** + * Specialized version of `std::function`. + */ + using Func_void_VideoInformation = std::function; + /** + * Wrapper class for a `std::function`, this can be used from Swift. + */ + class Func_void_VideoInformation_Wrapper final { + public: + explicit Func_void_VideoInformation_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {} + inline void call(VideoInformation result) const noexcept { + _function->operator()(result); + } + private: + std::unique_ptr> _function; + } SWIFT_NONCOPYABLE; + Func_void_VideoInformation create_Func_void_VideoInformation(void* NON_NULL swiftClosureWrapper) noexcept; + inline Func_void_VideoInformation_Wrapper wrap_Func_void_VideoInformation(Func_void_VideoInformation value) noexcept { + return Func_void_VideoInformation_Wrapper(std::move(value)); + } + + // pragma MARK: Result>> + using Result_std__shared_ptr_Promise_VideoInformation___ = Result>>; + inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::shared_ptr>& value) noexcept { + return Result>>::withValue(value); + } + inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::exception_ptr& error) noexcept { + return Result>>::withError(error); + } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: Result> + using Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ = Result>; + inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr& value) noexcept { + return Result>::withValue(value); + } + inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::exception_ptr& error) noexcept { + return Result>::withError(error); + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__shared_ptr_HybridVideoPlayerSpec__ = std::optional>; + inline std::optional> create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::shared_ptr get_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__function_void_bool____isInPictureInPicture______ = std::optional>; + inline std::optional> create_std__optional_std__function_void_bool____isInPictureInPicture______(const std::function& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__function_void_bool____isInPictureInPicture______(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::function get_std__optional_std__function_void_bool____isInPictureInPicture______(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__function_void_bool____fullscreen______ = std::optional>; + inline std::optional> create_std__optional_std__function_void_bool____fullscreen______(const std::function& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__function_void_bool____fullscreen______(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::function get_std__optional_std__function_void_bool____fullscreen______(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::optional> + /** + * Specialized version of `std::optional>`. + */ + using std__optional_std__function_void____ = std::optional>; + inline std::optional> create_std__optional_std__function_void____(const std::function& value) noexcept { + return std::optional>(value); + } + inline bool has_value_std__optional_std__function_void____(const std::optional>& optional) noexcept { + return optional.has_value(); + } + inline std::function get_std__optional_std__function_void____(const std::optional>& optional) noexcept { + return *optional; + } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoViewViewManagerSpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoViewViewManagerSpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoViewViewManagerSpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: Result + using Result_bool_ = Result; + inline Result_bool_ create_Result_bool_(bool value) noexcept { + return Result::withValue(std::move(value)); + } + inline Result_bool_ create_Result_bool_(const std::exception_ptr& error) noexcept { + return Result::withError(error); + } + + // pragma MARK: std::shared_ptr + /** + * Specialized version of `std::shared_ptr`. + */ + using std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ = std::shared_ptr; + std::shared_ptr create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept; + void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType) noexcept; + + // pragma MARK: std::weak_ptr + using std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ = std::weak_ptr; + inline std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(const std::shared_ptr& strong) noexcept { return strong; } + + // pragma MARK: Result> + using Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ = Result>; + inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::shared_ptr& value) noexcept { + return Result>::withValue(value); + } + inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::exception_ptr& error) noexcept { + return Result>::withError(error); + } + +} // namespace margelo::nitro::video::bridge::swift diff --git a/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Umbrella.hpp new file mode 100644 index 00000000..2d88026b --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Umbrella.hpp @@ -0,0 +1,157 @@ +/// +/// ReactNativeVideo-Swift-Cxx-Umbrella.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +// Forward declarations of C++ defined types +// Forward declaration of `BandwidthData` to properly resolve imports. +namespace margelo::nitro::video { struct BandwidthData; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } +// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; } +// Forward declaration of `HybridVideoPlayerFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerFactorySpec; } +// Forward declaration of `HybridVideoPlayerSourceFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceFactorySpec; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `HybridVideoViewViewManagerFactorySpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerFactorySpec; } +// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; } +// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports. +namespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `MixAudioMode` to properly resolve imports. +namespace margelo::nitro::video { enum class MixAudioMode; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `ResizeMode` to properly resolve imports. +namespace margelo::nitro::video { enum class ResizeMode; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `SourceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SourceType; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `SurfaceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SurfaceType; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } +// Forward declaration of `TimedMetadataObject` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadataObject; } +// Forward declaration of `TimedMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadata; } +// Forward declaration of `VideoInformation` to properly resolve imports. +namespace margelo::nitro::video { struct VideoInformation; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } +// Forward declaration of `onLoadData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadData; } +// Forward declaration of `onLoadStartData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadStartData; } +// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onPlaybackStateChangeData; } +// Forward declaration of `onProgressData` to properly resolve imports. +namespace margelo::nitro::video { struct onProgressData; } +// Forward declaration of `onVolumeChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onVolumeChangeData; } + +// Include C++ defined types +#include "BandwidthData.hpp" +#include "BufferConfig.hpp" +#include "CustomVideoMetadata.hpp" +#include "HybridVideoPlayerEventEmitterSpec.hpp" +#include "HybridVideoPlayerFactorySpec.hpp" +#include "HybridVideoPlayerSourceFactorySpec.hpp" +#include "HybridVideoPlayerSourceSpec.hpp" +#include "HybridVideoPlayerSpec.hpp" +#include "HybridVideoViewViewManagerFactorySpec.hpp" +#include "HybridVideoViewViewManagerSpec.hpp" +#include "IgnoreSilentSwitchMode.hpp" +#include "LivePlaybackParams.hpp" +#include "MixAudioMode.hpp" +#include "NativeDrmParams.hpp" +#include "NativeExternalSubtitle.hpp" +#include "NativeVideoConfig.hpp" +#include "OnGetLicensePayload.hpp" +#include "ResizeMode.hpp" +#include "Resolution.hpp" +#include "SourceType.hpp" +#include "SubtitleType.hpp" +#include "SurfaceType.hpp" +#include "TextTrack.hpp" +#include "TimedMetadata.hpp" +#include "TimedMetadataObject.hpp" +#include "VideoInformation.hpp" +#include "VideoOrientation.hpp" +#include "VideoPlayerStatus.hpp" +#include "onLoadData.hpp" +#include "onLoadStartData.hpp" +#include "onPlaybackStateChangeData.hpp" +#include "onProgressData.hpp" +#include "onVolumeChangeData.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// C++ helpers for Swift +#include "ReactNativeVideo-Swift-Cxx-Bridge.hpp" + +// Common C++ types used in Swift +#include +#include +#include +#include + +// Forward declarations of Swift defined types +// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; } +// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; } +// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; } +// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; } +// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; } +// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; } +// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; } + +// Include Swift defined types +#if __has_include("ReactNativeVideo-Swift.h") +// This header is generated by Xcode/Swift on every app build. +// If it cannot be found, make sure the Swift module's name (= podspec name) is actually "ReactNativeVideo". +#include "ReactNativeVideo-Swift.h" +// Same as above, but used when building with frameworks (`use_frameworks`) +#elif __has_include() +#include +#else +#error ReactNativeVideo's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually "ReactNativeVideo", and try building the app first. +#endif diff --git a/nitrogen/generated/ios/ReactNativeVideoAutolinking.mm b/nitrogen/generated/ios/ReactNativeVideoAutolinking.mm new file mode 100644 index 00000000..c4302e17 --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideoAutolinking.mm @@ -0,0 +1,49 @@ +/// +/// ReactNativeVideoAutolinking.mm +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#import +#import +#import "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" +#import + +#include "HybridVideoPlayerFactorySpecSwift.hpp" +#include "HybridVideoPlayerSourceFactorySpecSwift.hpp" +#include "HybridVideoViewViewManagerFactorySpecSwift.hpp" + +@interface ReactNativeVideoAutolinking : NSObject +@end + +@implementation ReactNativeVideoAutolinking + ++ (void) load { + using namespace margelo::nitro; + using namespace margelo::nitro::video; + + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoPlayerFactory", + []() -> std::shared_ptr { + std::shared_ptr hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoPlayerFactory(); + return hybridObject; + } + ); + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoPlayerSourceFactory", + []() -> std::shared_ptr { + std::shared_ptr hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoPlayerSourceFactory(); + return hybridObject; + } + ); + HybridObjectRegistry::registerHybridObjectConstructor( + "VideoViewViewManagerFactory", + []() -> std::shared_ptr { + std::shared_ptr hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoViewViewManagerFactory(); + return hybridObject; + } + ); +} + +@end diff --git a/nitrogen/generated/ios/ReactNativeVideoAutolinking.swift b/nitrogen/generated/ios/ReactNativeVideoAutolinking.swift new file mode 100644 index 00000000..4d2ef780 --- /dev/null +++ b/nitrogen/generated/ios/ReactNativeVideoAutolinking.swift @@ -0,0 +1,55 @@ +/// +/// ReactNativeVideoAutolinking.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +public final class ReactNativeVideoAutolinking { + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Creates an instance of a Swift class that implements `HybridVideoPlayerFactorySpec`, + * and wraps it in a Swift class that can directly interop with C++ (`HybridVideoPlayerFactorySpec_cxx`) + * + * This is generated by Nitrogen and will initialize the class specified + * in the `"autolinking"` property of `nitro.json` (in this case, `HybridVideoPlayerFactory`). + */ + public static func createVideoPlayerFactory() -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ { + let hybridObject = HybridVideoPlayerFactory() + return { () -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ in + let __cxxWrapped = hybridObject.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } + + /** + * Creates an instance of a Swift class that implements `HybridVideoPlayerSourceFactorySpec`, + * and wraps it in a Swift class that can directly interop with C++ (`HybridVideoPlayerSourceFactorySpec_cxx`) + * + * This is generated by Nitrogen and will initialize the class specified + * in the `"autolinking"` property of `nitro.json` (in this case, `HybridVideoPlayerSourceFactory`). + */ + public static func createVideoPlayerSourceFactory() -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ { + let hybridObject = HybridVideoPlayerSourceFactory() + return { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ in + let __cxxWrapped = hybridObject.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } + + /** + * Creates an instance of a Swift class that implements `HybridVideoViewViewManagerFactorySpec`, + * and wraps it in a Swift class that can directly interop with C++ (`HybridVideoViewViewManagerFactorySpec_cxx`) + * + * This is generated by Nitrogen and will initialize the class specified + * in the `"autolinking"` property of `nitro.json` (in this case, `HybridVideoViewViewManagerFactory`). + */ + public static func createVideoViewViewManagerFactory() -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ { + let hybridObject = HybridVideoViewViewManagerFactory() + return { () -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ in + let __cxxWrapped = hybridObject.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } +} diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.cpp new file mode 100644 index 00000000..6c47efb2 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoPlayerEventEmitterSpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerEventEmitterSpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.hpp new file mode 100644 index 00000000..e37e162b --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.hpp @@ -0,0 +1,240 @@ +/// +/// HybridVideoPlayerEventEmitterSpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoPlayerEventEmitterSpec.hpp" + +// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; } + +// Forward declaration of `BandwidthData` to properly resolve imports. +namespace margelo::nitro::video { struct BandwidthData; } +// Forward declaration of `onLoadData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadData; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } +// Forward declaration of `onLoadStartData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadStartData; } +// Forward declaration of `SourceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SourceType; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onPlaybackStateChangeData; } +// Forward declaration of `onProgressData` to properly resolve imports. +namespace margelo::nitro::video { struct onProgressData; } +// Forward declaration of `TimedMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadata; } +// Forward declaration of `TimedMetadataObject` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadataObject; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } +// Forward declaration of `onVolumeChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onVolumeChangeData; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } + +#include +#include "BandwidthData.hpp" +#include +#include "onLoadData.hpp" +#include "VideoOrientation.hpp" +#include "onLoadStartData.hpp" +#include "SourceType.hpp" +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "onPlaybackStateChangeData.hpp" +#include "onProgressData.hpp" +#include "TimedMetadata.hpp" +#include "TimedMetadataObject.hpp" +#include +#include +#include "TextTrack.hpp" +#include "onVolumeChangeData.hpp" +#include "VideoPlayerStatus.hpp" + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoPlayerEventEmitterSpec_cxx.swift. + * + * HybridVideoPlayerEventEmitterSpecSwift (C++) accesses HybridVideoPlayerEventEmitterSpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoPlayerEventEmitterSpec_cxx can directly inherit from the C++ class HybridVideoPlayerEventEmitterSpec + * to simplify the whole structure and memory management. + */ + class HybridVideoPlayerEventEmitterSpecSwift: public virtual HybridVideoPlayerEventEmitterSpec { + public: + // Constructor from a Swift instance + explicit HybridVideoPlayerEventEmitterSpecSwift(const ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& swiftPart): + HybridObject(HybridVideoPlayerEventEmitterSpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + inline std::function getOnAudioBecomingNoisy() noexcept override { + auto __result = _swiftPart.getOnAudioBecomingNoisy(); + return __result; + } + inline void setOnAudioBecomingNoisy(const std::function& onAudioBecomingNoisy) noexcept override { + _swiftPart.setOnAudioBecomingNoisy(onAudioBecomingNoisy); + } + inline std::function getOnAudioFocusChange() noexcept override { + auto __result = _swiftPart.getOnAudioFocusChange(); + return __result; + } + inline void setOnAudioFocusChange(const std::function& onAudioFocusChange) noexcept override { + _swiftPart.setOnAudioFocusChange(onAudioFocusChange); + } + inline std::function getOnBandwidthUpdate() noexcept override { + auto __result = _swiftPart.getOnBandwidthUpdate(); + return __result; + } + inline void setOnBandwidthUpdate(const std::function& onBandwidthUpdate) noexcept override { + _swiftPart.setOnBandwidthUpdate(onBandwidthUpdate); + } + inline std::function getOnBuffer() noexcept override { + auto __result = _swiftPart.getOnBuffer(); + return __result; + } + inline void setOnBuffer(const std::function& onBuffer) noexcept override { + _swiftPart.setOnBuffer(onBuffer); + } + inline std::function getOnControlsVisibleChange() noexcept override { + auto __result = _swiftPart.getOnControlsVisibleChange(); + return __result; + } + inline void setOnControlsVisibleChange(const std::function& onControlsVisibleChange) noexcept override { + _swiftPart.setOnControlsVisibleChange(onControlsVisibleChange); + } + inline std::function getOnEnd() noexcept override { + auto __result = _swiftPart.getOnEnd(); + return __result; + } + inline void setOnEnd(const std::function& onEnd) noexcept override { + _swiftPart.setOnEnd(onEnd); + } + inline std::function getOnExternalPlaybackChange() noexcept override { + auto __result = _swiftPart.getOnExternalPlaybackChange(); + return __result; + } + inline void setOnExternalPlaybackChange(const std::function& onExternalPlaybackChange) noexcept override { + _swiftPart.setOnExternalPlaybackChange(onExternalPlaybackChange); + } + inline std::function getOnLoad() noexcept override { + auto __result = _swiftPart.getOnLoad(); + return __result; + } + inline void setOnLoad(const std::function& onLoad) noexcept override { + _swiftPart.setOnLoad(onLoad); + } + inline std::function getOnLoadStart() noexcept override { + auto __result = _swiftPart.getOnLoadStart(); + return __result; + } + inline void setOnLoadStart(const std::function& onLoadStart) noexcept override { + _swiftPart.setOnLoadStart(onLoadStart); + } + inline std::function getOnPlaybackStateChange() noexcept override { + auto __result = _swiftPart.getOnPlaybackStateChange(); + return __result; + } + inline void setOnPlaybackStateChange(const std::function& onPlaybackStateChange) noexcept override { + _swiftPart.setOnPlaybackStateChange(onPlaybackStateChange); + } + inline std::function getOnPlaybackRateChange() noexcept override { + auto __result = _swiftPart.getOnPlaybackRateChange(); + return __result; + } + inline void setOnPlaybackRateChange(const std::function& onPlaybackRateChange) noexcept override { + _swiftPart.setOnPlaybackRateChange(onPlaybackRateChange); + } + inline std::function getOnProgress() noexcept override { + auto __result = _swiftPart.getOnProgress(); + return __result; + } + inline void setOnProgress(const std::function& onProgress) noexcept override { + _swiftPart.setOnProgress(onProgress); + } + inline std::function getOnReadyToDisplay() noexcept override { + auto __result = _swiftPart.getOnReadyToDisplay(); + return __result; + } + inline void setOnReadyToDisplay(const std::function& onReadyToDisplay) noexcept override { + _swiftPart.setOnReadyToDisplay(onReadyToDisplay); + } + inline std::function getOnSeek() noexcept override { + auto __result = _swiftPart.getOnSeek(); + return __result; + } + inline void setOnSeek(const std::function& onSeek) noexcept override { + _swiftPart.setOnSeek(onSeek); + } + inline std::function getOnTimedMetadata() noexcept override { + auto __result = _swiftPart.getOnTimedMetadata(); + return __result; + } + inline void setOnTimedMetadata(const std::function& onTimedMetadata) noexcept override { + _swiftPart.setOnTimedMetadata(onTimedMetadata); + } + inline std::function& /* texts */)> getOnTextTrackDataChanged() noexcept override { + auto __result = _swiftPart.getOnTextTrackDataChanged(); + return __result; + } + inline void setOnTextTrackDataChanged(const std::function& /* texts */)>& onTextTrackDataChanged) noexcept override { + _swiftPart.setOnTextTrackDataChanged(onTextTrackDataChanged); + } + inline std::function& /* track */)> getOnTrackChange() noexcept override { + auto __result = _swiftPart.getOnTrackChange(); + return __result; + } + inline void setOnTrackChange(const std::function& /* track */)>& onTrackChange) noexcept override { + _swiftPart.setOnTrackChange(onTrackChange); + } + inline std::function getOnVolumeChange() noexcept override { + auto __result = _swiftPart.getOnVolumeChange(); + return __result; + } + inline void setOnVolumeChange(const std::function& onVolumeChange) noexcept override { + _swiftPart.setOnVolumeChange(onVolumeChange); + } + inline std::function getOnStatusChange() noexcept override { + auto __result = _swiftPart.getOnStatusChange(); + return __result; + } + inline void setOnStatusChange(const std::function& onStatusChange) noexcept override { + _swiftPart.setOnStatusChange(onStatusChange); + } + + public: + // Methods + + + private: + ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.cpp new file mode 100644 index 00000000..2cbf600f --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoPlayerFactorySpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerFactorySpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.hpp new file mode 100644 index 00000000..adfd0b95 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.hpp @@ -0,0 +1,78 @@ +/// +/// HybridVideoPlayerFactorySpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoPlayerFactorySpec.hpp" + +// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; } + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include "HybridVideoPlayerSourceSpec.hpp" + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoPlayerFactorySpec_cxx.swift. + * + * HybridVideoPlayerFactorySpecSwift (C++) accesses HybridVideoPlayerFactorySpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoPlayerFactorySpec_cxx can directly inherit from the C++ class HybridVideoPlayerFactorySpec + * to simplify the whole structure and memory management. + */ + class HybridVideoPlayerFactorySpecSwift: public virtual HybridVideoPlayerFactorySpec { + public: + // Constructor from a Swift instance + explicit HybridVideoPlayerFactorySpecSwift(const ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& swiftPart): + HybridObject(HybridVideoPlayerFactorySpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + + + public: + // Methods + inline std::shared_ptr createPlayer(const std::shared_ptr& source) override { + auto __result = _swiftPart.createPlayer(source); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + + private: + ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.cpp new file mode 100644 index 00000000..4329f288 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoPlayerSourceFactorySpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSourceFactorySpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.hpp new file mode 100644 index 00000000..71d90811 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.hpp @@ -0,0 +1,116 @@ +/// +/// HybridVideoPlayerSourceFactorySpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoPlayerSourceFactorySpec.hpp" + +// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; } + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include +#include "NativeVideoConfig.hpp" +#include "NativeExternalSubtitle.hpp" +#include +#include +#include "SubtitleType.hpp" +#include "NativeDrmParams.hpp" +#include +#include +#include "OnGetLicensePayload.hpp" +#include +#include "BufferConfig.hpp" +#include "LivePlaybackParams.hpp" +#include "Resolution.hpp" +#include "CustomVideoMetadata.hpp" + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoPlayerSourceFactorySpec_cxx.swift. + * + * HybridVideoPlayerSourceFactorySpecSwift (C++) accesses HybridVideoPlayerSourceFactorySpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoPlayerSourceFactorySpec_cxx can directly inherit from the C++ class HybridVideoPlayerSourceFactorySpec + * to simplify the whole structure and memory management. + */ + class HybridVideoPlayerSourceFactorySpecSwift: public virtual HybridVideoPlayerSourceFactorySpec { + public: + // Constructor from a Swift instance + explicit HybridVideoPlayerSourceFactorySpecSwift(const ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& swiftPart): + HybridObject(HybridVideoPlayerSourceFactorySpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + + + public: + // Methods + inline std::shared_ptr fromUri(const std::string& uri) override { + auto __result = _swiftPart.fromUri(uri); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline std::shared_ptr fromVideoConfig(const NativeVideoConfig& config) override { + auto __result = _swiftPart.fromVideoConfig(std::forward(config)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + + private: + ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.cpp new file mode 100644 index 00000000..484ce67b --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoPlayerSourceSpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSourceSpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.hpp new file mode 100644 index 00000000..3a3564fc --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.hpp @@ -0,0 +1,116 @@ +/// +/// HybridVideoPlayerSourceSpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoPlayerSourceSpec.hpp" + +// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; } + +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } +// Forward declaration of `VideoInformation` to properly resolve imports. +namespace margelo::nitro::video { struct VideoInformation; } +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } + +#include +#include "NativeVideoConfig.hpp" +#include "NativeExternalSubtitle.hpp" +#include +#include +#include "SubtitleType.hpp" +#include "NativeDrmParams.hpp" +#include +#include +#include "OnGetLicensePayload.hpp" +#include +#include "BufferConfig.hpp" +#include "LivePlaybackParams.hpp" +#include "Resolution.hpp" +#include "CustomVideoMetadata.hpp" +#include "VideoInformation.hpp" +#include "VideoOrientation.hpp" + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoPlayerSourceSpec_cxx.swift. + * + * HybridVideoPlayerSourceSpecSwift (C++) accesses HybridVideoPlayerSourceSpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoPlayerSourceSpec_cxx can directly inherit from the C++ class HybridVideoPlayerSourceSpec + * to simplify the whole structure and memory management. + */ + class HybridVideoPlayerSourceSpecSwift: public virtual HybridVideoPlayerSourceSpec { + public: + // Constructor from a Swift instance + explicit HybridVideoPlayerSourceSpecSwift(const ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& swiftPart): + HybridObject(HybridVideoPlayerSourceSpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + inline std::string getUri() noexcept override { + auto __result = _swiftPart.getUri(); + return __result; + } + inline NativeVideoConfig getConfig() noexcept override { + return _swiftPart.getConfig(); + } + + public: + // Methods + inline std::shared_ptr> getAssetInformationAsync() override { + auto __result = _swiftPart.getAssetInformationAsync(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + + private: + ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.cpp new file mode 100644 index 00000000..90a4cbd0 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoPlayerSpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.hpp new file mode 100644 index 00000000..6ea8e857 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.hpp @@ -0,0 +1,231 @@ +/// +/// HybridVideoPlayerSpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoPlayerSpec.hpp" + +// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; } + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } +// Forward declaration of `MixAudioMode` to properly resolve imports. +namespace margelo::nitro::video { enum class MixAudioMode; } +// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports. +namespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "HybridVideoPlayerEventEmitterSpec.hpp" +#include "VideoPlayerStatus.hpp" +#include "MixAudioMode.hpp" +#include "IgnoreSilentSwitchMode.hpp" +#include "TextTrack.hpp" +#include +#include +#include +#include + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoPlayerSpec_cxx.swift. + * + * HybridVideoPlayerSpecSwift (C++) accesses HybridVideoPlayerSpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoPlayerSpec_cxx can directly inherit from the C++ class HybridVideoPlayerSpec + * to simplify the whole structure and memory management. + */ + class HybridVideoPlayerSpecSwift: public virtual HybridVideoPlayerSpec { + public: + // Constructor from a Swift instance + explicit HybridVideoPlayerSpecSwift(const ReactNativeVideo::HybridVideoPlayerSpec_cxx& swiftPart): + HybridObject(HybridVideoPlayerSpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoPlayerSpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + inline std::shared_ptr getSource() noexcept override { + auto __result = _swiftPart.getSource(); + return __result; + } + inline std::shared_ptr getEventEmitter() noexcept override { + auto __result = _swiftPart.getEventEmitter(); + return __result; + } + inline bool getShowNotificationControls() noexcept override { + return _swiftPart.getShowNotificationControls(); + } + inline void setShowNotificationControls(bool showNotificationControls) noexcept override { + _swiftPart.setShowNotificationControls(std::forward(showNotificationControls)); + } + inline VideoPlayerStatus getStatus() noexcept override { + auto __result = _swiftPart.getStatus(); + return static_cast(__result); + } + inline double getDuration() noexcept override { + return _swiftPart.getDuration(); + } + inline double getVolume() noexcept override { + return _swiftPart.getVolume(); + } + inline void setVolume(double volume) noexcept override { + _swiftPart.setVolume(std::forward(volume)); + } + inline double getCurrentTime() noexcept override { + return _swiftPart.getCurrentTime(); + } + inline void setCurrentTime(double currentTime) noexcept override { + _swiftPart.setCurrentTime(std::forward(currentTime)); + } + inline bool getMuted() noexcept override { + return _swiftPart.getMuted(); + } + inline void setMuted(bool muted) noexcept override { + _swiftPart.setMuted(std::forward(muted)); + } + inline bool getLoop() noexcept override { + return _swiftPart.getLoop(); + } + inline void setLoop(bool loop) noexcept override { + _swiftPart.setLoop(std::forward(loop)); + } + inline double getRate() noexcept override { + return _swiftPart.getRate(); + } + inline void setRate(double rate) noexcept override { + _swiftPart.setRate(std::forward(rate)); + } + inline MixAudioMode getMixAudioMode() noexcept override { + auto __result = _swiftPart.getMixAudioMode(); + return static_cast(__result); + } + inline void setMixAudioMode(MixAudioMode mixAudioMode) noexcept override { + _swiftPart.setMixAudioMode(static_cast(mixAudioMode)); + } + inline IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() noexcept override { + auto __result = _swiftPart.getIgnoreSilentSwitchMode(); + return static_cast(__result); + } + inline void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) noexcept override { + _swiftPart.setIgnoreSilentSwitchMode(static_cast(ignoreSilentSwitchMode)); + } + inline bool getPlayInBackground() noexcept override { + return _swiftPart.getPlayInBackground(); + } + inline void setPlayInBackground(bool playInBackground) noexcept override { + _swiftPart.setPlayInBackground(std::forward(playInBackground)); + } + inline bool getPlayWhenInactive() noexcept override { + return _swiftPart.getPlayWhenInactive(); + } + inline void setPlayWhenInactive(bool playWhenInactive) noexcept override { + _swiftPart.setPlayWhenInactive(std::forward(playWhenInactive)); + } + inline bool getIsPlaying() noexcept override { + return _swiftPart.isPlaying(); + } + inline std::optional getSelectedTrack() noexcept override { + auto __result = _swiftPart.getSelectedTrack(); + return __result; + } + + public: + // Methods + inline std::shared_ptr> replaceSourceAsync(const std::optional>& source) override { + auto __result = _swiftPart.replaceSourceAsync(source); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline std::vector getAvailableTextTracks() override { + auto __result = _swiftPart.getAvailableTextTracks(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline void selectTextTrack(const std::optional& textTrack) override { + auto __result = _swiftPart.selectTextTrack(textTrack); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline std::shared_ptr> initialize() override { + auto __result = _swiftPart.initialize(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline std::shared_ptr> preload() override { + auto __result = _swiftPart.preload(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline void play() override { + auto __result = _swiftPart.play(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void pause() override { + auto __result = _swiftPart.pause(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void seekBy(double time) override { + auto __result = _swiftPart.seekBy(std::forward(time)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void seekTo(double time) override { + auto __result = _swiftPart.seekTo(std::forward(time)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + + private: + ReactNativeVideo::HybridVideoPlayerSpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.cpp new file mode 100644 index 00000000..4e0fa316 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoViewViewManagerFactorySpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoViewViewManagerFactorySpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.hpp new file mode 100644 index 00000000..a45fda33 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.hpp @@ -0,0 +1,75 @@ +/// +/// HybridVideoViewViewManagerFactorySpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoViewViewManagerFactorySpec.hpp" + +// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; } + +// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; } + +#include +#include "HybridVideoViewViewManagerSpec.hpp" + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoViewViewManagerFactorySpec_cxx.swift. + * + * HybridVideoViewViewManagerFactorySpecSwift (C++) accesses HybridVideoViewViewManagerFactorySpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoViewViewManagerFactorySpec_cxx can directly inherit from the C++ class HybridVideoViewViewManagerFactorySpec + * to simplify the whole structure and memory management. + */ + class HybridVideoViewViewManagerFactorySpecSwift: public virtual HybridVideoViewViewManagerFactorySpec { + public: + // Constructor from a Swift instance + explicit HybridVideoViewViewManagerFactorySpecSwift(const ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& swiftPart): + HybridObject(HybridVideoViewViewManagerFactorySpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + + + public: + // Methods + inline std::shared_ptr createViewManager(double nitroId) override { + auto __result = _swiftPart.createViewManager(std::forward(nitroId)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + + private: + ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.cpp b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.cpp new file mode 100644 index 00000000..e004cc59 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.cpp @@ -0,0 +1,11 @@ +/// +/// HybridVideoViewViewManagerSpecSwift.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoViewViewManagerSpecSwift.hpp" + +namespace margelo::nitro::video { +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.hpp new file mode 100644 index 00000000..6d9d0119 --- /dev/null +++ b/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.hpp @@ -0,0 +1,193 @@ +/// +/// HybridVideoViewViewManagerSpecSwift.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#include "HybridVideoViewViewManagerSpec.hpp" + +// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports. +namespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; } + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `ResizeMode` to properly resolve imports. +namespace margelo::nitro::video { enum class ResizeMode; } +// Forward declaration of `SurfaceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SurfaceType; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include +#include "ResizeMode.hpp" +#include "SurfaceType.hpp" +#include + +#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp" + +namespace margelo::nitro::video { + + /** + * The C++ part of HybridVideoViewViewManagerSpec_cxx.swift. + * + * HybridVideoViewViewManagerSpecSwift (C++) accesses HybridVideoViewViewManagerSpec_cxx (Swift), and might + * contain some additional bridging code for C++ <> Swift interop. + * + * Since this obviously introduces an overhead, I hope at some point in + * the future, HybridVideoViewViewManagerSpec_cxx can directly inherit from the C++ class HybridVideoViewViewManagerSpec + * to simplify the whole structure and memory management. + */ + class HybridVideoViewViewManagerSpecSwift: public virtual HybridVideoViewViewManagerSpec { + public: + // Constructor from a Swift instance + explicit HybridVideoViewViewManagerSpecSwift(const ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& swiftPart): + HybridObject(HybridVideoViewViewManagerSpec::TAG), + _swiftPart(swiftPart) { } + + public: + // Get the Swift part + inline ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& getSwiftPart() noexcept { + return _swiftPart; + } + + public: + inline size_t getExternalMemorySize() noexcept override { + return _swiftPart.getMemorySize(); + } + void dispose() noexcept override { + _swiftPart.dispose(); + } + + public: + // Properties + inline std::optional> getPlayer() noexcept override { + auto __result = _swiftPart.getPlayer(); + return __result; + } + inline void setPlayer(const std::optional>& player) noexcept override { + _swiftPart.setPlayer(player); + } + inline bool getControls() noexcept override { + return _swiftPart.getControls(); + } + inline void setControls(bool controls) noexcept override { + _swiftPart.setControls(std::forward(controls)); + } + inline bool getPictureInPicture() noexcept override { + return _swiftPart.getPictureInPicture(); + } + inline void setPictureInPicture(bool pictureInPicture) noexcept override { + _swiftPart.setPictureInPicture(std::forward(pictureInPicture)); + } + inline bool getAutoEnterPictureInPicture() noexcept override { + return _swiftPart.getAutoEnterPictureInPicture(); + } + inline void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) noexcept override { + _swiftPart.setAutoEnterPictureInPicture(std::forward(autoEnterPictureInPicture)); + } + inline ResizeMode getResizeMode() noexcept override { + auto __result = _swiftPart.getResizeMode(); + return static_cast(__result); + } + inline void setResizeMode(ResizeMode resizeMode) noexcept override { + _swiftPart.setResizeMode(static_cast(resizeMode)); + } + inline bool getKeepScreenAwake() noexcept override { + return _swiftPart.getKeepScreenAwake(); + } + inline void setKeepScreenAwake(bool keepScreenAwake) noexcept override { + _swiftPart.setKeepScreenAwake(std::forward(keepScreenAwake)); + } + inline SurfaceType getSurfaceType() noexcept override { + auto __result = _swiftPart.getSurfaceType(); + return static_cast(__result); + } + inline void setSurfaceType(SurfaceType surfaceType) noexcept override { + _swiftPart.setSurfaceType(static_cast(surfaceType)); + } + inline std::optional> getOnPictureInPictureChange() noexcept override { + auto __result = _swiftPart.getOnPictureInPictureChange(); + return __result; + } + inline void setOnPictureInPictureChange(const std::optional>& onPictureInPictureChange) noexcept override { + _swiftPart.setOnPictureInPictureChange(onPictureInPictureChange); + } + inline std::optional> getOnFullscreenChange() noexcept override { + auto __result = _swiftPart.getOnFullscreenChange(); + return __result; + } + inline void setOnFullscreenChange(const std::optional>& onFullscreenChange) noexcept override { + _swiftPart.setOnFullscreenChange(onFullscreenChange); + } + inline std::optional> getWillEnterFullscreen() noexcept override { + auto __result = _swiftPart.getWillEnterFullscreen(); + return __result; + } + inline void setWillEnterFullscreen(const std::optional>& willEnterFullscreen) noexcept override { + _swiftPart.setWillEnterFullscreen(willEnterFullscreen); + } + inline std::optional> getWillExitFullscreen() noexcept override { + auto __result = _swiftPart.getWillExitFullscreen(); + return __result; + } + inline void setWillExitFullscreen(const std::optional>& willExitFullscreen) noexcept override { + _swiftPart.setWillExitFullscreen(willExitFullscreen); + } + inline std::optional> getWillEnterPictureInPicture() noexcept override { + auto __result = _swiftPart.getWillEnterPictureInPicture(); + return __result; + } + inline void setWillEnterPictureInPicture(const std::optional>& willEnterPictureInPicture) noexcept override { + _swiftPart.setWillEnterPictureInPicture(willEnterPictureInPicture); + } + inline std::optional> getWillExitPictureInPicture() noexcept override { + auto __result = _swiftPart.getWillExitPictureInPicture(); + return __result; + } + inline void setWillExitPictureInPicture(const std::optional>& willExitPictureInPicture) noexcept override { + _swiftPart.setWillExitPictureInPicture(willExitPictureInPicture); + } + + public: + // Methods + inline void enterFullscreen() override { + auto __result = _swiftPart.enterFullscreen(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void exitFullscreen() override { + auto __result = _swiftPart.exitFullscreen(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void enterPictureInPicture() override { + auto __result = _swiftPart.enterPictureInPicture(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline void exitPictureInPicture() override { + auto __result = _swiftPart.exitPictureInPicture(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + } + inline bool canEnterPictureInPicture() override { + auto __result = _swiftPart.canEnterPictureInPicture(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + + private: + ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx _swiftPart; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/ios/swift/BandwidthData.swift b/nitrogen/generated/ios/swift/BandwidthData.swift new file mode 100644 index 00000000..94f0d26a --- /dev/null +++ b/nitrogen/generated/ios/swift/BandwidthData.swift @@ -0,0 +1,81 @@ +/// +/// BandwidthData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `BandwidthData`, backed by a C++ struct. + */ +public typealias BandwidthData = margelo.nitro.video.BandwidthData + +public extension BandwidthData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `BandwidthData`. + */ + init(bitrate: Double, width: Double?, height: Double?) { + self.init(bitrate, { () -> bridge.std__optional_double_ in + if let __unwrappedValue = width { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = height { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var bitrate: Double { + @inline(__always) + get { + return self.__bitrate + } + @inline(__always) + set { + self.__bitrate = newValue + } + } + + var width: Double? { + @inline(__always) + get { + return self.__width.value + } + @inline(__always) + set { + self.__width = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var height: Double? { + @inline(__always) + get { + return self.__height.value + } + @inline(__always) + set { + self.__height = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/BufferConfig.swift b/nitrogen/generated/ios/swift/BufferConfig.swift new file mode 100644 index 00000000..1c4dbaf6 --- /dev/null +++ b/nitrogen/generated/ios/swift/BufferConfig.swift @@ -0,0 +1,277 @@ +/// +/// BufferConfig.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `BufferConfig`, backed by a C++ struct. + */ +public typealias BufferConfig = margelo.nitro.video.BufferConfig + +public extension BufferConfig { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `BufferConfig`. + */ + init(livePlayback: LivePlaybackParams?, minBufferMs: Double?, maxBufferMs: Double?, bufferForPlaybackMs: Double?, bufferForPlaybackAfterRebufferMs: Double?, backBufferDurationMs: Double?, preferredForwardBufferDurationMs: Double?, preferredPeakBitRate: Double?, preferredMaximumResolution: Resolution?, preferredPeakBitRateForExpensiveNetworks: Double?, preferredMaximumResolutionForExpensiveNetworks: Resolution?) { + self.init({ () -> bridge.std__optional_LivePlaybackParams_ in + if let __unwrappedValue = livePlayback { + return bridge.create_std__optional_LivePlaybackParams_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = minBufferMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = maxBufferMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = bufferForPlaybackMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = bufferForPlaybackAfterRebufferMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = backBufferDurationMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = preferredForwardBufferDurationMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = preferredPeakBitRate { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_Resolution_ in + if let __unwrappedValue = preferredMaximumResolution { + return bridge.create_std__optional_Resolution_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = preferredPeakBitRateForExpensiveNetworks { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_Resolution_ in + if let __unwrappedValue = preferredMaximumResolutionForExpensiveNetworks { + return bridge.create_std__optional_Resolution_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var livePlayback: LivePlaybackParams? { + @inline(__always) + get { + return self.__livePlayback.value + } + @inline(__always) + set { + self.__livePlayback = { () -> bridge.std__optional_LivePlaybackParams_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_LivePlaybackParams_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var minBufferMs: Double? { + @inline(__always) + get { + return self.__minBufferMs.value + } + @inline(__always) + set { + self.__minBufferMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var maxBufferMs: Double? { + @inline(__always) + get { + return self.__maxBufferMs.value + } + @inline(__always) + set { + self.__maxBufferMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var bufferForPlaybackMs: Double? { + @inline(__always) + get { + return self.__bufferForPlaybackMs.value + } + @inline(__always) + set { + self.__bufferForPlaybackMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var bufferForPlaybackAfterRebufferMs: Double? { + @inline(__always) + get { + return self.__bufferForPlaybackAfterRebufferMs.value + } + @inline(__always) + set { + self.__bufferForPlaybackAfterRebufferMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var backBufferDurationMs: Double? { + @inline(__always) + get { + return self.__backBufferDurationMs.value + } + @inline(__always) + set { + self.__backBufferDurationMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var preferredForwardBufferDurationMs: Double? { + @inline(__always) + get { + return self.__preferredForwardBufferDurationMs.value + } + @inline(__always) + set { + self.__preferredForwardBufferDurationMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var preferredPeakBitRate: Double? { + @inline(__always) + get { + return self.__preferredPeakBitRate.value + } + @inline(__always) + set { + self.__preferredPeakBitRate = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var preferredMaximumResolution: Resolution? { + @inline(__always) + get { + return self.__preferredMaximumResolution.value + } + @inline(__always) + set { + self.__preferredMaximumResolution = { () -> bridge.std__optional_Resolution_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_Resolution_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var preferredPeakBitRateForExpensiveNetworks: Double? { + @inline(__always) + get { + return self.__preferredPeakBitRateForExpensiveNetworks.value + } + @inline(__always) + set { + self.__preferredPeakBitRateForExpensiveNetworks = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var preferredMaximumResolutionForExpensiveNetworks: Resolution? { + @inline(__always) + get { + return self.__preferredMaximumResolutionForExpensiveNetworks.value + } + @inline(__always) + set { + self.__preferredMaximumResolutionForExpensiveNetworks = { () -> bridge.std__optional_Resolution_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_Resolution_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/CustomVideoMetadata.swift b/nitrogen/generated/ios/swift/CustomVideoMetadata.swift new file mode 100644 index 00000000..a9a0e616 --- /dev/null +++ b/nitrogen/generated/ios/swift/CustomVideoMetadata.swift @@ -0,0 +1,169 @@ +/// +/// CustomVideoMetadata.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `CustomVideoMetadata`, backed by a C++ struct. + */ +public typealias CustomVideoMetadata = margelo.nitro.video.CustomVideoMetadata + +public extension CustomVideoMetadata { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `CustomVideoMetadata`. + */ + init(title: String?, subtitle: String?, description: String?, artist: String?, imageUri: String?) { + self.init({ () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = title { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = subtitle { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = description { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = artist { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = imageUri { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }()) + } + + var title: String? { + @inline(__always) + get { + return { () -> String? in + if let __unwrapped = self.__title.value { + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__title = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var subtitle: String? { + @inline(__always) + get { + return { () -> String? in + if let __unwrapped = self.__subtitle.value { + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__subtitle = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var description: String? { + @inline(__always) + get { + return { () -> String? in + if let __unwrapped = self.__description.value { + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__description = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var artist: String? { + @inline(__always) + get { + return { () -> String? in + if let __unwrapped = self.__artist.value { + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__artist = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var imageUri: String? { + @inline(__always) + get { + return { () -> String? in + if let __unwrapped = self.__imageUri.value { + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__imageUri = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift b/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift new file mode 100644 index 00000000..eb52fa34 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift @@ -0,0 +1,62 @@ +/// +/// Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ payload: OnGetLicensePayload) -> Promise>` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ payload: OnGetLicensePayload) -> Promise> + + public init(_ closure: @escaping (_ payload: OnGetLicensePayload) -> Promise>) { + self.closure = closure + } + + @inline(__always) + public func call(payload: OnGetLicensePayload) -> bridge.std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ { + let __result: Promise> = self.closure(payload) + return { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ in + let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(__promise) + __result + .then({ __result in __promiseHolder.resolve({ () -> bridge.std__shared_ptr_Promise_std__string__ in + let __promise = bridge.create_std__shared_ptr_Promise_std__string__() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(__promise) + __result + .then({ __result in __promiseHolder.resolve(std.string(__result)) }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }()) }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void.swift b/nitrogen/generated/ios/swift/Func_void.swift new file mode 100644 index 00000000..48b038a9 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void.swift @@ -0,0 +1,47 @@ +/// +/// Func_void.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `() -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: () -> Void + + public init(_ closure: @escaping () -> Void) { + self.closure = closure + } + + @inline(__always) + public func call() -> Void { + self.closure() + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_BandwidthData.swift b/nitrogen/generated/ios/swift/Func_void_BandwidthData.swift new file mode 100644 index 00000000..59b81f4a --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_BandwidthData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_BandwidthData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: BandwidthData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_BandwidthData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: BandwidthData) -> Void + + public init(_ closure: @escaping (_ data: BandwidthData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: BandwidthData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_BandwidthData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_BandwidthData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift b/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift new file mode 100644 index 00000000..f7efc07e --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_TimedMetadata.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ metadata: TimedMetadata) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_TimedMetadata { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ metadata: TimedMetadata) -> Void + + public init(_ closure: @escaping (_ metadata: TimedMetadata) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(metadata: TimedMetadata) -> Void { + self.closure(metadata) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_TimedMetadata`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_TimedMetadata { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_VideoInformation.swift b/nitrogen/generated/ios/swift/Func_void_VideoInformation.swift new file mode 100644 index 00000000..db0d4ad7 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_VideoInformation.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_VideoInformation.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ value: VideoInformation) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_VideoInformation { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ value: VideoInformation) -> Void + + public init(_ closure: @escaping (_ value: VideoInformation) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(value: VideoInformation) -> Void { + self.closure(value) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_VideoInformation`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_VideoInformation { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_VideoPlayerStatus.swift b/nitrogen/generated/ios/swift/Func_void_VideoPlayerStatus.swift new file mode 100644 index 00000000..183d16ae --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_VideoPlayerStatus.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_VideoPlayerStatus.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ status: VideoPlayerStatus) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_VideoPlayerStatus { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ status: VideoPlayerStatus) -> Void + + public init(_ closure: @escaping (_ status: VideoPlayerStatus) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(status: Int32) -> Void { + self.closure(margelo.nitro.video.VideoPlayerStatus(rawValue: status)!) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_VideoPlayerStatus`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_VideoPlayerStatus { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_bool.swift b/nitrogen/generated/ios/swift/Func_void_bool.swift new file mode 100644 index 00000000..7ed02cc4 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_bool.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_bool.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ isInPictureInPicture: Bool) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_bool { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ isInPictureInPicture: Bool) -> Void + + public init(_ closure: @escaping (_ isInPictureInPicture: Bool) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(isInPictureInPicture: Bool) -> Void { + self.closure(isInPictureInPicture) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_bool`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_bool { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_double.swift b/nitrogen/generated/ios/swift/Func_void_double.swift new file mode 100644 index 00000000..245198bd --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_double.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_double.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ rate: Double) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_double { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ rate: Double) -> Void + + public init(_ closure: @escaping (_ rate: Double) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(rate: Double) -> Void { + self.closure(rate) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_double`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_double { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_onLoadData.swift b/nitrogen/generated/ios/swift/Func_void_onLoadData.swift new file mode 100644 index 00000000..af153509 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_onLoadData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_onLoadData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: onLoadData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_onLoadData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: onLoadData) -> Void + + public init(_ closure: @escaping (_ data: onLoadData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: onLoadData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_onLoadData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onLoadData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_onLoadStartData.swift b/nitrogen/generated/ios/swift/Func_void_onLoadStartData.swift new file mode 100644 index 00000000..7ffdd51f --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_onLoadStartData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_onLoadStartData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: onLoadStartData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_onLoadStartData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: onLoadStartData) -> Void + + public init(_ closure: @escaping (_ data: onLoadStartData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: onLoadStartData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_onLoadStartData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onLoadStartData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_onPlaybackStateChangeData.swift b/nitrogen/generated/ios/swift/Func_void_onPlaybackStateChangeData.swift new file mode 100644 index 00000000..16cfa823 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_onPlaybackStateChangeData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_onPlaybackStateChangeData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: onPlaybackStateChangeData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_onPlaybackStateChangeData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: onPlaybackStateChangeData) -> Void + + public init(_ closure: @escaping (_ data: onPlaybackStateChangeData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: onPlaybackStateChangeData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_onPlaybackStateChangeData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onPlaybackStateChangeData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_onProgressData.swift b/nitrogen/generated/ios/swift/Func_void_onProgressData.swift new file mode 100644 index 00000000..fd7efea8 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_onProgressData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_onProgressData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: onProgressData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_onProgressData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: onProgressData) -> Void + + public init(_ closure: @escaping (_ data: onProgressData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: onProgressData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_onProgressData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onProgressData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_onVolumeChangeData.swift b/nitrogen/generated/ios/swift/Func_void_onVolumeChangeData.swift new file mode 100644 index 00000000..9162496e --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_onVolumeChangeData.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_onVolumeChangeData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ data: onVolumeChangeData) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_onVolumeChangeData { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ data: onVolumeChangeData) -> Void + + public init(_ closure: @escaping (_ data: onVolumeChangeData) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(data: onVolumeChangeData) -> Void { + self.closure(data) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_onVolumeChangeData`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onVolumeChangeData { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift b/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift new file mode 100644 index 00000000..1ff9b139 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_std__exception_ptr.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ error: Error) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__exception_ptr { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ error: Error) -> Void + + public init(_ closure: @escaping (_ error: Error) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(error: std.exception_ptr) -> Void { + self.closure(RuntimeError.from(cppError: error)) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__exception_ptr`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__exception_ptr { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_std__optional_TextTrack_.swift b/nitrogen/generated/ios/swift/Func_void_std__optional_TextTrack_.swift new file mode 100644 index 00000000..23208f7d --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__optional_TextTrack_.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_std__optional_TextTrack_.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ track: TextTrack?) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__optional_TextTrack_ { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ track: TextTrack?) -> Void + + public init(_ closure: @escaping (_ track: TextTrack?) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(track: bridge.std__optional_TextTrack_) -> Void { + self.closure(track.value) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__optional_TextTrack_`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__optional_TextTrack_ { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__string__.swift b/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__string__.swift new file mode 100644 index 00000000..e793bef9 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__string__.swift @@ -0,0 +1,67 @@ +/// +/// Func_void_std__shared_ptr_Promise_std__string__.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ value: Promise) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__shared_ptr_Promise_std__string__ { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ value: Promise) -> Void + + public init(_ closure: @escaping (_ value: Promise) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(value: bridge.std__shared_ptr_Promise_std__string__) -> Void { + self.closure({ () -> Promise in + let __promise = Promise() + let __resolver = { (__result: String) in + __promise.resolve(withResult: __result) + } + let __rejecter = { (__error: Error) in + __promise.reject(withError: __error) + } + let __resolverCpp = { () -> bridge.Func_void_std__string in + let __closureWrapper = Func_void_std__string(__resolver) + return bridge.create_Func_void_std__string(__closureWrapper.toUnsafe()) + }() + let __rejecterCpp = { () -> bridge.Func_void_std__exception_ptr in + let __closureWrapper = Func_void_std__exception_ptr(__rejecter) + return bridge.create_Func_void_std__exception_ptr(__closureWrapper.toUnsafe()) + }() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(value) + __promiseHolder.addOnResolvedListener(__resolverCpp) + __promiseHolder.addOnRejectedListener(__rejecterCpp) + return __promise + }()) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__shared_ptr_Promise_std__string__`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__shared_ptr_Promise_std__string__ { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_std__string.swift b/nitrogen/generated/ios/swift/Func_void_std__string.swift new file mode 100644 index 00000000..155e0826 --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__string.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_std__string.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ value: String) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__string { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ value: String) -> Void + + public init(_ closure: @escaping (_ value: String) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(value: std.string) -> Void { + self.closure(String(value)) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__string`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__string { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift b/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift new file mode 100644 index 00000000..0836c42c --- /dev/null +++ b/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift @@ -0,0 +1,47 @@ +/// +/// Func_void_std__vector_std__string_.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + + +/** + * Wraps a Swift `(_ texts: [String]) -> Void` as a class. + * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. + */ +public final class Func_void_std__vector_std__string_ { + public typealias bridge = margelo.nitro.video.bridge.swift + + private let closure: (_ texts: [String]) -> Void + + public init(_ closure: @escaping (_ texts: [String]) -> Void) { + self.closure = closure + } + + @inline(__always) + public func call(texts: bridge.std__vector_std__string_) -> Void { + self.closure(texts.map({ __item in String(__item) })) + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + @inline(__always) + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `Func_void_std__vector_std__string_`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + @inline(__always) + public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__vector_std__string_ { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec.swift new file mode 100644 index 00000000..b55259ab --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec.swift @@ -0,0 +1,67 @@ +/// +/// HybridVideoPlayerEventEmitterSpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoPlayerEventEmitterSpec`` +public protocol HybridVideoPlayerEventEmitterSpec_protocol: HybridObject { + // Properties + var onAudioBecomingNoisy: () -> Void { get set } + var onAudioFocusChange: (_ hasAudioFocus: Bool) -> Void { get set } + var onBandwidthUpdate: (_ data: BandwidthData) -> Void { get set } + var onBuffer: (_ buffering: Bool) -> Void { get set } + var onControlsVisibleChange: (_ visible: Bool) -> Void { get set } + var onEnd: () -> Void { get set } + var onExternalPlaybackChange: (_ externalPlaybackActive: Bool) -> Void { get set } + var onLoad: (_ data: onLoadData) -> Void { get set } + var onLoadStart: (_ data: onLoadStartData) -> Void { get set } + var onPlaybackStateChange: (_ data: onPlaybackStateChangeData) -> Void { get set } + var onPlaybackRateChange: (_ rate: Double) -> Void { get set } + var onProgress: (_ data: onProgressData) -> Void { get set } + var onReadyToDisplay: () -> Void { get set } + var onSeek: (_ seekTime: Double) -> Void { get set } + var onTimedMetadata: (_ metadata: TimedMetadata) -> Void { get set } + var onTextTrackDataChanged: (_ texts: [String]) -> Void { get set } + var onTrackChange: (_ track: TextTrack?) -> Void { get set } + var onVolumeChange: (_ data: onVolumeChangeData) -> Void { get set } + var onStatusChange: (_ status: VideoPlayerStatus) -> Void { get set } + + // Methods + +} + +/// See ``HybridVideoPlayerEventEmitterSpec`` +open class HybridVideoPlayerEventEmitterSpec_base { + private weak var cxxWrapper: HybridVideoPlayerEventEmitterSpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoPlayerEventEmitterSpec_cxx { + #if DEBUG + guard self is HybridVideoPlayerEventEmitterSpec else { + fatalError("`self` is not a `HybridVideoPlayerEventEmitterSpec`! Did you accidentally inherit from `HybridVideoPlayerEventEmitterSpec_base` instead of `HybridVideoPlayerEventEmitterSpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoPlayerEventEmitterSpec_cxx(self as! HybridVideoPlayerEventEmitterSpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoPlayerEventEmitter HybridObject. + * Implement this protocol to create Swift-based instances of VideoPlayerEventEmitter. + * ```swift + * class HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoPlayerEventEmitterSpec = HybridVideoPlayerEventEmitterSpec_protocol & HybridVideoPlayerEventEmitterSpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec_cxx.swift new file mode 100644 index 00000000..93d0624e --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec_cxx.swift @@ -0,0 +1,484 @@ +/// +/// HybridVideoPlayerEventEmitterSpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoPlayerEventEmitterSpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoPlayerEventEmitterSpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoPlayerEventEmitterSpec` Swift protocol. + */ + private var __implementation: any HybridVideoPlayerEventEmitterSpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ + + /** + * Create a new `HybridVideoPlayerEventEmitterSpec_cxx` that wraps the given `HybridVideoPlayerEventEmitterSpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoPlayerEventEmitterSpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoPlayerEventEmitterSpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoPlayerEventEmitterSpec() -> any HybridVideoPlayerEventEmitterSpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoPlayerEventEmitterSpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerEventEmitterSpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + public final var onAudioBecomingNoisy: bridge.Func_void { + @inline(__always) + get { + return { () -> bridge.Func_void in + let __closureWrapper = Func_void(self.__implementation.onAudioBecomingNoisy) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onAudioBecomingNoisy = { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(newValue) + return { () -> Void in + __wrappedFunction.call() + } + }() + } + } + + public final var onAudioFocusChange: bridge.Func_void_bool { + @inline(__always) + get { + return { () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(self.__implementation.onAudioFocusChange) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onAudioFocusChange = { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(newValue) + return { (__hasAudioFocus: Bool) -> Void in + __wrappedFunction.call(__hasAudioFocus) + } + }() + } + } + + public final var onBandwidthUpdate: bridge.Func_void_BandwidthData { + @inline(__always) + get { + return { () -> bridge.Func_void_BandwidthData in + let __closureWrapper = Func_void_BandwidthData(self.__implementation.onBandwidthUpdate) + return bridge.create_Func_void_BandwidthData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onBandwidthUpdate = { () -> (BandwidthData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_BandwidthData(newValue) + return { (__data: BandwidthData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onBuffer: bridge.Func_void_bool { + @inline(__always) + get { + return { () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(self.__implementation.onBuffer) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onBuffer = { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(newValue) + return { (__buffering: Bool) -> Void in + __wrappedFunction.call(__buffering) + } + }() + } + } + + public final var onControlsVisibleChange: bridge.Func_void_bool { + @inline(__always) + get { + return { () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(self.__implementation.onControlsVisibleChange) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onControlsVisibleChange = { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(newValue) + return { (__visible: Bool) -> Void in + __wrappedFunction.call(__visible) + } + }() + } + } + + public final var onEnd: bridge.Func_void { + @inline(__always) + get { + return { () -> bridge.Func_void in + let __closureWrapper = Func_void(self.__implementation.onEnd) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onEnd = { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(newValue) + return { () -> Void in + __wrappedFunction.call() + } + }() + } + } + + public final var onExternalPlaybackChange: bridge.Func_void_bool { + @inline(__always) + get { + return { () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(self.__implementation.onExternalPlaybackChange) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onExternalPlaybackChange = { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(newValue) + return { (__externalPlaybackActive: Bool) -> Void in + __wrappedFunction.call(__externalPlaybackActive) + } + }() + } + } + + public final var onLoad: bridge.Func_void_onLoadData { + @inline(__always) + get { + return { () -> bridge.Func_void_onLoadData in + let __closureWrapper = Func_void_onLoadData(self.__implementation.onLoad) + return bridge.create_Func_void_onLoadData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onLoad = { () -> (onLoadData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_onLoadData(newValue) + return { (__data: onLoadData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onLoadStart: bridge.Func_void_onLoadStartData { + @inline(__always) + get { + return { () -> bridge.Func_void_onLoadStartData in + let __closureWrapper = Func_void_onLoadStartData(self.__implementation.onLoadStart) + return bridge.create_Func_void_onLoadStartData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onLoadStart = { () -> (onLoadStartData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_onLoadStartData(newValue) + return { (__data: onLoadStartData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onPlaybackStateChange: bridge.Func_void_onPlaybackStateChangeData { + @inline(__always) + get { + return { () -> bridge.Func_void_onPlaybackStateChangeData in + let __closureWrapper = Func_void_onPlaybackStateChangeData(self.__implementation.onPlaybackStateChange) + return bridge.create_Func_void_onPlaybackStateChangeData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onPlaybackStateChange = { () -> (onPlaybackStateChangeData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_onPlaybackStateChangeData(newValue) + return { (__data: onPlaybackStateChangeData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onPlaybackRateChange: bridge.Func_void_double { + @inline(__always) + get { + return { () -> bridge.Func_void_double in + let __closureWrapper = Func_void_double(self.__implementation.onPlaybackRateChange) + return bridge.create_Func_void_double(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onPlaybackRateChange = { () -> (Double) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_double(newValue) + return { (__rate: Double) -> Void in + __wrappedFunction.call(__rate) + } + }() + } + } + + public final var onProgress: bridge.Func_void_onProgressData { + @inline(__always) + get { + return { () -> bridge.Func_void_onProgressData in + let __closureWrapper = Func_void_onProgressData(self.__implementation.onProgress) + return bridge.create_Func_void_onProgressData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onProgress = { () -> (onProgressData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_onProgressData(newValue) + return { (__data: onProgressData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onReadyToDisplay: bridge.Func_void { + @inline(__always) + get { + return { () -> bridge.Func_void in + let __closureWrapper = Func_void(self.__implementation.onReadyToDisplay) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onReadyToDisplay = { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(newValue) + return { () -> Void in + __wrappedFunction.call() + } + }() + } + } + + public final var onSeek: bridge.Func_void_double { + @inline(__always) + get { + return { () -> bridge.Func_void_double in + let __closureWrapper = Func_void_double(self.__implementation.onSeek) + return bridge.create_Func_void_double(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onSeek = { () -> (Double) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_double(newValue) + return { (__seekTime: Double) -> Void in + __wrappedFunction.call(__seekTime) + } + }() + } + } + + public final var onTimedMetadata: bridge.Func_void_TimedMetadata { + @inline(__always) + get { + return { () -> bridge.Func_void_TimedMetadata in + let __closureWrapper = Func_void_TimedMetadata(self.__implementation.onTimedMetadata) + return bridge.create_Func_void_TimedMetadata(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onTimedMetadata = { () -> (TimedMetadata) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_TimedMetadata(newValue) + return { (__metadata: TimedMetadata) -> Void in + __wrappedFunction.call(__metadata) + } + }() + } + } + + public final var onTextTrackDataChanged: bridge.Func_void_std__vector_std__string_ { + @inline(__always) + get { + return { () -> bridge.Func_void_std__vector_std__string_ in + let __closureWrapper = Func_void_std__vector_std__string_(self.__implementation.onTextTrackDataChanged) + return bridge.create_Func_void_std__vector_std__string_(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onTextTrackDataChanged = { () -> ([String]) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_std__vector_std__string_(newValue) + return { (__texts: [String]) -> Void in + __wrappedFunction.call({ () -> bridge.std__vector_std__string_ in + var __vector = bridge.create_std__vector_std__string_(__texts.count) + for __item in __texts { + __vector.push_back(std.string(__item)) + } + return __vector + }()) + } + }() + } + } + + public final var onTrackChange: bridge.Func_void_std__optional_TextTrack_ { + @inline(__always) + get { + return { () -> bridge.Func_void_std__optional_TextTrack_ in + let __closureWrapper = Func_void_std__optional_TextTrack_(self.__implementation.onTrackChange) + return bridge.create_Func_void_std__optional_TextTrack_(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onTrackChange = { () -> (TextTrack?) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_std__optional_TextTrack_(newValue) + return { (__track: TextTrack?) -> Void in + __wrappedFunction.call({ () -> bridge.std__optional_TextTrack_ in + if let __unwrappedValue = __track { + return bridge.create_std__optional_TextTrack_(__unwrappedValue) + } else { + return .init() + } + }()) + } + }() + } + } + + public final var onVolumeChange: bridge.Func_void_onVolumeChangeData { + @inline(__always) + get { + return { () -> bridge.Func_void_onVolumeChangeData in + let __closureWrapper = Func_void_onVolumeChangeData(self.__implementation.onVolumeChange) + return bridge.create_Func_void_onVolumeChangeData(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onVolumeChange = { () -> (onVolumeChangeData) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_onVolumeChangeData(newValue) + return { (__data: onVolumeChangeData) -> Void in + __wrappedFunction.call(__data) + } + }() + } + } + + public final var onStatusChange: bridge.Func_void_VideoPlayerStatus { + @inline(__always) + get { + return { () -> bridge.Func_void_VideoPlayerStatus in + let __closureWrapper = Func_void_VideoPlayerStatus(self.__implementation.onStatusChange) + return bridge.create_Func_void_VideoPlayerStatus(__closureWrapper.toUnsafe()) + }() + } + @inline(__always) + set { + self.__implementation.onStatusChange = { () -> (VideoPlayerStatus) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_VideoPlayerStatus(newValue) + return { (__status: VideoPlayerStatus) -> Void in + __wrappedFunction.call(__status.rawValue) + } + }() + } + } + + // Methods + +} diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec.swift new file mode 100644 index 00000000..a3ef9be8 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec.swift @@ -0,0 +1,49 @@ +/// +/// HybridVideoPlayerFactorySpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoPlayerFactorySpec`` +public protocol HybridVideoPlayerFactorySpec_protocol: HybridObject { + // Properties + + + // Methods + func createPlayer(source: (any HybridVideoPlayerSourceSpec)) throws -> (any HybridVideoPlayerSpec) +} + +/// See ``HybridVideoPlayerFactorySpec`` +open class HybridVideoPlayerFactorySpec_base { + private weak var cxxWrapper: HybridVideoPlayerFactorySpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoPlayerFactorySpec_cxx { + #if DEBUG + guard self is HybridVideoPlayerFactorySpec else { + fatalError("`self` is not a `HybridVideoPlayerFactorySpec`! Did you accidentally inherit from `HybridVideoPlayerFactorySpec_base` instead of `HybridVideoPlayerFactorySpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoPlayerFactorySpec_cxx(self as! HybridVideoPlayerFactorySpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoPlayerFactory HybridObject. + * Implement this protocol to create Swift-based instances of VideoPlayerFactory. + * ```swift + * class HybridVideoPlayerFactory : HybridVideoPlayerFactorySpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoPlayerFactorySpec = HybridVideoPlayerFactorySpec_protocol & HybridVideoPlayerFactorySpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec_cxx.swift new file mode 100644 index 00000000..5a76e01a --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec_cxx.swift @@ -0,0 +1,130 @@ +/// +/// HybridVideoPlayerFactorySpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoPlayerFactorySpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoPlayerFactorySpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoPlayerFactorySpec` Swift protocol. + */ + private var __implementation: any HybridVideoPlayerFactorySpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerFactorySpec_ + + /** + * Create a new `HybridVideoPlayerFactorySpec_cxx` that wraps the given `HybridVideoPlayerFactorySpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoPlayerFactorySpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoPlayerFactorySpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoPlayerFactorySpec() -> any HybridVideoPlayerFactorySpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoPlayerFactorySpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerFactorySpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerFactorySpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + + + // Methods + @inline(__always) + public final func createPlayer(source: bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSpec__ { + do { + let __result = try self.__implementation.createPlayer(source: { () -> HybridVideoPlayerSourceSpec in + let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(source) + let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer) + return __instance.getHybridVideoPlayerSourceSpec() + }()) + let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSpec__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSpec__(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec.swift new file mode 100644 index 00000000..7f2f1034 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec.swift @@ -0,0 +1,50 @@ +/// +/// HybridVideoPlayerSourceFactorySpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoPlayerSourceFactorySpec`` +public protocol HybridVideoPlayerSourceFactorySpec_protocol: HybridObject { + // Properties + + + // Methods + func fromUri(uri: String) throws -> (any HybridVideoPlayerSourceSpec) + func fromVideoConfig(config: NativeVideoConfig) throws -> (any HybridVideoPlayerSourceSpec) +} + +/// See ``HybridVideoPlayerSourceFactorySpec`` +open class HybridVideoPlayerSourceFactorySpec_base { + private weak var cxxWrapper: HybridVideoPlayerSourceFactorySpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoPlayerSourceFactorySpec_cxx { + #if DEBUG + guard self is HybridVideoPlayerSourceFactorySpec else { + fatalError("`self` is not a `HybridVideoPlayerSourceFactorySpec`! Did you accidentally inherit from `HybridVideoPlayerSourceFactorySpec_base` instead of `HybridVideoPlayerSourceFactorySpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoPlayerSourceFactorySpec_cxx(self as! HybridVideoPlayerSourceFactorySpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoPlayerSourceFactory HybridObject. + * Implement this protocol to create Swift-based instances of VideoPlayerSourceFactory. + * ```swift + * class HybridVideoPlayerSourceFactory : HybridVideoPlayerSourceFactorySpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoPlayerSourceFactorySpec = HybridVideoPlayerSourceFactorySpec_protocol & HybridVideoPlayerSourceFactorySpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec_cxx.swift new file mode 100644 index 00000000..a6978fc0 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec_cxx.swift @@ -0,0 +1,141 @@ +/// +/// HybridVideoPlayerSourceFactorySpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoPlayerSourceFactorySpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoPlayerSourceFactorySpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoPlayerSourceFactorySpec` Swift protocol. + */ + private var __implementation: any HybridVideoPlayerSourceFactorySpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ + + /** + * Create a new `HybridVideoPlayerSourceFactorySpec_cxx` that wraps the given `HybridVideoPlayerSourceFactorySpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoPlayerSourceFactorySpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoPlayerSourceFactorySpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoPlayerSourceFactorySpec() -> any HybridVideoPlayerSourceFactorySpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoPlayerSourceFactorySpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSourceFactorySpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + + + // Methods + @inline(__always) + public final func fromUri(uri: std.string) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ { + do { + let __result = try self.__implementation.fromUri(uri: String(uri)) + let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__exceptionPtr) + } + } + + @inline(__always) + public final func fromVideoConfig(config: NativeVideoConfig) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ { + do { + let __result = try self.__implementation.fromVideoConfig(config: config) + let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec.swift new file mode 100644 index 00000000..0bf86e9a --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec.swift @@ -0,0 +1,50 @@ +/// +/// HybridVideoPlayerSourceSpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoPlayerSourceSpec`` +public protocol HybridVideoPlayerSourceSpec_protocol: HybridObject { + // Properties + var uri: String { get } + var config: NativeVideoConfig { get } + + // Methods + func getAssetInformationAsync() throws -> Promise +} + +/// See ``HybridVideoPlayerSourceSpec`` +open class HybridVideoPlayerSourceSpec_base { + private weak var cxxWrapper: HybridVideoPlayerSourceSpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoPlayerSourceSpec_cxx { + #if DEBUG + guard self is HybridVideoPlayerSourceSpec else { + fatalError("`self` is not a `HybridVideoPlayerSourceSpec`! Did you accidentally inherit from `HybridVideoPlayerSourceSpec_base` instead of `HybridVideoPlayerSourceSpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoPlayerSourceSpec_cxx(self as! HybridVideoPlayerSourceSpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoPlayerSource HybridObject. + * Implement this protocol to create Swift-based instances of VideoPlayerSource. + * ```swift + * class HybridVideoPlayerSource : HybridVideoPlayerSourceSpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoPlayerSourceSpec = HybridVideoPlayerSourceSpec_protocol & HybridVideoPlayerSourceSpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec_cxx.swift new file mode 100644 index 00000000..810c8253 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec_cxx.swift @@ -0,0 +1,142 @@ +/// +/// HybridVideoPlayerSourceSpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoPlayerSourceSpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoPlayerSourceSpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoPlayerSourceSpec` Swift protocol. + */ + private var __implementation: any HybridVideoPlayerSourceSpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSourceSpec_ + + /** + * Create a new `HybridVideoPlayerSourceSpec_cxx` that wraps the given `HybridVideoPlayerSourceSpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoPlayerSourceSpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoPlayerSourceSpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoPlayerSourceSpec() -> any HybridVideoPlayerSourceSpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoPlayerSourceSpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSourceSpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSourceSpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + public final var uri: std.string { + @inline(__always) + get { + return std.string(self.__implementation.uri) + } + } + + public final var config: NativeVideoConfig { + @inline(__always) + get { + return self.__implementation.config + } + } + + // Methods + @inline(__always) + public final func getAssetInformationAsync() -> bridge.Result_std__shared_ptr_Promise_VideoInformation___ { + do { + let __result = try self.__implementation.getAssetInformationAsync() + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_VideoInformation__ in + let __promise = bridge.create_std__shared_ptr_Promise_VideoInformation__() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_VideoInformation__(__promise) + __result + .then({ __result in __promiseHolder.resolve(__result) }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + return bridge.create_Result_std__shared_ptr_Promise_VideoInformation___(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_Promise_VideoInformation___(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSpec.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSpec.swift new file mode 100644 index 00000000..a72adeb6 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSpec.swift @@ -0,0 +1,72 @@ +/// +/// HybridVideoPlayerSpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoPlayerSpec`` +public protocol HybridVideoPlayerSpec_protocol: HybridObject { + // Properties + var source: (any HybridVideoPlayerSourceSpec) { get } + var eventEmitter: (any HybridVideoPlayerEventEmitterSpec) { get } + var showNotificationControls: Bool { get set } + var status: VideoPlayerStatus { get } + var duration: Double { get } + var volume: Double { get set } + var currentTime: Double { get set } + var muted: Bool { get set } + var loop: Bool { get set } + var rate: Double { get set } + var mixAudioMode: MixAudioMode { get set } + var ignoreSilentSwitchMode: IgnoreSilentSwitchMode { get set } + var playInBackground: Bool { get set } + var playWhenInactive: Bool { get set } + var isPlaying: Bool { get } + var selectedTrack: TextTrack? { get } + + // Methods + func replaceSourceAsync(source: (any HybridVideoPlayerSourceSpec)?) throws -> Promise + func getAvailableTextTracks() throws -> [TextTrack] + func selectTextTrack(textTrack: TextTrack?) throws -> Void + func initialize() throws -> Promise + func preload() throws -> Promise + func play() throws -> Void + func pause() throws -> Void + func seekBy(time: Double) throws -> Void + func seekTo(time: Double) throws -> Void +} + +/// See ``HybridVideoPlayerSpec`` +open class HybridVideoPlayerSpec_base { + private weak var cxxWrapper: HybridVideoPlayerSpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoPlayerSpec_cxx { + #if DEBUG + guard self is HybridVideoPlayerSpec else { + fatalError("`self` is not a `HybridVideoPlayerSpec`! Did you accidentally inherit from `HybridVideoPlayerSpec_base` instead of `HybridVideoPlayerSpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoPlayerSpec_cxx(self as! HybridVideoPlayerSpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoPlayer HybridObject. + * Implement this protocol to create Swift-based instances of VideoPlayer. + * ```swift + * class HybridVideoPlayer : HybridVideoPlayerSpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoPlayerSpec = HybridVideoPlayerSpec_protocol & HybridVideoPlayerSpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoPlayerSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoPlayerSpec_cxx.swift new file mode 100644 index 00000000..13e805cf --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoPlayerSpec_cxx.swift @@ -0,0 +1,410 @@ +/// +/// HybridVideoPlayerSpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoPlayerSpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoPlayerSpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoPlayerSpec` Swift protocol. + */ + private var __implementation: any HybridVideoPlayerSpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSpec_ + + /** + * Create a new `HybridVideoPlayerSpec_cxx` that wraps the given `HybridVideoPlayerSpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoPlayerSpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoPlayerSpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoPlayerSpec() -> any HybridVideoPlayerSpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoPlayerSpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + public final var source: bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ { + @inline(__always) + get { + return { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in + let __cxxWrapped = self.__implementation.source.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } + } + + public final var eventEmitter: bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ { + @inline(__always) + get { + return { () -> bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ in + let __cxxWrapped = self.__implementation.eventEmitter.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } + } + + public final var showNotificationControls: Bool { + @inline(__always) + get { + return self.__implementation.showNotificationControls + } + @inline(__always) + set { + self.__implementation.showNotificationControls = newValue + } + } + + public final var status: Int32 { + @inline(__always) + get { + return self.__implementation.status.rawValue + } + } + + public final var duration: Double { + @inline(__always) + get { + return self.__implementation.duration + } + } + + public final var volume: Double { + @inline(__always) + get { + return self.__implementation.volume + } + @inline(__always) + set { + self.__implementation.volume = newValue + } + } + + public final var currentTime: Double { + @inline(__always) + get { + return self.__implementation.currentTime + } + @inline(__always) + set { + self.__implementation.currentTime = newValue + } + } + + public final var muted: Bool { + @inline(__always) + get { + return self.__implementation.muted + } + @inline(__always) + set { + self.__implementation.muted = newValue + } + } + + public final var loop: Bool { + @inline(__always) + get { + return self.__implementation.loop + } + @inline(__always) + set { + self.__implementation.loop = newValue + } + } + + public final var rate: Double { + @inline(__always) + get { + return self.__implementation.rate + } + @inline(__always) + set { + self.__implementation.rate = newValue + } + } + + public final var mixAudioMode: Int32 { + @inline(__always) + get { + return self.__implementation.mixAudioMode.rawValue + } + @inline(__always) + set { + self.__implementation.mixAudioMode = margelo.nitro.video.MixAudioMode(rawValue: newValue)! + } + } + + public final var ignoreSilentSwitchMode: Int32 { + @inline(__always) + get { + return self.__implementation.ignoreSilentSwitchMode.rawValue + } + @inline(__always) + set { + self.__implementation.ignoreSilentSwitchMode = margelo.nitro.video.IgnoreSilentSwitchMode(rawValue: newValue)! + } + } + + public final var playInBackground: Bool { + @inline(__always) + get { + return self.__implementation.playInBackground + } + @inline(__always) + set { + self.__implementation.playInBackground = newValue + } + } + + public final var playWhenInactive: Bool { + @inline(__always) + get { + return self.__implementation.playWhenInactive + } + @inline(__always) + set { + self.__implementation.playWhenInactive = newValue + } + } + + public final var isPlaying: Bool { + @inline(__always) + get { + return self.__implementation.isPlaying + } + } + + public final var selectedTrack: bridge.std__optional_TextTrack_ { + @inline(__always) + get { + return { () -> bridge.std__optional_TextTrack_ in + if let __unwrappedValue = self.__implementation.selectedTrack { + return bridge.create_std__optional_TextTrack_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + // Methods + @inline(__always) + public final func replaceSourceAsync(source: bridge.std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__) -> bridge.Result_std__shared_ptr_Promise_void___ { + do { + let __result = try self.__implementation.replaceSourceAsync(source: { () -> (any HybridVideoPlayerSourceSpec)? in + if bridge.has_value_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(source) { + let __unwrapped = bridge.get_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(source) + return { () -> HybridVideoPlayerSourceSpec in + let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(__unwrapped) + let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer) + return __instance.getHybridVideoPlayerSourceSpec() + }() + } else { + return nil + } + }()) + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in + let __promise = bridge.create_std__shared_ptr_Promise_void__() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise) + __result + .then({ __result in __promiseHolder.resolve() }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr) + } + } + + @inline(__always) + public final func getAvailableTextTracks() -> bridge.Result_std__vector_TextTrack__ { + do { + let __result = try self.__implementation.getAvailableTextTracks() + let __resultCpp = __result.withUnsafeBufferPointer { __pointer -> bridge.std__vector_TextTrack_ in + return bridge.copy_std__vector_TextTrack_(__pointer.baseAddress!, __result.count) + } + return bridge.create_Result_std__vector_TextTrack__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__vector_TextTrack__(__exceptionPtr) + } + } + + @inline(__always) + public final func selectTextTrack(textTrack: bridge.std__optional_TextTrack_) -> bridge.Result_void_ { + do { + try self.__implementation.selectTextTrack(textTrack: textTrack.value) + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func initialize() -> bridge.Result_std__shared_ptr_Promise_void___ { + do { + let __result = try self.__implementation.initialize() + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in + let __promise = bridge.create_std__shared_ptr_Promise_void__() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise) + __result + .then({ __result in __promiseHolder.resolve() }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr) + } + } + + @inline(__always) + public final func preload() -> bridge.Result_std__shared_ptr_Promise_void___ { + do { + let __result = try self.__implementation.preload() + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in + let __promise = bridge.create_std__shared_ptr_Promise_void__() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise) + __result + .then({ __result in __promiseHolder.resolve() }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr) + } + } + + @inline(__always) + public final func play() -> bridge.Result_void_ { + do { + try self.__implementation.play() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func pause() -> bridge.Result_void_ { + do { + try self.__implementation.pause() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func seekBy(time: Double) -> bridge.Result_void_ { + do { + try self.__implementation.seekBy(time: time) + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func seekTo(time: Double) -> bridge.Result_void_ { + do { + try self.__implementation.seekTo(time: time) + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec.swift b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec.swift new file mode 100644 index 00000000..cdbbbe1e --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec.swift @@ -0,0 +1,49 @@ +/// +/// HybridVideoViewViewManagerFactorySpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoViewViewManagerFactorySpec`` +public protocol HybridVideoViewViewManagerFactorySpec_protocol: HybridObject { + // Properties + + + // Methods + func createViewManager(nitroId: Double) throws -> (any HybridVideoViewViewManagerSpec) +} + +/// See ``HybridVideoViewViewManagerFactorySpec`` +open class HybridVideoViewViewManagerFactorySpec_base { + private weak var cxxWrapper: HybridVideoViewViewManagerFactorySpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoViewViewManagerFactorySpec_cxx { + #if DEBUG + guard self is HybridVideoViewViewManagerFactorySpec else { + fatalError("`self` is not a `HybridVideoViewViewManagerFactorySpec`! Did you accidentally inherit from `HybridVideoViewViewManagerFactorySpec_base` instead of `HybridVideoViewViewManagerFactorySpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoViewViewManagerFactorySpec_cxx(self as! HybridVideoViewViewManagerFactorySpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoViewViewManagerFactory HybridObject. + * Implement this protocol to create Swift-based instances of VideoViewViewManagerFactory. + * ```swift + * class HybridVideoViewViewManagerFactory : HybridVideoViewViewManagerFactorySpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoViewViewManagerFactorySpec = HybridVideoViewViewManagerFactorySpec_protocol & HybridVideoViewViewManagerFactorySpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec_cxx.swift new file mode 100644 index 00000000..112b5698 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec_cxx.swift @@ -0,0 +1,126 @@ +/// +/// HybridVideoViewViewManagerFactorySpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoViewViewManagerFactorySpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoViewViewManagerFactorySpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoViewViewManagerFactorySpec` Swift protocol. + */ + private var __implementation: any HybridVideoViewViewManagerFactorySpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ + + /** + * Create a new `HybridVideoViewViewManagerFactorySpec_cxx` that wraps the given `HybridVideoViewViewManagerFactorySpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoViewViewManagerFactorySpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoViewViewManagerFactorySpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoViewViewManagerFactorySpec() -> any HybridVideoViewViewManagerFactorySpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoViewViewManagerFactorySpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoViewViewManagerFactorySpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + + + // Methods + @inline(__always) + public final func createViewManager(nitroId: Double) -> bridge.Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ { + do { + let __result = try self.__implementation.createViewManager(nitroId: nitroId) + let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoViewViewManagerSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + return bridge.create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec.swift b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec.swift new file mode 100644 index 00000000..0f731fcc --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec.swift @@ -0,0 +1,65 @@ +/// +/// HybridVideoViewViewManagerSpec.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/// See ``HybridVideoViewViewManagerSpec`` +public protocol HybridVideoViewViewManagerSpec_protocol: HybridObject { + // Properties + var player: (any HybridVideoPlayerSpec)? { get set } + var controls: Bool { get set } + var pictureInPicture: Bool { get set } + var autoEnterPictureInPicture: Bool { get set } + var resizeMode: ResizeMode { get set } + var keepScreenAwake: Bool { get set } + var surfaceType: SurfaceType { get set } + var onPictureInPictureChange: ((_ isInPictureInPicture: Bool) -> Void)? { get set } + var onFullscreenChange: ((_ fullscreen: Bool) -> Void)? { get set } + var willEnterFullscreen: (() -> Void)? { get set } + var willExitFullscreen: (() -> Void)? { get set } + var willEnterPictureInPicture: (() -> Void)? { get set } + var willExitPictureInPicture: (() -> Void)? { get set } + + // Methods + func enterFullscreen() throws -> Void + func exitFullscreen() throws -> Void + func enterPictureInPicture() throws -> Void + func exitPictureInPicture() throws -> Void + func canEnterPictureInPicture() throws -> Bool +} + +/// See ``HybridVideoViewViewManagerSpec`` +open class HybridVideoViewViewManagerSpec_base { + private weak var cxxWrapper: HybridVideoViewViewManagerSpec_cxx? = nil + public init() { } + public func getCxxWrapper() -> HybridVideoViewViewManagerSpec_cxx { + #if DEBUG + guard self is HybridVideoViewViewManagerSpec else { + fatalError("`self` is not a `HybridVideoViewViewManagerSpec`! Did you accidentally inherit from `HybridVideoViewViewManagerSpec_base` instead of `HybridVideoViewViewManagerSpec`?") + } + #endif + if let cxxWrapper = self.cxxWrapper { + return cxxWrapper + } else { + let cxxWrapper = HybridVideoViewViewManagerSpec_cxx(self as! HybridVideoViewViewManagerSpec) + self.cxxWrapper = cxxWrapper + return cxxWrapper + } + } +} + +/** + * A Swift base-protocol representing the VideoViewViewManager HybridObject. + * Implement this protocol to create Swift-based instances of VideoViewViewManager. + * ```swift + * class HybridVideoViewViewManager : HybridVideoViewViewManagerSpec { + * // ... + * } + * ``` + */ +public typealias HybridVideoViewViewManagerSpec = HybridVideoViewViewManagerSpec_protocol & HybridVideoViewViewManagerSpec_base diff --git a/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec_cxx.swift new file mode 100644 index 00000000..b6ef9f04 --- /dev/null +++ b/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec_cxx.swift @@ -0,0 +1,454 @@ +/// +/// HybridVideoViewViewManagerSpec_cxx.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import Foundation +import NitroModules + +/** + * A class implementation that bridges HybridVideoViewViewManagerSpec over to C++. + * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. + * + * Also, some Swift types need to be bridged with special handling: + * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) + * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper + * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ + */ +open class HybridVideoViewViewManagerSpec_cxx { + /** + * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`) + * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`. + * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. + */ + public typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Holds an instance of the `HybridVideoViewViewManagerSpec` Swift protocol. + */ + private var __implementation: any HybridVideoViewViewManagerSpec + + /** + * Holds a weak pointer to the C++ class that wraps the Swift class. + */ + private var __cxxPart: bridge.std__weak_ptr_HybridVideoViewViewManagerSpec_ + + /** + * Create a new `HybridVideoViewViewManagerSpec_cxx` that wraps the given `HybridVideoViewViewManagerSpec`. + * All properties and methods bridge to C++ types. + */ + public init(_ implementation: any HybridVideoViewViewManagerSpec) { + self.__implementation = implementation + self.__cxxPart = .init() + /* no base class */ + } + + /** + * Get the actual `HybridVideoViewViewManagerSpec` instance this class wraps. + */ + @inline(__always) + public func getHybridVideoViewViewManagerSpec() -> any HybridVideoViewViewManagerSpec { + return __implementation + } + + /** + * Casts this instance to a retained unsafe raw pointer. + * This acquires one additional strong reference on the object! + */ + public func toUnsafe() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + /** + * Casts an unsafe pointer to a `HybridVideoViewViewManagerSpec_cxx`. + * The pointer has to be a retained opaque `Unmanaged`. + * This removes one strong reference from the object! + */ + public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoViewViewManagerSpec_cxx { + return Unmanaged.fromOpaque(pointer).takeRetainedValue() + } + + /** + * Gets (or creates) the C++ part of this Hybrid Object. + * The C++ part is a `std::shared_ptr`. + */ + public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoViewViewManagerSpec_ { + let cachedCxxPart = self.__cxxPart.lock() + if cachedCxxPart.__convertToBool() { + return cachedCxxPart + } else { + let newCxxPart = bridge.create_std__shared_ptr_HybridVideoViewViewManagerSpec_(self.toUnsafe()) + __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(newCxxPart) + return newCxxPart + } + } + + + + /** + * Get the memory size of the Swift class (plus size of any other allocations) + * so the JS VM can properly track it and garbage-collect the JS object if needed. + */ + @inline(__always) + public var memorySize: Int { + return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize + } + + /** + * Call dispose() on the Swift class. + * This _may_ be called manually from JS. + */ + @inline(__always) + public func dispose() { + self.__implementation.dispose() + } + + // Properties + public final var player: bridge.std__optional_std__shared_ptr_HybridVideoPlayerSpec__ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__shared_ptr_HybridVideoPlayerSpec__ in + if let __unwrappedValue = self.__implementation.player { + return bridge.create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__({ () -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ in + let __cxxWrapped = __unwrappedValue.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.player = { () -> (any HybridVideoPlayerSpec)? in + if bridge.has_value_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(newValue) { + let __unwrapped = bridge.get_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(newValue) + return { () -> HybridVideoPlayerSpec in + let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSpec_(__unwrapped) + let __instance = HybridVideoPlayerSpec_cxx.fromUnsafe(__unsafePointer) + return __instance.getHybridVideoPlayerSpec() + }() + } else { + return nil + } + }() + } + } + + public final var controls: Bool { + @inline(__always) + get { + return self.__implementation.controls + } + @inline(__always) + set { + self.__implementation.controls = newValue + } + } + + public final var pictureInPicture: Bool { + @inline(__always) + get { + return self.__implementation.pictureInPicture + } + @inline(__always) + set { + self.__implementation.pictureInPicture = newValue + } + } + + public final var autoEnterPictureInPicture: Bool { + @inline(__always) + get { + return self.__implementation.autoEnterPictureInPicture + } + @inline(__always) + set { + self.__implementation.autoEnterPictureInPicture = newValue + } + } + + public final var resizeMode: Int32 { + @inline(__always) + get { + return self.__implementation.resizeMode.rawValue + } + @inline(__always) + set { + self.__implementation.resizeMode = margelo.nitro.video.ResizeMode(rawValue: newValue)! + } + } + + public final var keepScreenAwake: Bool { + @inline(__always) + get { + return self.__implementation.keepScreenAwake + } + @inline(__always) + set { + self.__implementation.keepScreenAwake = newValue + } + } + + public final var surfaceType: Int32 { + @inline(__always) + get { + return self.__implementation.surfaceType.rawValue + } + @inline(__always) + set { + self.__implementation.surfaceType = margelo.nitro.video.SurfaceType(rawValue: newValue)! + } + } + + public final var onPictureInPictureChange: bridge.std__optional_std__function_void_bool____isInPictureInPicture______ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void_bool____isInPictureInPicture______ in + if let __unwrappedValue = self.__implementation.onPictureInPictureChange { + return bridge.create_std__optional_std__function_void_bool____isInPictureInPicture______({ () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(__unwrappedValue) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.onPictureInPictureChange = { () -> ((_ isInPictureInPicture: Bool) -> Void)? in + if bridge.has_value_std__optional_std__function_void_bool____isInPictureInPicture______(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void_bool____isInPictureInPicture______(newValue) + return { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(__unwrapped) + return { (__isInPictureInPicture: Bool) -> Void in + __wrappedFunction.call(__isInPictureInPicture) + } + }() + } else { + return nil + } + }() + } + } + + public final var onFullscreenChange: bridge.std__optional_std__function_void_bool____fullscreen______ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void_bool____fullscreen______ in + if let __unwrappedValue = self.__implementation.onFullscreenChange { + return bridge.create_std__optional_std__function_void_bool____fullscreen______({ () -> bridge.Func_void_bool in + let __closureWrapper = Func_void_bool(__unwrappedValue) + return bridge.create_Func_void_bool(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.onFullscreenChange = { () -> ((_ fullscreen: Bool) -> Void)? in + if bridge.has_value_std__optional_std__function_void_bool____fullscreen______(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void_bool____fullscreen______(newValue) + return { () -> (Bool) -> Void in + let __wrappedFunction = bridge.wrap_Func_void_bool(__unwrapped) + return { (__fullscreen: Bool) -> Void in + __wrappedFunction.call(__fullscreen) + } + }() + } else { + return nil + } + }() + } + } + + public final var willEnterFullscreen: bridge.std__optional_std__function_void____ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void____ in + if let __unwrappedValue = self.__implementation.willEnterFullscreen { + return bridge.create_std__optional_std__function_void____({ () -> bridge.Func_void in + let __closureWrapper = Func_void(__unwrappedValue) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.willEnterFullscreen = { () -> (() -> Void)? in + if bridge.has_value_std__optional_std__function_void____(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void____(newValue) + return { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(__unwrapped) + return { () -> Void in + __wrappedFunction.call() + } + }() + } else { + return nil + } + }() + } + } + + public final var willExitFullscreen: bridge.std__optional_std__function_void____ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void____ in + if let __unwrappedValue = self.__implementation.willExitFullscreen { + return bridge.create_std__optional_std__function_void____({ () -> bridge.Func_void in + let __closureWrapper = Func_void(__unwrappedValue) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.willExitFullscreen = { () -> (() -> Void)? in + if bridge.has_value_std__optional_std__function_void____(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void____(newValue) + return { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(__unwrapped) + return { () -> Void in + __wrappedFunction.call() + } + }() + } else { + return nil + } + }() + } + } + + public final var willEnterPictureInPicture: bridge.std__optional_std__function_void____ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void____ in + if let __unwrappedValue = self.__implementation.willEnterPictureInPicture { + return bridge.create_std__optional_std__function_void____({ () -> bridge.Func_void in + let __closureWrapper = Func_void(__unwrappedValue) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.willEnterPictureInPicture = { () -> (() -> Void)? in + if bridge.has_value_std__optional_std__function_void____(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void____(newValue) + return { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(__unwrapped) + return { () -> Void in + __wrappedFunction.call() + } + }() + } else { + return nil + } + }() + } + } + + public final var willExitPictureInPicture: bridge.std__optional_std__function_void____ { + @inline(__always) + get { + return { () -> bridge.std__optional_std__function_void____ in + if let __unwrappedValue = self.__implementation.willExitPictureInPicture { + return bridge.create_std__optional_std__function_void____({ () -> bridge.Func_void in + let __closureWrapper = Func_void(__unwrappedValue) + return bridge.create_Func_void(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + @inline(__always) + set { + self.__implementation.willExitPictureInPicture = { () -> (() -> Void)? in + if bridge.has_value_std__optional_std__function_void____(newValue) { + let __unwrapped = bridge.get_std__optional_std__function_void____(newValue) + return { () -> () -> Void in + let __wrappedFunction = bridge.wrap_Func_void(__unwrapped) + return { () -> Void in + __wrappedFunction.call() + } + }() + } else { + return nil + } + }() + } + } + + // Methods + @inline(__always) + public final func enterFullscreen() -> bridge.Result_void_ { + do { + try self.__implementation.enterFullscreen() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func exitFullscreen() -> bridge.Result_void_ { + do { + try self.__implementation.exitFullscreen() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func enterPictureInPicture() -> bridge.Result_void_ { + do { + try self.__implementation.enterPictureInPicture() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func exitPictureInPicture() -> bridge.Result_void_ { + do { + try self.__implementation.exitPictureInPicture() + return bridge.create_Result_void_() + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_void_(__exceptionPtr) + } + } + + @inline(__always) + public final func canEnterPictureInPicture() -> bridge.Result_bool_ { + do { + let __result = try self.__implementation.canEnterPictureInPicture() + let __resultCpp = __result + return bridge.create_Result_bool_(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_bool_(__exceptionPtr) + } + } +} diff --git a/nitrogen/generated/ios/swift/IgnoreSilentSwitchMode.swift b/nitrogen/generated/ios/swift/IgnoreSilentSwitchMode.swift new file mode 100644 index 00000000..ed8d01e3 --- /dev/null +++ b/nitrogen/generated/ios/swift/IgnoreSilentSwitchMode.swift @@ -0,0 +1,44 @@ +/// +/// IgnoreSilentSwitchMode.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `IgnoreSilentSwitchMode`, backed by a C++ enum. + */ +public typealias IgnoreSilentSwitchMode = margelo.nitro.video.IgnoreSilentSwitchMode + +public extension IgnoreSilentSwitchMode { + /** + * Get a IgnoreSilentSwitchMode for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "auto": + self = .auto + case "ignore": + self = .ignore + case "obey": + self = .obey + default: + return nil + } + } + + /** + * Get the String value this IgnoreSilentSwitchMode represents. + */ + var stringValue: String { + switch self { + case .auto: + return "auto" + case .ignore: + return "ignore" + case .obey: + return "obey" + } + } +} diff --git a/nitrogen/generated/ios/swift/LivePlaybackParams.swift b/nitrogen/generated/ios/swift/LivePlaybackParams.swift new file mode 100644 index 00000000..3390dd71 --- /dev/null +++ b/nitrogen/generated/ios/swift/LivePlaybackParams.swift @@ -0,0 +1,139 @@ +/// +/// LivePlaybackParams.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `LivePlaybackParams`, backed by a C++ struct. + */ +public typealias LivePlaybackParams = margelo.nitro.video.LivePlaybackParams + +public extension LivePlaybackParams { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `LivePlaybackParams`. + */ + init(minPlaybackSpeed: Double?, maxPlaybackSpeed: Double?, maxOffsetMs: Double?, minOffsetMs: Double?, targetOffsetMs: Double?) { + self.init({ () -> bridge.std__optional_double_ in + if let __unwrappedValue = minPlaybackSpeed { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = maxPlaybackSpeed { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = maxOffsetMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = minOffsetMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_double_ in + if let __unwrappedValue = targetOffsetMs { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var minPlaybackSpeed: Double? { + @inline(__always) + get { + return self.__minPlaybackSpeed.value + } + @inline(__always) + set { + self.__minPlaybackSpeed = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var maxPlaybackSpeed: Double? { + @inline(__always) + get { + return self.__maxPlaybackSpeed.value + } + @inline(__always) + set { + self.__maxPlaybackSpeed = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var maxOffsetMs: Double? { + @inline(__always) + get { + return self.__maxOffsetMs.value + } + @inline(__always) + set { + self.__maxOffsetMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var minOffsetMs: Double? { + @inline(__always) + get { + return self.__minOffsetMs.value + } + @inline(__always) + set { + self.__minOffsetMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var targetOffsetMs: Double? { + @inline(__always) + get { + return self.__targetOffsetMs.value + } + @inline(__always) + set { + self.__targetOffsetMs = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/MixAudioMode.swift b/nitrogen/generated/ios/swift/MixAudioMode.swift new file mode 100644 index 00000000..425330b9 --- /dev/null +++ b/nitrogen/generated/ios/swift/MixAudioMode.swift @@ -0,0 +1,48 @@ +/// +/// MixAudioMode.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `MixAudioMode`, backed by a C++ enum. + */ +public typealias MixAudioMode = margelo.nitro.video.MixAudioMode + +public extension MixAudioMode { + /** + * Get a MixAudioMode for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "mixWithOthers": + self = .mixwithothers + case "doNotMix": + self = .donotmix + case "duckOthers": + self = .duckothers + case "auto": + self = .auto + default: + return nil + } + } + + /** + * Get the String value this MixAudioMode represents. + */ + var stringValue: String { + switch self { + case .mixwithothers: + return "mixWithOthers" + case .donotmix: + return "doNotMix" + case .duckothers: + return "duckOthers" + case .auto: + return "auto" + } + } +} diff --git a/nitrogen/generated/ios/swift/NativeDrmParams.swift b/nitrogen/generated/ios/swift/NativeDrmParams.swift new file mode 100644 index 00000000..ceaa4bb3 --- /dev/null +++ b/nitrogen/generated/ios/swift/NativeDrmParams.swift @@ -0,0 +1,279 @@ +/// +/// NativeDrmParams.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `NativeDrmParams`, backed by a C++ struct. + */ +public typealias NativeDrmParams = margelo.nitro.video.NativeDrmParams + +public extension NativeDrmParams { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `NativeDrmParams`. + */ + init(type: String?, licenseUrl: String?, certificateUrl: String?, contentId: String?, licenseHeaders: Dictionary?, multiSession: Bool?, getLicense: ((_ payload: OnGetLicensePayload) -> Promise>)?) { + self.init({ () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = type { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = licenseUrl { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = certificateUrl { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = contentId { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in + if let __unwrappedValue = licenseHeaders { + return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in + var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v)) + } + return __map + }()) + } else { + return .init() + } + }(), { () -> bridge.std__optional_bool_ in + if let __unwrappedValue = multiSession { + return bridge.create_std__optional_bool_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ in + if let __unwrappedValue = getLicense { + return bridge.create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______({ () -> bridge.Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload in + let __closureWrapper = Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrappedValue) + return bridge.create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }()) + } + + var type: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__type) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__type) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__type = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var licenseUrl: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__licenseUrl) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__licenseUrl) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__licenseUrl = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var certificateUrl: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__certificateUrl) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__certificateUrl) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__certificateUrl = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var contentId: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__contentId) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__contentId) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__contentId = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var licenseHeaders: Dictionary? { + @inline(__always) + get { + return { () -> Dictionary? in + if bridge.has_value_std__optional_std__unordered_map_std__string__std__string__(self.__licenseHeaders) { + let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__std__string__(self.__licenseHeaders) + return { () -> Dictionary in + var __dictionary = Dictionary(minimumCapacity: __unwrapped.size()) + let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped) + for __key in __keys { + let __value = bridge.get_std__unordered_map_std__string__std__string__value(__unwrapped, __key) + __dictionary[String(__key)] = String(__value) + } + return __dictionary + }() + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__licenseHeaders = { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in + var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v)) + } + return __map + }()) + } else { + return .init() + } + }() + } + } + + var multiSession: Bool? { + @inline(__always) + get { + return self.__multiSession.value + } + @inline(__always) + set { + self.__multiSession = { () -> bridge.std__optional_bool_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_bool_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var getLicense: ((_ payload: OnGetLicensePayload) -> Promise>)? { + @inline(__always) + get { + return { () -> ((_ payload: OnGetLicensePayload) -> Promise>)? in + if bridge.has_value_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(self.__getLicense) { + let __unwrapped = bridge.get_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(self.__getLicense) + return { () -> (OnGetLicensePayload) -> Promise> in + let __wrappedFunction = bridge.wrap_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrapped) + return { (__payload: OnGetLicensePayload) -> Promise> in + let __result = __wrappedFunction.call(__payload) + return { () -> Promise> in + let __promise = Promise>() + let __resolver = { (__result: Promise) in + __promise.resolve(withResult: __result) + } + let __rejecter = { (__error: Error) in + __promise.reject(withError: __error) + } + let __resolverCpp = { () -> bridge.Func_void_std__shared_ptr_Promise_std__string__ in + let __closureWrapper = Func_void_std__shared_ptr_Promise_std__string__(__resolver) + return bridge.create_Func_void_std__shared_ptr_Promise_std__string__(__closureWrapper.toUnsafe()) + }() + let __rejecterCpp = { () -> bridge.Func_void_std__exception_ptr in + let __closureWrapper = Func_void_std__exception_ptr(__rejecter) + return bridge.create_Func_void_std__exception_ptr(__closureWrapper.toUnsafe()) + }() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(__result) + __promiseHolder.addOnResolvedListener(__resolverCpp) + __promiseHolder.addOnRejectedListener(__rejecterCpp) + return __promise + }() + } + }() + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__getLicense = { () -> bridge.std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______({ () -> bridge.Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload in + let __closureWrapper = Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrappedValue) + return bridge.create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__closureWrapper.toUnsafe()) + }()) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/NativeExternalSubtitle.swift b/nitrogen/generated/ios/swift/NativeExternalSubtitle.swift new file mode 100644 index 00000000..472a8ddb --- /dev/null +++ b/nitrogen/generated/ios/swift/NativeExternalSubtitle.swift @@ -0,0 +1,68 @@ +/// +/// NativeExternalSubtitle.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `NativeExternalSubtitle`, backed by a C++ struct. + */ +public typealias NativeExternalSubtitle = margelo.nitro.video.NativeExternalSubtitle + +public extension NativeExternalSubtitle { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `NativeExternalSubtitle`. + */ + init(uri: String, label: String, type: SubtitleType, language: String) { + self.init(std.string(uri), std.string(label), type, std.string(language)) + } + + var uri: String { + @inline(__always) + get { + return String(self.__uri) + } + @inline(__always) + set { + self.__uri = std.string(newValue) + } + } + + var label: String { + @inline(__always) + get { + return String(self.__label) + } + @inline(__always) + set { + self.__label = std.string(newValue) + } + } + + var type: SubtitleType { + @inline(__always) + get { + return self.__type + } + @inline(__always) + set { + self.__type = newValue + } + } + + var language: String { + @inline(__always) + get { + return String(self.__language) + } + @inline(__always) + set { + self.__language = std.string(newValue) + } + } +} diff --git a/nitrogen/generated/ios/swift/NativeVideoConfig.swift b/nitrogen/generated/ios/swift/NativeVideoConfig.swift new file mode 100644 index 00000000..0c9d6138 --- /dev/null +++ b/nitrogen/generated/ios/swift/NativeVideoConfig.swift @@ -0,0 +1,221 @@ +/// +/// NativeVideoConfig.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `NativeVideoConfig`, backed by a C++ struct. + */ +public typealias NativeVideoConfig = margelo.nitro.video.NativeVideoConfig + +public extension NativeVideoConfig { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `NativeVideoConfig`. + */ + init(uri: String, externalSubtitles: [NativeExternalSubtitle]?, drm: NativeDrmParams?, headers: Dictionary?, bufferConfig: BufferConfig?, metadata: CustomVideoMetadata?, initializeOnCreation: Bool?) { + self.init(std.string(uri), { () -> bridge.std__optional_std__vector_NativeExternalSubtitle__ in + if let __unwrappedValue = externalSubtitles { + return bridge.create_std__optional_std__vector_NativeExternalSubtitle__(__unwrappedValue.withUnsafeBufferPointer { __pointer -> bridge.std__vector_NativeExternalSubtitle_ in + return bridge.copy_std__vector_NativeExternalSubtitle_(__pointer.baseAddress!, __unwrappedValue.count) + }) + } else { + return .init() + } + }(), { () -> bridge.std__optional_NativeDrmParams_ in + if let __unwrappedValue = drm { + return bridge.create_std__optional_NativeDrmParams_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in + if let __unwrappedValue = headers { + return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in + var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v)) + } + return __map + }()) + } else { + return .init() + } + }(), { () -> bridge.std__optional_BufferConfig_ in + if let __unwrappedValue = bufferConfig { + return bridge.create_std__optional_BufferConfig_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_CustomVideoMetadata_ in + if let __unwrappedValue = metadata { + return bridge.create_std__optional_CustomVideoMetadata_(__unwrappedValue) + } else { + return .init() + } + }(), { () -> bridge.std__optional_bool_ in + if let __unwrappedValue = initializeOnCreation { + return bridge.create_std__optional_bool_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var uri: String { + @inline(__always) + get { + return String(self.__uri) + } + @inline(__always) + set { + self.__uri = std.string(newValue) + } + } + + var externalSubtitles: [NativeExternalSubtitle]? { + @inline(__always) + get { + return { () -> [NativeExternalSubtitle]? in + if bridge.has_value_std__optional_std__vector_NativeExternalSubtitle__(self.__externalSubtitles) { + let __unwrapped = bridge.get_std__optional_std__vector_NativeExternalSubtitle__(self.__externalSubtitles) + return { () -> [NativeExternalSubtitle] in + let __data = bridge.get_data_std__vector_NativeExternalSubtitle_(__unwrapped) + let __size = __unwrapped.size() + return Array(UnsafeBufferPointer(start: __data, count: __size)) + }() + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__externalSubtitles = { () -> bridge.std__optional_std__vector_NativeExternalSubtitle__ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__vector_NativeExternalSubtitle__(__unwrappedValue.withUnsafeBufferPointer { __pointer -> bridge.std__vector_NativeExternalSubtitle_ in + return bridge.copy_std__vector_NativeExternalSubtitle_(__pointer.baseAddress!, __unwrappedValue.count) + }) + } else { + return .init() + } + }() + } + } + + var drm: NativeDrmParams? { + @inline(__always) + get { + return self.__drm.value + } + @inline(__always) + set { + self.__drm = { () -> bridge.std__optional_NativeDrmParams_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_NativeDrmParams_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var headers: Dictionary? { + @inline(__always) + get { + return { () -> Dictionary? in + if bridge.has_value_std__optional_std__unordered_map_std__string__std__string__(self.__headers) { + let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__std__string__(self.__headers) + return { () -> Dictionary in + var __dictionary = Dictionary(minimumCapacity: __unwrapped.size()) + let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped) + for __key in __keys { + let __value = bridge.get_std__unordered_map_std__string__std__string__value(__unwrapped, __key) + __dictionary[String(__key)] = String(__value) + } + return __dictionary + }() + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__headers = { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in + var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count) + for (__k, __v) in __unwrappedValue { + bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v)) + } + return __map + }()) + } else { + return .init() + } + }() + } + } + + var bufferConfig: BufferConfig? { + @inline(__always) + get { + return self.__bufferConfig.value + } + @inline(__always) + set { + self.__bufferConfig = { () -> bridge.std__optional_BufferConfig_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_BufferConfig_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var metadata: CustomVideoMetadata? { + @inline(__always) + get { + return { () -> CustomVideoMetadata? in + if let __unwrapped = self.__metadata.value { + return __unwrapped + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__metadata = { () -> bridge.std__optional_CustomVideoMetadata_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_CustomVideoMetadata_(__unwrappedValue) + } else { + return .init() + } + }() + } + } + + var initializeOnCreation: Bool? { + @inline(__always) + get { + return self.__initializeOnCreation.value + } + @inline(__always) + set { + self.__initializeOnCreation = { () -> bridge.std__optional_bool_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_bool_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/OnGetLicensePayload.swift b/nitrogen/generated/ios/swift/OnGetLicensePayload.swift new file mode 100644 index 00000000..f7a8e345 --- /dev/null +++ b/nitrogen/generated/ios/swift/OnGetLicensePayload.swift @@ -0,0 +1,68 @@ +/// +/// OnGetLicensePayload.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `OnGetLicensePayload`, backed by a C++ struct. + */ +public typealias OnGetLicensePayload = margelo.nitro.video.OnGetLicensePayload + +public extension OnGetLicensePayload { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `OnGetLicensePayload`. + */ + init(contentId: String, licenseUrl: String, keyUrl: String, spc: String) { + self.init(std.string(contentId), std.string(licenseUrl), std.string(keyUrl), std.string(spc)) + } + + var contentId: String { + @inline(__always) + get { + return String(self.__contentId) + } + @inline(__always) + set { + self.__contentId = std.string(newValue) + } + } + + var licenseUrl: String { + @inline(__always) + get { + return String(self.__licenseUrl) + } + @inline(__always) + set { + self.__licenseUrl = std.string(newValue) + } + } + + var keyUrl: String { + @inline(__always) + get { + return String(self.__keyUrl) + } + @inline(__always) + set { + self.__keyUrl = std.string(newValue) + } + } + + var spc: String { + @inline(__always) + get { + return String(self.__spc) + } + @inline(__always) + set { + self.__spc = std.string(newValue) + } + } +} diff --git a/nitrogen/generated/ios/swift/ResizeMode.swift b/nitrogen/generated/ios/swift/ResizeMode.swift new file mode 100644 index 00000000..c596c061 --- /dev/null +++ b/nitrogen/generated/ios/swift/ResizeMode.swift @@ -0,0 +1,48 @@ +/// +/// ResizeMode.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `ResizeMode`, backed by a C++ enum. + */ +public typealias ResizeMode = margelo.nitro.video.ResizeMode + +public extension ResizeMode { + /** + * Get a ResizeMode for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "contain": + self = .contain + case "cover": + self = .cover + case "stretch": + self = .stretch + case "none": + self = .none + default: + return nil + } + } + + /** + * Get the String value this ResizeMode represents. + */ + var stringValue: String { + switch self { + case .contain: + return "contain" + case .cover: + return "cover" + case .stretch: + return "stretch" + case .none: + return "none" + } + } +} diff --git a/nitrogen/generated/ios/swift/Resolution.swift b/nitrogen/generated/ios/swift/Resolution.swift new file mode 100644 index 00000000..3b85fa07 --- /dev/null +++ b/nitrogen/generated/ios/swift/Resolution.swift @@ -0,0 +1,46 @@ +/// +/// Resolution.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `Resolution`, backed by a C++ struct. + */ +public typealias Resolution = margelo.nitro.video.Resolution + +public extension Resolution { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `Resolution`. + */ + init(width: Double, height: Double) { + self.init(width, height) + } + + var width: Double { + @inline(__always) + get { + return self.__width + } + @inline(__always) + set { + self.__width = newValue + } + } + + var height: Double { + @inline(__always) + get { + return self.__height + } + @inline(__always) + set { + self.__height = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/SourceType.swift b/nitrogen/generated/ios/swift/SourceType.swift new file mode 100644 index 00000000..4ebe3cb8 --- /dev/null +++ b/nitrogen/generated/ios/swift/SourceType.swift @@ -0,0 +1,40 @@ +/// +/// SourceType.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `SourceType`, backed by a C++ enum. + */ +public typealias SourceType = margelo.nitro.video.SourceType + +public extension SourceType { + /** + * Get a SourceType for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "local": + self = .local + case "network": + self = .network + default: + return nil + } + } + + /** + * Get the String value this SourceType represents. + */ + var stringValue: String { + switch self { + case .local: + return "local" + case .network: + return "network" + } + } +} diff --git a/nitrogen/generated/ios/swift/SubtitleType.swift b/nitrogen/generated/ios/swift/SubtitleType.swift new file mode 100644 index 00000000..2e0eb2f6 --- /dev/null +++ b/nitrogen/generated/ios/swift/SubtitleType.swift @@ -0,0 +1,52 @@ +/// +/// SubtitleType.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `SubtitleType`, backed by a C++ enum. + */ +public typealias SubtitleType = margelo.nitro.video.SubtitleType + +public extension SubtitleType { + /** + * Get a SubtitleType for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "auto": + self = .auto + case "vtt": + self = .vtt + case "srt": + self = .srt + case "ssa": + self = .ssa + case "ass": + self = .ass + default: + return nil + } + } + + /** + * Get the String value this SubtitleType represents. + */ + var stringValue: String { + switch self { + case .auto: + return "auto" + case .vtt: + return "vtt" + case .srt: + return "srt" + case .ssa: + return "ssa" + case .ass: + return "ass" + } + } +} diff --git a/nitrogen/generated/ios/swift/SurfaceType.swift b/nitrogen/generated/ios/swift/SurfaceType.swift new file mode 100644 index 00000000..49de04f3 --- /dev/null +++ b/nitrogen/generated/ios/swift/SurfaceType.swift @@ -0,0 +1,40 @@ +/// +/// SurfaceType.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `SurfaceType`, backed by a C++ enum. + */ +public typealias SurfaceType = margelo.nitro.video.SurfaceType + +public extension SurfaceType { + /** + * Get a SurfaceType for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "surface": + self = .surface + case "texture": + self = .texture + default: + return nil + } + } + + /** + * Get the String value this SurfaceType represents. + */ + var stringValue: String { + switch self { + case .surface: + return "surface" + case .texture: + return "texture" + } + } +} diff --git a/nitrogen/generated/ios/swift/TextTrack.swift b/nitrogen/generated/ios/swift/TextTrack.swift new file mode 100644 index 00000000..f582412f --- /dev/null +++ b/nitrogen/generated/ios/swift/TextTrack.swift @@ -0,0 +1,87 @@ +/// +/// TextTrack.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `TextTrack`, backed by a C++ struct. + */ +public typealias TextTrack = margelo.nitro.video.TextTrack + +public extension TextTrack { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `TextTrack`. + */ + init(id: String, label: String, language: String?, selected: Bool) { + self.init(std.string(id), std.string(label), { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = language { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }(), selected) + } + + var id: String { + @inline(__always) + get { + return String(self.__id) + } + @inline(__always) + set { + self.__id = std.string(newValue) + } + } + + var label: String { + @inline(__always) + get { + return String(self.__label) + } + @inline(__always) + set { + self.__label = std.string(newValue) + } + } + + var language: String? { + @inline(__always) + get { + return { () -> String? in + if bridge.has_value_std__optional_std__string_(self.__language) { + let __unwrapped = bridge.get_std__optional_std__string_(self.__language) + return String(__unwrapped) + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__language = { () -> bridge.std__optional_std__string_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) + } else { + return .init() + } + }() + } + } + + var selected: Bool { + @inline(__always) + get { + return self.__selected + } + @inline(__always) + set { + self.__selected = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/TimedMetadata.swift b/nitrogen/generated/ios/swift/TimedMetadata.swift new file mode 100644 index 00000000..14641c38 --- /dev/null +++ b/nitrogen/generated/ios/swift/TimedMetadata.swift @@ -0,0 +1,43 @@ +/// +/// TimedMetadata.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `TimedMetadata`, backed by a C++ struct. + */ +public typealias TimedMetadata = margelo.nitro.video.TimedMetadata + +public extension TimedMetadata { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `TimedMetadata`. + */ + init(metadata: [TimedMetadataObject]) { + self.init(metadata.withUnsafeBufferPointer { __pointer -> bridge.std__vector_TimedMetadataObject_ in + return bridge.copy_std__vector_TimedMetadataObject_(__pointer.baseAddress!, metadata.count) + }) + } + + var metadata: [TimedMetadataObject] { + @inline(__always) + get { + return { () -> [TimedMetadataObject] in + let __data = bridge.get_data_std__vector_TimedMetadataObject_(self.__metadata) + let __size = self.__metadata.size() + return Array(UnsafeBufferPointer(start: __data, count: __size)) + }() + } + @inline(__always) + set { + self.__metadata = newValue.withUnsafeBufferPointer { __pointer -> bridge.std__vector_TimedMetadataObject_ in + return bridge.copy_std__vector_TimedMetadataObject_(__pointer.baseAddress!, newValue.count) + } + } + } +} diff --git a/nitrogen/generated/ios/swift/TimedMetadataObject.swift b/nitrogen/generated/ios/swift/TimedMetadataObject.swift new file mode 100644 index 00000000..70dcf655 --- /dev/null +++ b/nitrogen/generated/ios/swift/TimedMetadataObject.swift @@ -0,0 +1,46 @@ +/// +/// TimedMetadataObject.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `TimedMetadataObject`, backed by a C++ struct. + */ +public typealias TimedMetadataObject = margelo.nitro.video.TimedMetadataObject + +public extension TimedMetadataObject { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `TimedMetadataObject`. + */ + init(value: String, identifier: String) { + self.init(std.string(value), std.string(identifier)) + } + + var value: String { + @inline(__always) + get { + return String(self.__value) + } + @inline(__always) + set { + self.__value = std.string(newValue) + } + } + + var identifier: String { + @inline(__always) + get { + return String(self.__identifier) + } + @inline(__always) + set { + self.__identifier = std.string(newValue) + } + } +} diff --git a/nitrogen/generated/ios/swift/VideoInformation.swift b/nitrogen/generated/ios/swift/VideoInformation.swift new file mode 100644 index 00000000..0d01a50a --- /dev/null +++ b/nitrogen/generated/ios/swift/VideoInformation.swift @@ -0,0 +1,112 @@ +/// +/// VideoInformation.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `VideoInformation`, backed by a C++ struct. + */ +public typealias VideoInformation = margelo.nitro.video.VideoInformation + +public extension VideoInformation { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `VideoInformation`. + */ + init(bitrate: Double, width: Double, height: Double, duration: Int64, fileSize: Int64, isHDR: Bool, isLive: Bool, orientation: VideoOrientation) { + self.init(bitrate, width, height, duration, fileSize, isHDR, isLive, orientation) + } + + var bitrate: Double { + @inline(__always) + get { + return self.__bitrate + } + @inline(__always) + set { + self.__bitrate = newValue + } + } + + var width: Double { + @inline(__always) + get { + return self.__width + } + @inline(__always) + set { + self.__width = newValue + } + } + + var height: Double { + @inline(__always) + get { + return self.__height + } + @inline(__always) + set { + self.__height = newValue + } + } + + var duration: Int64 { + @inline(__always) + get { + return self.__duration + } + @inline(__always) + set { + self.__duration = newValue + } + } + + var fileSize: Int64 { + @inline(__always) + get { + return self.__fileSize + } + @inline(__always) + set { + self.__fileSize = newValue + } + } + + var isHDR: Bool { + @inline(__always) + get { + return self.__isHDR + } + @inline(__always) + set { + self.__isHDR = newValue + } + } + + var isLive: Bool { + @inline(__always) + get { + return self.__isLive + } + @inline(__always) + set { + self.__isLive = newValue + } + } + + var orientation: VideoOrientation { + @inline(__always) + get { + return self.__orientation + } + @inline(__always) + set { + self.__orientation = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/VideoOrientation.swift b/nitrogen/generated/ios/swift/VideoOrientation.swift new file mode 100644 index 00000000..f74ff262 --- /dev/null +++ b/nitrogen/generated/ios/swift/VideoOrientation.swift @@ -0,0 +1,60 @@ +/// +/// VideoOrientation.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `VideoOrientation`, backed by a C++ enum. + */ +public typealias VideoOrientation = margelo.nitro.video.VideoOrientation + +public extension VideoOrientation { + /** + * Get a VideoOrientation for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "portrait": + self = .portrait + case "landscape": + self = .landscape + case "portrait-upside-down": + self = .portraitUpsideDown + case "landscape-left": + self = .landscapeLeft + case "landscape-right": + self = .landscapeRight + case "square": + self = .square + case "unknown": + self = .unknown + default: + return nil + } + } + + /** + * Get the String value this VideoOrientation represents. + */ + var stringValue: String { + switch self { + case .portrait: + return "portrait" + case .landscape: + return "landscape" + case .portraitUpsideDown: + return "portrait-upside-down" + case .landscapeLeft: + return "landscape-left" + case .landscapeRight: + return "landscape-right" + case .square: + return "square" + case .unknown: + return "unknown" + } + } +} diff --git a/nitrogen/generated/ios/swift/VideoPlayerStatus.swift b/nitrogen/generated/ios/swift/VideoPlayerStatus.swift new file mode 100644 index 00000000..dae121cb --- /dev/null +++ b/nitrogen/generated/ios/swift/VideoPlayerStatus.swift @@ -0,0 +1,48 @@ +/// +/// VideoPlayerStatus.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `VideoPlayerStatus`, backed by a C++ enum. + */ +public typealias VideoPlayerStatus = margelo.nitro.video.VideoPlayerStatus + +public extension VideoPlayerStatus { + /** + * Get a VideoPlayerStatus for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "idle": + self = .idle + case "loading": + self = .loading + case "readyToPlay": + self = .readytoplay + case "error": + self = .error + default: + return nil + } + } + + /** + * Get the String value this VideoPlayerStatus represents. + */ + var stringValue: String { + switch self { + case .idle: + return "idle" + case .loading: + return "loading" + case .readytoplay: + return "readyToPlay" + case .error: + return "error" + } + } +} diff --git a/nitrogen/generated/ios/swift/onLoadData.swift b/nitrogen/generated/ios/swift/onLoadData.swift new file mode 100644 index 00000000..301d21d3 --- /dev/null +++ b/nitrogen/generated/ios/swift/onLoadData.swift @@ -0,0 +1,79 @@ +/// +/// onLoadData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `onLoadData`, backed by a C++ struct. + */ +public typealias onLoadData = margelo.nitro.video.onLoadData + +public extension onLoadData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `onLoadData`. + */ + init(currentTime: Double, duration: Double, height: Double, width: Double, orientation: VideoOrientation) { + self.init(currentTime, duration, height, width, orientation) + } + + var currentTime: Double { + @inline(__always) + get { + return self.__currentTime + } + @inline(__always) + set { + self.__currentTime = newValue + } + } + + var duration: Double { + @inline(__always) + get { + return self.__duration + } + @inline(__always) + set { + self.__duration = newValue + } + } + + var height: Double { + @inline(__always) + get { + return self.__height + } + @inline(__always) + set { + self.__height = newValue + } + } + + var width: Double { + @inline(__always) + get { + return self.__width + } + @inline(__always) + set { + self.__width = newValue + } + } + + var orientation: VideoOrientation { + @inline(__always) + get { + return self.__orientation + } + @inline(__always) + set { + self.__orientation = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/onLoadStartData.swift b/nitrogen/generated/ios/swift/onLoadStartData.swift new file mode 100644 index 00000000..e5a63cfc --- /dev/null +++ b/nitrogen/generated/ios/swift/onLoadStartData.swift @@ -0,0 +1,56 @@ +/// +/// onLoadStartData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `onLoadStartData`, backed by a C++ struct. + */ +public typealias onLoadStartData = margelo.nitro.video.onLoadStartData + +public extension onLoadStartData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `onLoadStartData`. + */ + init(sourceType: SourceType, source: (any HybridVideoPlayerSourceSpec)) { + self.init(sourceType, { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in + let __cxxWrapped = source.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }()) + } + + var sourceType: SourceType { + @inline(__always) + get { + return self.__sourceType + } + @inline(__always) + set { + self.__sourceType = newValue + } + } + + var source: (any HybridVideoPlayerSourceSpec) { + @inline(__always) + get { + return { () -> HybridVideoPlayerSourceSpec in + let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(self.__source) + let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer) + return __instance.getHybridVideoPlayerSourceSpec() + }() + } + @inline(__always) + set { + self.__source = { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in + let __cxxWrapped = newValue.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + } + } +} diff --git a/nitrogen/generated/ios/swift/onPlaybackStateChangeData.swift b/nitrogen/generated/ios/swift/onPlaybackStateChangeData.swift new file mode 100644 index 00000000..daa5601e --- /dev/null +++ b/nitrogen/generated/ios/swift/onPlaybackStateChangeData.swift @@ -0,0 +1,46 @@ +/// +/// onPlaybackStateChangeData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `onPlaybackStateChangeData`, backed by a C++ struct. + */ +public typealias onPlaybackStateChangeData = margelo.nitro.video.onPlaybackStateChangeData + +public extension onPlaybackStateChangeData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `onPlaybackStateChangeData`. + */ + init(isPlaying: Bool, isBuffering: Bool) { + self.init(isPlaying, isBuffering) + } + + var isPlaying: Bool { + @inline(__always) + get { + return self.__isPlaying + } + @inline(__always) + set { + self.__isPlaying = newValue + } + } + + var isBuffering: Bool { + @inline(__always) + get { + return self.__isBuffering + } + @inline(__always) + set { + self.__isBuffering = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/onProgressData.swift b/nitrogen/generated/ios/swift/onProgressData.swift new file mode 100644 index 00000000..9eda524d --- /dev/null +++ b/nitrogen/generated/ios/swift/onProgressData.swift @@ -0,0 +1,46 @@ +/// +/// onProgressData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `onProgressData`, backed by a C++ struct. + */ +public typealias onProgressData = margelo.nitro.video.onProgressData + +public extension onProgressData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `onProgressData`. + */ + init(currentTime: Double, bufferDuration: Double) { + self.init(currentTime, bufferDuration) + } + + var currentTime: Double { + @inline(__always) + get { + return self.__currentTime + } + @inline(__always) + set { + self.__currentTime = newValue + } + } + + var bufferDuration: Double { + @inline(__always) + get { + return self.__bufferDuration + } + @inline(__always) + set { + self.__bufferDuration = newValue + } + } +} diff --git a/nitrogen/generated/ios/swift/onVolumeChangeData.swift b/nitrogen/generated/ios/swift/onVolumeChangeData.swift new file mode 100644 index 00000000..ab9b5410 --- /dev/null +++ b/nitrogen/generated/ios/swift/onVolumeChangeData.swift @@ -0,0 +1,46 @@ +/// +/// onVolumeChangeData.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `onVolumeChangeData`, backed by a C++ struct. + */ +public typealias onVolumeChangeData = margelo.nitro.video.onVolumeChangeData + +public extension onVolumeChangeData { + private typealias bridge = margelo.nitro.video.bridge.swift + + /** + * Create a new instance of `onVolumeChangeData`. + */ + init(volume: Double, muted: Bool) { + self.init(volume, muted) + } + + var volume: Double { + @inline(__always) + get { + return self.__volume + } + @inline(__always) + set { + self.__volume = newValue + } + } + + var muted: Bool { + @inline(__always) + get { + return self.__muted + } + @inline(__always) + set { + self.__muted = newValue + } + } +} diff --git a/nitrogen/generated/shared/c++/BandwidthData.hpp b/nitrogen/generated/shared/c++/BandwidthData.hpp new file mode 100644 index 00000000..db1057d5 --- /dev/null +++ b/nitrogen/generated/shared/c++/BandwidthData.hpp @@ -0,0 +1,75 @@ +/// +/// BandwidthData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (BandwidthData). + */ + struct BandwidthData { + public: + double bitrate SWIFT_PRIVATE; + std::optional width SWIFT_PRIVATE; + std::optional height SWIFT_PRIVATE; + + public: + BandwidthData() = default; + explicit BandwidthData(double bitrate, std::optional width, std::optional height): bitrate(bitrate), width(width), height(height) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ BandwidthData <> JS BandwidthData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::BandwidthData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::BandwidthData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "bitrate")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "width")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "height")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::BandwidthData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "bitrate", JSIConverter::toJSI(runtime, arg.bitrate)); + obj.setProperty(runtime, "width", JSIConverter>::toJSI(runtime, arg.width)); + obj.setProperty(runtime, "height", JSIConverter>::toJSI(runtime, arg.height)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "bitrate"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/BufferConfig.hpp b/nitrogen/generated/shared/c++/BufferConfig.hpp new file mode 100644 index 00000000..c86d20b2 --- /dev/null +++ b/nitrogen/generated/shared/c++/BufferConfig.hpp @@ -0,0 +1,112 @@ +/// +/// BufferConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `LivePlaybackParams` to properly resolve imports. +namespace margelo::nitro::video { struct LivePlaybackParams; } +// Forward declaration of `Resolution` to properly resolve imports. +namespace margelo::nitro::video { struct Resolution; } + +#include "LivePlaybackParams.hpp" +#include +#include "Resolution.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (BufferConfig). + */ + struct BufferConfig { + public: + std::optional livePlayback SWIFT_PRIVATE; + std::optional minBufferMs SWIFT_PRIVATE; + std::optional maxBufferMs SWIFT_PRIVATE; + std::optional bufferForPlaybackMs SWIFT_PRIVATE; + std::optional bufferForPlaybackAfterRebufferMs SWIFT_PRIVATE; + std::optional backBufferDurationMs SWIFT_PRIVATE; + std::optional preferredForwardBufferDurationMs SWIFT_PRIVATE; + std::optional preferredPeakBitRate SWIFT_PRIVATE; + std::optional preferredMaximumResolution SWIFT_PRIVATE; + std::optional preferredPeakBitRateForExpensiveNetworks SWIFT_PRIVATE; + std::optional preferredMaximumResolutionForExpensiveNetworks SWIFT_PRIVATE; + + public: + BufferConfig() = default; + explicit BufferConfig(std::optional livePlayback, std::optional minBufferMs, std::optional maxBufferMs, std::optional bufferForPlaybackMs, std::optional bufferForPlaybackAfterRebufferMs, std::optional backBufferDurationMs, std::optional preferredForwardBufferDurationMs, std::optional preferredPeakBitRate, std::optional preferredMaximumResolution, std::optional preferredPeakBitRateForExpensiveNetworks, std::optional preferredMaximumResolutionForExpensiveNetworks): livePlayback(livePlayback), minBufferMs(minBufferMs), maxBufferMs(maxBufferMs), bufferForPlaybackMs(bufferForPlaybackMs), bufferForPlaybackAfterRebufferMs(bufferForPlaybackAfterRebufferMs), backBufferDurationMs(backBufferDurationMs), preferredForwardBufferDurationMs(preferredForwardBufferDurationMs), preferredPeakBitRate(preferredPeakBitRate), preferredMaximumResolution(preferredMaximumResolution), preferredPeakBitRateForExpensiveNetworks(preferredPeakBitRateForExpensiveNetworks), preferredMaximumResolutionForExpensiveNetworks(preferredMaximumResolutionForExpensiveNetworks) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ BufferConfig <> JS BufferConfig (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::BufferConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::BufferConfig( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "livePlayback")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "minBufferMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxBufferMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "bufferForPlaybackMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "bufferForPlaybackAfterRebufferMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "backBufferDurationMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preferredForwardBufferDurationMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preferredPeakBitRate")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preferredMaximumResolution")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preferredPeakBitRateForExpensiveNetworks")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preferredMaximumResolutionForExpensiveNetworks")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::BufferConfig& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "livePlayback", JSIConverter>::toJSI(runtime, arg.livePlayback)); + obj.setProperty(runtime, "minBufferMs", JSIConverter>::toJSI(runtime, arg.minBufferMs)); + obj.setProperty(runtime, "maxBufferMs", JSIConverter>::toJSI(runtime, arg.maxBufferMs)); + obj.setProperty(runtime, "bufferForPlaybackMs", JSIConverter>::toJSI(runtime, arg.bufferForPlaybackMs)); + obj.setProperty(runtime, "bufferForPlaybackAfterRebufferMs", JSIConverter>::toJSI(runtime, arg.bufferForPlaybackAfterRebufferMs)); + obj.setProperty(runtime, "backBufferDurationMs", JSIConverter>::toJSI(runtime, arg.backBufferDurationMs)); + obj.setProperty(runtime, "preferredForwardBufferDurationMs", JSIConverter>::toJSI(runtime, arg.preferredForwardBufferDurationMs)); + obj.setProperty(runtime, "preferredPeakBitRate", JSIConverter>::toJSI(runtime, arg.preferredPeakBitRate)); + obj.setProperty(runtime, "preferredMaximumResolution", JSIConverter>::toJSI(runtime, arg.preferredMaximumResolution)); + obj.setProperty(runtime, "preferredPeakBitRateForExpensiveNetworks", JSIConverter>::toJSI(runtime, arg.preferredPeakBitRateForExpensiveNetworks)); + obj.setProperty(runtime, "preferredMaximumResolutionForExpensiveNetworks", JSIConverter>::toJSI(runtime, arg.preferredMaximumResolutionForExpensiveNetworks)); + 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 (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "livePlayback"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "minBufferMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxBufferMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "bufferForPlaybackMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "bufferForPlaybackAfterRebufferMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "backBufferDurationMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preferredForwardBufferDurationMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preferredPeakBitRate"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preferredMaximumResolution"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preferredPeakBitRateForExpensiveNetworks"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preferredMaximumResolutionForExpensiveNetworks"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp b/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp new file mode 100644 index 00000000..8f977006 --- /dev/null +++ b/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp @@ -0,0 +1,84 @@ +/// +/// CustomVideoMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (CustomVideoMetadata). + */ + struct CustomVideoMetadata { + public: + std::optional title SWIFT_PRIVATE; + std::optional subtitle SWIFT_PRIVATE; + std::optional description SWIFT_PRIVATE; + std::optional artist SWIFT_PRIVATE; + std::optional imageUri SWIFT_PRIVATE; + + public: + CustomVideoMetadata() = default; + explicit CustomVideoMetadata(std::optional title, std::optional subtitle, std::optional description, std::optional artist, std::optional imageUri): title(title), subtitle(subtitle), description(description), artist(artist), imageUri(imageUri) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ CustomVideoMetadata <> JS CustomVideoMetadata (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::CustomVideoMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::CustomVideoMetadata( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "title")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "subtitle")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "description")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "artist")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "imageUri")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::CustomVideoMetadata& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "title", JSIConverter>::toJSI(runtime, arg.title)); + obj.setProperty(runtime, "subtitle", JSIConverter>::toJSI(runtime, arg.subtitle)); + obj.setProperty(runtime, "description", JSIConverter>::toJSI(runtime, arg.description)); + obj.setProperty(runtime, "artist", JSIConverter>::toJSI(runtime, arg.artist)); + obj.setProperty(runtime, "imageUri", JSIConverter>::toJSI(runtime, arg.imageUri)); + 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 (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "title"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "subtitle"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "description"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "artist"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "imageUri"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp b/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp new file mode 100644 index 00000000..09a17aa1 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp @@ -0,0 +1,58 @@ +/// +/// HybridVideoPlayerEventEmitterSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerEventEmitterSpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoPlayerEventEmitterSpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridGetter("onAudioBecomingNoisy", &HybridVideoPlayerEventEmitterSpec::getOnAudioBecomingNoisy); + prototype.registerHybridSetter("onAudioBecomingNoisy", &HybridVideoPlayerEventEmitterSpec::setOnAudioBecomingNoisy); + prototype.registerHybridGetter("onAudioFocusChange", &HybridVideoPlayerEventEmitterSpec::getOnAudioFocusChange); + prototype.registerHybridSetter("onAudioFocusChange", &HybridVideoPlayerEventEmitterSpec::setOnAudioFocusChange); + prototype.registerHybridGetter("onBandwidthUpdate", &HybridVideoPlayerEventEmitterSpec::getOnBandwidthUpdate); + prototype.registerHybridSetter("onBandwidthUpdate", &HybridVideoPlayerEventEmitterSpec::setOnBandwidthUpdate); + prototype.registerHybridGetter("onBuffer", &HybridVideoPlayerEventEmitterSpec::getOnBuffer); + prototype.registerHybridSetter("onBuffer", &HybridVideoPlayerEventEmitterSpec::setOnBuffer); + prototype.registerHybridGetter("onControlsVisibleChange", &HybridVideoPlayerEventEmitterSpec::getOnControlsVisibleChange); + prototype.registerHybridSetter("onControlsVisibleChange", &HybridVideoPlayerEventEmitterSpec::setOnControlsVisibleChange); + prototype.registerHybridGetter("onEnd", &HybridVideoPlayerEventEmitterSpec::getOnEnd); + prototype.registerHybridSetter("onEnd", &HybridVideoPlayerEventEmitterSpec::setOnEnd); + prototype.registerHybridGetter("onExternalPlaybackChange", &HybridVideoPlayerEventEmitterSpec::getOnExternalPlaybackChange); + prototype.registerHybridSetter("onExternalPlaybackChange", &HybridVideoPlayerEventEmitterSpec::setOnExternalPlaybackChange); + prototype.registerHybridGetter("onLoad", &HybridVideoPlayerEventEmitterSpec::getOnLoad); + prototype.registerHybridSetter("onLoad", &HybridVideoPlayerEventEmitterSpec::setOnLoad); + prototype.registerHybridGetter("onLoadStart", &HybridVideoPlayerEventEmitterSpec::getOnLoadStart); + prototype.registerHybridSetter("onLoadStart", &HybridVideoPlayerEventEmitterSpec::setOnLoadStart); + prototype.registerHybridGetter("onPlaybackStateChange", &HybridVideoPlayerEventEmitterSpec::getOnPlaybackStateChange); + prototype.registerHybridSetter("onPlaybackStateChange", &HybridVideoPlayerEventEmitterSpec::setOnPlaybackStateChange); + prototype.registerHybridGetter("onPlaybackRateChange", &HybridVideoPlayerEventEmitterSpec::getOnPlaybackRateChange); + prototype.registerHybridSetter("onPlaybackRateChange", &HybridVideoPlayerEventEmitterSpec::setOnPlaybackRateChange); + prototype.registerHybridGetter("onProgress", &HybridVideoPlayerEventEmitterSpec::getOnProgress); + prototype.registerHybridSetter("onProgress", &HybridVideoPlayerEventEmitterSpec::setOnProgress); + prototype.registerHybridGetter("onReadyToDisplay", &HybridVideoPlayerEventEmitterSpec::getOnReadyToDisplay); + prototype.registerHybridSetter("onReadyToDisplay", &HybridVideoPlayerEventEmitterSpec::setOnReadyToDisplay); + prototype.registerHybridGetter("onSeek", &HybridVideoPlayerEventEmitterSpec::getOnSeek); + prototype.registerHybridSetter("onSeek", &HybridVideoPlayerEventEmitterSpec::setOnSeek); + prototype.registerHybridGetter("onTimedMetadata", &HybridVideoPlayerEventEmitterSpec::getOnTimedMetadata); + prototype.registerHybridSetter("onTimedMetadata", &HybridVideoPlayerEventEmitterSpec::setOnTimedMetadata); + prototype.registerHybridGetter("onTextTrackDataChanged", &HybridVideoPlayerEventEmitterSpec::getOnTextTrackDataChanged); + prototype.registerHybridSetter("onTextTrackDataChanged", &HybridVideoPlayerEventEmitterSpec::setOnTextTrackDataChanged); + prototype.registerHybridGetter("onTrackChange", &HybridVideoPlayerEventEmitterSpec::getOnTrackChange); + prototype.registerHybridSetter("onTrackChange", &HybridVideoPlayerEventEmitterSpec::setOnTrackChange); + prototype.registerHybridGetter("onVolumeChange", &HybridVideoPlayerEventEmitterSpec::getOnVolumeChange); + prototype.registerHybridSetter("onVolumeChange", &HybridVideoPlayerEventEmitterSpec::setOnVolumeChange); + prototype.registerHybridGetter("onStatusChange", &HybridVideoPlayerEventEmitterSpec::getOnStatusChange); + prototype.registerHybridSetter("onStatusChange", &HybridVideoPlayerEventEmitterSpec::setOnStatusChange); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.hpp b/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.hpp new file mode 100644 index 00000000..d5fac00b --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.hpp @@ -0,0 +1,128 @@ +/// +/// HybridVideoPlayerEventEmitterSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `BandwidthData` to properly resolve imports. +namespace margelo::nitro::video { struct BandwidthData; } +// Forward declaration of `onLoadData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadData; } +// Forward declaration of `onLoadStartData` to properly resolve imports. +namespace margelo::nitro::video { struct onLoadStartData; } +// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onPlaybackStateChangeData; } +// Forward declaration of `onProgressData` to properly resolve imports. +namespace margelo::nitro::video { struct onProgressData; } +// Forward declaration of `TimedMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadata; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } +// Forward declaration of `onVolumeChangeData` to properly resolve imports. +namespace margelo::nitro::video { struct onVolumeChangeData; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } + +#include +#include "BandwidthData.hpp" +#include "onLoadData.hpp" +#include "onLoadStartData.hpp" +#include "onPlaybackStateChangeData.hpp" +#include "onProgressData.hpp" +#include "TimedMetadata.hpp" +#include +#include +#include "TextTrack.hpp" +#include +#include "onVolumeChangeData.hpp" +#include "VideoPlayerStatus.hpp" + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoPlayerEventEmitter` + * Inherit this class to create instances of `HybridVideoPlayerEventEmitterSpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoPlayerEventEmitter: public HybridVideoPlayerEventEmitterSpec { + * public: + * HybridVideoPlayerEventEmitter(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoPlayerEventEmitterSpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoPlayerEventEmitterSpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoPlayerEventEmitterSpec() override = default; + + public: + // Properties + virtual std::function getOnAudioBecomingNoisy() = 0; + virtual void setOnAudioBecomingNoisy(const std::function& onAudioBecomingNoisy) = 0; + virtual std::function getOnAudioFocusChange() = 0; + virtual void setOnAudioFocusChange(const std::function& onAudioFocusChange) = 0; + virtual std::function getOnBandwidthUpdate() = 0; + virtual void setOnBandwidthUpdate(const std::function& onBandwidthUpdate) = 0; + virtual std::function getOnBuffer() = 0; + virtual void setOnBuffer(const std::function& onBuffer) = 0; + virtual std::function getOnControlsVisibleChange() = 0; + virtual void setOnControlsVisibleChange(const std::function& onControlsVisibleChange) = 0; + virtual std::function getOnEnd() = 0; + virtual void setOnEnd(const std::function& onEnd) = 0; + virtual std::function getOnExternalPlaybackChange() = 0; + virtual void setOnExternalPlaybackChange(const std::function& onExternalPlaybackChange) = 0; + virtual std::function getOnLoad() = 0; + virtual void setOnLoad(const std::function& onLoad) = 0; + virtual std::function getOnLoadStart() = 0; + virtual void setOnLoadStart(const std::function& onLoadStart) = 0; + virtual std::function getOnPlaybackStateChange() = 0; + virtual void setOnPlaybackStateChange(const std::function& onPlaybackStateChange) = 0; + virtual std::function getOnPlaybackRateChange() = 0; + virtual void setOnPlaybackRateChange(const std::function& onPlaybackRateChange) = 0; + virtual std::function getOnProgress() = 0; + virtual void setOnProgress(const std::function& onProgress) = 0; + virtual std::function getOnReadyToDisplay() = 0; + virtual void setOnReadyToDisplay(const std::function& onReadyToDisplay) = 0; + virtual std::function getOnSeek() = 0; + virtual void setOnSeek(const std::function& onSeek) = 0; + virtual std::function getOnTimedMetadata() = 0; + virtual void setOnTimedMetadata(const std::function& onTimedMetadata) = 0; + virtual std::function& /* texts */)> getOnTextTrackDataChanged() = 0; + virtual void setOnTextTrackDataChanged(const std::function& /* texts */)>& onTextTrackDataChanged) = 0; + virtual std::function& /* track */)> getOnTrackChange() = 0; + virtual void setOnTrackChange(const std::function& /* track */)>& onTrackChange) = 0; + virtual std::function getOnVolumeChange() = 0; + virtual void setOnVolumeChange(const std::function& onVolumeChange) = 0; + virtual std::function getOnStatusChange() = 0; + virtual void setOnStatusChange(const std::function& onStatusChange) = 0; + + public: + // Methods + + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoPlayerEventEmitter"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp b/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp new file mode 100644 index 00000000..2c384f8c --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp @@ -0,0 +1,21 @@ +/// +/// HybridVideoPlayerFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerFactorySpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoPlayerFactorySpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridMethod("createPlayer", &HybridVideoPlayerFactorySpec::createPlayer); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.hpp b/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.hpp new file mode 100644 index 00000000..ef3506b4 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.hpp @@ -0,0 +1,67 @@ +/// +/// HybridVideoPlayerFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include "HybridVideoPlayerSourceSpec.hpp" + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoPlayerFactory` + * Inherit this class to create instances of `HybridVideoPlayerFactorySpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoPlayerFactory: public HybridVideoPlayerFactorySpec { + * public: + * HybridVideoPlayerFactory(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoPlayerFactorySpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoPlayerFactorySpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoPlayerFactorySpec() override = default; + + public: + // Properties + + + public: + // Methods + virtual std::shared_ptr createPlayer(const std::shared_ptr& source) = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoPlayerFactory"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp new file mode 100644 index 00000000..19677655 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp @@ -0,0 +1,22 @@ +/// +/// HybridVideoPlayerSourceFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSourceFactorySpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoPlayerSourceFactorySpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridMethod("fromUri", &HybridVideoPlayerSourceFactorySpec::fromUri); + prototype.registerHybridMethod("fromVideoConfig", &HybridVideoPlayerSourceFactorySpec::fromVideoConfig); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.hpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.hpp new file mode 100644 index 00000000..67b5c262 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.hpp @@ -0,0 +1,69 @@ +/// +/// HybridVideoPlayerSourceFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include +#include "NativeVideoConfig.hpp" + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoPlayerSourceFactory` + * Inherit this class to create instances of `HybridVideoPlayerSourceFactorySpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoPlayerSourceFactory: public HybridVideoPlayerSourceFactorySpec { + * public: + * HybridVideoPlayerSourceFactory(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoPlayerSourceFactorySpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoPlayerSourceFactorySpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoPlayerSourceFactorySpec() override = default; + + public: + // Properties + + + public: + // Methods + virtual std::shared_ptr fromUri(const std::string& uri) = 0; + virtual std::shared_ptr fromVideoConfig(const NativeVideoConfig& config) = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoPlayerSourceFactory"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp new file mode 100644 index 00000000..dcf46bc4 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp @@ -0,0 +1,23 @@ +/// +/// HybridVideoPlayerSourceSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSourceSpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoPlayerSourceSpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridGetter("uri", &HybridVideoPlayerSourceSpec::getUri); + prototype.registerHybridGetter("config", &HybridVideoPlayerSourceSpec::getConfig); + prototype.registerHybridMethod("getAssetInformationAsync", &HybridVideoPlayerSourceSpec::getAssetInformationAsync); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.hpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.hpp new file mode 100644 index 00000000..cff24f42 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.hpp @@ -0,0 +1,69 @@ +/// +/// HybridVideoPlayerSourceSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `NativeVideoConfig` to properly resolve imports. +namespace margelo::nitro::video { struct NativeVideoConfig; } +// Forward declaration of `VideoInformation` to properly resolve imports. +namespace margelo::nitro::video { struct VideoInformation; } + +#include +#include "NativeVideoConfig.hpp" +#include "VideoInformation.hpp" +#include + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoPlayerSource` + * Inherit this class to create instances of `HybridVideoPlayerSourceSpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoPlayerSource: public HybridVideoPlayerSourceSpec { + * public: + * HybridVideoPlayerSource(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoPlayerSourceSpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoPlayerSourceSpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoPlayerSourceSpec() override = default; + + public: + // Properties + virtual std::string getUri() = 0; + virtual NativeVideoConfig getConfig() = 0; + + public: + // Methods + virtual std::shared_ptr> getAssetInformationAsync() = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoPlayerSource"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp new file mode 100644 index 00000000..0c6e677d --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp @@ -0,0 +1,55 @@ +/// +/// HybridVideoPlayerSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoPlayerSpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoPlayerSpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridGetter("source", &HybridVideoPlayerSpec::getSource); + prototype.registerHybridGetter("eventEmitter", &HybridVideoPlayerSpec::getEventEmitter); + prototype.registerHybridGetter("showNotificationControls", &HybridVideoPlayerSpec::getShowNotificationControls); + prototype.registerHybridSetter("showNotificationControls", &HybridVideoPlayerSpec::setShowNotificationControls); + prototype.registerHybridGetter("status", &HybridVideoPlayerSpec::getStatus); + prototype.registerHybridGetter("duration", &HybridVideoPlayerSpec::getDuration); + prototype.registerHybridGetter("volume", &HybridVideoPlayerSpec::getVolume); + prototype.registerHybridSetter("volume", &HybridVideoPlayerSpec::setVolume); + prototype.registerHybridGetter("currentTime", &HybridVideoPlayerSpec::getCurrentTime); + prototype.registerHybridSetter("currentTime", &HybridVideoPlayerSpec::setCurrentTime); + prototype.registerHybridGetter("muted", &HybridVideoPlayerSpec::getMuted); + prototype.registerHybridSetter("muted", &HybridVideoPlayerSpec::setMuted); + prototype.registerHybridGetter("loop", &HybridVideoPlayerSpec::getLoop); + prototype.registerHybridSetter("loop", &HybridVideoPlayerSpec::setLoop); + prototype.registerHybridGetter("rate", &HybridVideoPlayerSpec::getRate); + prototype.registerHybridSetter("rate", &HybridVideoPlayerSpec::setRate); + prototype.registerHybridGetter("mixAudioMode", &HybridVideoPlayerSpec::getMixAudioMode); + prototype.registerHybridSetter("mixAudioMode", &HybridVideoPlayerSpec::setMixAudioMode); + prototype.registerHybridGetter("ignoreSilentSwitchMode", &HybridVideoPlayerSpec::getIgnoreSilentSwitchMode); + prototype.registerHybridSetter("ignoreSilentSwitchMode", &HybridVideoPlayerSpec::setIgnoreSilentSwitchMode); + prototype.registerHybridGetter("playInBackground", &HybridVideoPlayerSpec::getPlayInBackground); + prototype.registerHybridSetter("playInBackground", &HybridVideoPlayerSpec::setPlayInBackground); + prototype.registerHybridGetter("playWhenInactive", &HybridVideoPlayerSpec::getPlayWhenInactive); + prototype.registerHybridSetter("playWhenInactive", &HybridVideoPlayerSpec::setPlayWhenInactive); + prototype.registerHybridGetter("isPlaying", &HybridVideoPlayerSpec::getIsPlaying); + prototype.registerHybridGetter("selectedTrack", &HybridVideoPlayerSpec::getSelectedTrack); + prototype.registerHybridMethod("replaceSourceAsync", &HybridVideoPlayerSpec::replaceSourceAsync); + prototype.registerHybridMethod("getAvailableTextTracks", &HybridVideoPlayerSpec::getAvailableTextTracks); + prototype.registerHybridMethod("selectTextTrack", &HybridVideoPlayerSpec::selectTextTrack); + prototype.registerHybridMethod("initialize", &HybridVideoPlayerSpec::initialize); + prototype.registerHybridMethod("preload", &HybridVideoPlayerSpec::preload); + prototype.registerHybridMethod("play", &HybridVideoPlayerSpec::play); + prototype.registerHybridMethod("pause", &HybridVideoPlayerSpec::pause); + prototype.registerHybridMethod("seekBy", &HybridVideoPlayerSpec::seekBy); + prototype.registerHybridMethod("seekTo", &HybridVideoPlayerSpec::seekTo); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.hpp b/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.hpp new file mode 100644 index 00000000..c4ca014b --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.hpp @@ -0,0 +1,115 @@ +/// +/// HybridVideoPlayerSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } +// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; } +// Forward declaration of `VideoPlayerStatus` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoPlayerStatus; } +// Forward declaration of `MixAudioMode` to properly resolve imports. +namespace margelo::nitro::video { enum class MixAudioMode; } +// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports. +namespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; } +// Forward declaration of `TextTrack` to properly resolve imports. +namespace margelo::nitro::video { struct TextTrack; } + +#include +#include "HybridVideoPlayerSourceSpec.hpp" +#include "HybridVideoPlayerEventEmitterSpec.hpp" +#include "VideoPlayerStatus.hpp" +#include "MixAudioMode.hpp" +#include "IgnoreSilentSwitchMode.hpp" +#include "TextTrack.hpp" +#include +#include +#include + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoPlayer` + * Inherit this class to create instances of `HybridVideoPlayerSpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoPlayer: public HybridVideoPlayerSpec { + * public: + * HybridVideoPlayer(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoPlayerSpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoPlayerSpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoPlayerSpec() override = default; + + public: + // Properties + virtual std::shared_ptr getSource() = 0; + virtual std::shared_ptr getEventEmitter() = 0; + virtual bool getShowNotificationControls() = 0; + virtual void setShowNotificationControls(bool showNotificationControls) = 0; + virtual VideoPlayerStatus getStatus() = 0; + virtual double getDuration() = 0; + virtual double getVolume() = 0; + virtual void setVolume(double volume) = 0; + virtual double getCurrentTime() = 0; + virtual void setCurrentTime(double currentTime) = 0; + virtual bool getMuted() = 0; + virtual void setMuted(bool muted) = 0; + virtual bool getLoop() = 0; + virtual void setLoop(bool loop) = 0; + virtual double getRate() = 0; + virtual void setRate(double rate) = 0; + virtual MixAudioMode getMixAudioMode() = 0; + virtual void setMixAudioMode(MixAudioMode mixAudioMode) = 0; + virtual IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() = 0; + virtual void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) = 0; + virtual bool getPlayInBackground() = 0; + virtual void setPlayInBackground(bool playInBackground) = 0; + virtual bool getPlayWhenInactive() = 0; + virtual void setPlayWhenInactive(bool playWhenInactive) = 0; + virtual bool getIsPlaying() = 0; + virtual std::optional getSelectedTrack() = 0; + + public: + // Methods + virtual std::shared_ptr> replaceSourceAsync(const std::optional>& source) = 0; + virtual std::vector getAvailableTextTracks() = 0; + virtual void selectTextTrack(const std::optional& textTrack) = 0; + virtual std::shared_ptr> initialize() = 0; + virtual std::shared_ptr> preload() = 0; + virtual void play() = 0; + virtual void pause() = 0; + virtual void seekBy(double time) = 0; + virtual void seekTo(double time) = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoPlayer"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp new file mode 100644 index 00000000..2b6be369 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp @@ -0,0 +1,21 @@ +/// +/// HybridVideoViewViewManagerFactorySpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoViewViewManagerFactorySpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoViewViewManagerFactorySpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridMethod("createViewManager", &HybridVideoViewViewManagerFactorySpec::createViewManager); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.hpp b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.hpp new file mode 100644 index 00000000..a2a2f84c --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.hpp @@ -0,0 +1,64 @@ +/// +/// HybridVideoViewViewManagerFactorySpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; } + +#include +#include "HybridVideoViewViewManagerSpec.hpp" + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoViewViewManagerFactory` + * Inherit this class to create instances of `HybridVideoViewViewManagerFactorySpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoViewViewManagerFactory: public HybridVideoViewViewManagerFactorySpec { + * public: + * HybridVideoViewViewManagerFactory(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoViewViewManagerFactorySpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoViewViewManagerFactorySpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoViewViewManagerFactorySpec() override = default; + + public: + // Properties + + + public: + // Methods + virtual std::shared_ptr createViewManager(double nitroId) = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoViewViewManagerFactory"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp new file mode 100644 index 00000000..713cc6c4 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp @@ -0,0 +1,51 @@ +/// +/// HybridVideoViewViewManagerSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#include "HybridVideoViewViewManagerSpec.hpp" + +namespace margelo::nitro::video { + + void HybridVideoViewViewManagerSpec::loadHybridMethods() { + // load base methods/properties + HybridObject::loadHybridMethods(); + // load custom methods/properties + registerHybrids(this, [](Prototype& prototype) { + prototype.registerHybridGetter("player", &HybridVideoViewViewManagerSpec::getPlayer); + prototype.registerHybridSetter("player", &HybridVideoViewViewManagerSpec::setPlayer); + prototype.registerHybridGetter("controls", &HybridVideoViewViewManagerSpec::getControls); + prototype.registerHybridSetter("controls", &HybridVideoViewViewManagerSpec::setControls); + prototype.registerHybridGetter("pictureInPicture", &HybridVideoViewViewManagerSpec::getPictureInPicture); + prototype.registerHybridSetter("pictureInPicture", &HybridVideoViewViewManagerSpec::setPictureInPicture); + prototype.registerHybridGetter("autoEnterPictureInPicture", &HybridVideoViewViewManagerSpec::getAutoEnterPictureInPicture); + prototype.registerHybridSetter("autoEnterPictureInPicture", &HybridVideoViewViewManagerSpec::setAutoEnterPictureInPicture); + prototype.registerHybridGetter("resizeMode", &HybridVideoViewViewManagerSpec::getResizeMode); + prototype.registerHybridSetter("resizeMode", &HybridVideoViewViewManagerSpec::setResizeMode); + prototype.registerHybridGetter("keepScreenAwake", &HybridVideoViewViewManagerSpec::getKeepScreenAwake); + prototype.registerHybridSetter("keepScreenAwake", &HybridVideoViewViewManagerSpec::setKeepScreenAwake); + prototype.registerHybridGetter("surfaceType", &HybridVideoViewViewManagerSpec::getSurfaceType); + prototype.registerHybridSetter("surfaceType", &HybridVideoViewViewManagerSpec::setSurfaceType); + prototype.registerHybridGetter("onPictureInPictureChange", &HybridVideoViewViewManagerSpec::getOnPictureInPictureChange); + prototype.registerHybridSetter("onPictureInPictureChange", &HybridVideoViewViewManagerSpec::setOnPictureInPictureChange); + prototype.registerHybridGetter("onFullscreenChange", &HybridVideoViewViewManagerSpec::getOnFullscreenChange); + prototype.registerHybridSetter("onFullscreenChange", &HybridVideoViewViewManagerSpec::setOnFullscreenChange); + prototype.registerHybridGetter("willEnterFullscreen", &HybridVideoViewViewManagerSpec::getWillEnterFullscreen); + prototype.registerHybridSetter("willEnterFullscreen", &HybridVideoViewViewManagerSpec::setWillEnterFullscreen); + prototype.registerHybridGetter("willExitFullscreen", &HybridVideoViewViewManagerSpec::getWillExitFullscreen); + prototype.registerHybridSetter("willExitFullscreen", &HybridVideoViewViewManagerSpec::setWillExitFullscreen); + prototype.registerHybridGetter("willEnterPictureInPicture", &HybridVideoViewViewManagerSpec::getWillEnterPictureInPicture); + prototype.registerHybridSetter("willEnterPictureInPicture", &HybridVideoViewViewManagerSpec::setWillEnterPictureInPicture); + prototype.registerHybridGetter("willExitPictureInPicture", &HybridVideoViewViewManagerSpec::getWillExitPictureInPicture); + prototype.registerHybridSetter("willExitPictureInPicture", &HybridVideoViewViewManagerSpec::setWillExitPictureInPicture); + prototype.registerHybridMethod("enterFullscreen", &HybridVideoViewViewManagerSpec::enterFullscreen); + prototype.registerHybridMethod("exitFullscreen", &HybridVideoViewViewManagerSpec::exitFullscreen); + prototype.registerHybridMethod("enterPictureInPicture", &HybridVideoViewViewManagerSpec::enterPictureInPicture); + prototype.registerHybridMethod("exitPictureInPicture", &HybridVideoViewViewManagerSpec::exitPictureInPicture); + prototype.registerHybridMethod("canEnterPictureInPicture", &HybridVideoViewViewManagerSpec::canEnterPictureInPicture); + }); + } + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.hpp b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.hpp new file mode 100644 index 00000000..3a4cba13 --- /dev/null +++ b/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.hpp @@ -0,0 +1,101 @@ +/// +/// HybridVideoViewViewManagerSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSpec; } +// Forward declaration of `ResizeMode` to properly resolve imports. +namespace margelo::nitro::video { enum class ResizeMode; } +// Forward declaration of `SurfaceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SurfaceType; } + +#include +#include "HybridVideoPlayerSpec.hpp" +#include +#include "ResizeMode.hpp" +#include "SurfaceType.hpp" +#include + +namespace margelo::nitro::video { + + using namespace margelo::nitro; + + /** + * An abstract base class for `VideoViewViewManager` + * Inherit this class to create instances of `HybridVideoViewViewManagerSpec` in C++. + * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. + * @example + * ```cpp + * class HybridVideoViewViewManager: public HybridVideoViewViewManagerSpec { + * public: + * HybridVideoViewViewManager(...): HybridObject(TAG) { ... } + * // ... + * }; + * ``` + */ + class HybridVideoViewViewManagerSpec: public virtual HybridObject { + public: + // Constructor + explicit HybridVideoViewViewManagerSpec(): HybridObject(TAG) { } + + // Destructor + ~HybridVideoViewViewManagerSpec() override = default; + + public: + // Properties + virtual std::optional> getPlayer() = 0; + virtual void setPlayer(const std::optional>& player) = 0; + virtual bool getControls() = 0; + virtual void setControls(bool controls) = 0; + virtual bool getPictureInPicture() = 0; + virtual void setPictureInPicture(bool pictureInPicture) = 0; + virtual bool getAutoEnterPictureInPicture() = 0; + virtual void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) = 0; + virtual ResizeMode getResizeMode() = 0; + virtual void setResizeMode(ResizeMode resizeMode) = 0; + virtual bool getKeepScreenAwake() = 0; + virtual void setKeepScreenAwake(bool keepScreenAwake) = 0; + virtual SurfaceType getSurfaceType() = 0; + virtual void setSurfaceType(SurfaceType surfaceType) = 0; + virtual std::optional> getOnPictureInPictureChange() = 0; + virtual void setOnPictureInPictureChange(const std::optional>& onPictureInPictureChange) = 0; + virtual std::optional> getOnFullscreenChange() = 0; + virtual void setOnFullscreenChange(const std::optional>& onFullscreenChange) = 0; + virtual std::optional> getWillEnterFullscreen() = 0; + virtual void setWillEnterFullscreen(const std::optional>& willEnterFullscreen) = 0; + virtual std::optional> getWillExitFullscreen() = 0; + virtual void setWillExitFullscreen(const std::optional>& willExitFullscreen) = 0; + virtual std::optional> getWillEnterPictureInPicture() = 0; + virtual void setWillEnterPictureInPicture(const std::optional>& willEnterPictureInPicture) = 0; + virtual std::optional> getWillExitPictureInPicture() = 0; + virtual void setWillExitPictureInPicture(const std::optional>& willExitPictureInPicture) = 0; + + public: + // Methods + virtual void enterFullscreen() = 0; + virtual void exitFullscreen() = 0; + virtual void enterPictureInPicture() = 0; + virtual void exitPictureInPicture() = 0; + virtual bool canEnterPictureInPicture() = 0; + + protected: + // Hybrid Setup + void loadHybridMethods() override; + + protected: + // Tag for logging + static constexpr auto TAG = "VideoViewViewManager"; + }; + +} // namespace margelo::nitro::video diff --git a/nitrogen/generated/shared/c++/IgnoreSilentSwitchMode.hpp b/nitrogen/generated/shared/c++/IgnoreSilentSwitchMode.hpp new file mode 100644 index 00000000..50651bea --- /dev/null +++ b/nitrogen/generated/shared/c++/IgnoreSilentSwitchMode.hpp @@ -0,0 +1,80 @@ +/// +/// IgnoreSilentSwitchMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (IgnoreSilentSwitchMode). + */ + enum class IgnoreSilentSwitchMode { + AUTO SWIFT_NAME(auto) = 0, + IGNORE SWIFT_NAME(ignore) = 1, + OBEY SWIFT_NAME(obey) = 2, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ IgnoreSilentSwitchMode <> JS IgnoreSilentSwitchMode (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::IgnoreSilentSwitchMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("auto"): return margelo::nitro::video::IgnoreSilentSwitchMode::AUTO; + case hashString("ignore"): return margelo::nitro::video::IgnoreSilentSwitchMode::IGNORE; + case hashString("obey"): return margelo::nitro::video::IgnoreSilentSwitchMode::OBEY; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum IgnoreSilentSwitchMode - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::IgnoreSilentSwitchMode arg) { + switch (arg) { + case margelo::nitro::video::IgnoreSilentSwitchMode::AUTO: return JSIConverter::toJSI(runtime, "auto"); + case margelo::nitro::video::IgnoreSilentSwitchMode::IGNORE: return JSIConverter::toJSI(runtime, "ignore"); + case margelo::nitro::video::IgnoreSilentSwitchMode::OBEY: return JSIConverter::toJSI(runtime, "obey"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert IgnoreSilentSwitchMode 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("auto"): + case hashString("ignore"): + case hashString("obey"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/LivePlaybackParams.hpp b/nitrogen/generated/shared/c++/LivePlaybackParams.hpp new file mode 100644 index 00000000..9b70701f --- /dev/null +++ b/nitrogen/generated/shared/c++/LivePlaybackParams.hpp @@ -0,0 +1,83 @@ +/// +/// LivePlaybackParams.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (LivePlaybackParams). + */ + struct LivePlaybackParams { + public: + std::optional minPlaybackSpeed SWIFT_PRIVATE; + std::optional maxPlaybackSpeed SWIFT_PRIVATE; + std::optional maxOffsetMs SWIFT_PRIVATE; + std::optional minOffsetMs SWIFT_PRIVATE; + std::optional targetOffsetMs SWIFT_PRIVATE; + + public: + LivePlaybackParams() = default; + explicit LivePlaybackParams(std::optional minPlaybackSpeed, std::optional maxPlaybackSpeed, std::optional maxOffsetMs, std::optional minOffsetMs, std::optional targetOffsetMs): minPlaybackSpeed(minPlaybackSpeed), maxPlaybackSpeed(maxPlaybackSpeed), maxOffsetMs(maxOffsetMs), minOffsetMs(minOffsetMs), targetOffsetMs(targetOffsetMs) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ LivePlaybackParams <> JS LivePlaybackParams (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::LivePlaybackParams fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::LivePlaybackParams( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "minPlaybackSpeed")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxPlaybackSpeed")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxOffsetMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "minOffsetMs")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "targetOffsetMs")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::LivePlaybackParams& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "minPlaybackSpeed", JSIConverter>::toJSI(runtime, arg.minPlaybackSpeed)); + obj.setProperty(runtime, "maxPlaybackSpeed", JSIConverter>::toJSI(runtime, arg.maxPlaybackSpeed)); + obj.setProperty(runtime, "maxOffsetMs", JSIConverter>::toJSI(runtime, arg.maxOffsetMs)); + obj.setProperty(runtime, "minOffsetMs", JSIConverter>::toJSI(runtime, arg.minOffsetMs)); + obj.setProperty(runtime, "targetOffsetMs", JSIConverter>::toJSI(runtime, arg.targetOffsetMs)); + 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 (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "minPlaybackSpeed"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxPlaybackSpeed"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxOffsetMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "minOffsetMs"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "targetOffsetMs"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/MixAudioMode.hpp b/nitrogen/generated/shared/c++/MixAudioMode.hpp new file mode 100644 index 00000000..2b36d2d0 --- /dev/null +++ b/nitrogen/generated/shared/c++/MixAudioMode.hpp @@ -0,0 +1,84 @@ +/// +/// MixAudioMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (MixAudioMode). + */ + enum class MixAudioMode { + MIXWITHOTHERS SWIFT_NAME(mixwithothers) = 0, + DONOTMIX SWIFT_NAME(donotmix) = 1, + DUCKOTHERS SWIFT_NAME(duckothers) = 2, + AUTO SWIFT_NAME(auto) = 3, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ MixAudioMode <> JS MixAudioMode (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::MixAudioMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("mixWithOthers"): return margelo::nitro::video::MixAudioMode::MIXWITHOTHERS; + case hashString("doNotMix"): return margelo::nitro::video::MixAudioMode::DONOTMIX; + case hashString("duckOthers"): return margelo::nitro::video::MixAudioMode::DUCKOTHERS; + case hashString("auto"): return margelo::nitro::video::MixAudioMode::AUTO; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum MixAudioMode - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::MixAudioMode arg) { + switch (arg) { + case margelo::nitro::video::MixAudioMode::MIXWITHOTHERS: return JSIConverter::toJSI(runtime, "mixWithOthers"); + case margelo::nitro::video::MixAudioMode::DONOTMIX: return JSIConverter::toJSI(runtime, "doNotMix"); + case margelo::nitro::video::MixAudioMode::DUCKOTHERS: return JSIConverter::toJSI(runtime, "duckOthers"); + case margelo::nitro::video::MixAudioMode::AUTO: return JSIConverter::toJSI(runtime, "auto"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert MixAudioMode 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("mixWithOthers"): + case hashString("doNotMix"): + case hashString("duckOthers"): + case hashString("auto"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/NativeDrmParams.hpp b/nitrogen/generated/shared/c++/NativeDrmParams.hpp new file mode 100644 index 00000000..a4f2941e --- /dev/null +++ b/nitrogen/generated/shared/c++/NativeDrmParams.hpp @@ -0,0 +1,97 @@ +/// +/// NativeDrmParams.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `OnGetLicensePayload` to properly resolve imports. +namespace margelo::nitro::video { struct OnGetLicensePayload; } + +#include +#include +#include +#include +#include "OnGetLicensePayload.hpp" +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (NativeDrmParams). + */ + struct NativeDrmParams { + public: + std::optional type SWIFT_PRIVATE; + std::optional licenseUrl SWIFT_PRIVATE; + std::optional certificateUrl SWIFT_PRIVATE; + std::optional contentId SWIFT_PRIVATE; + std::optional> licenseHeaders SWIFT_PRIVATE; + std::optional multiSession SWIFT_PRIVATE; + std::optional>>>(const OnGetLicensePayload& /* payload */)>> getLicense SWIFT_PRIVATE; + + public: + NativeDrmParams() = default; + explicit NativeDrmParams(std::optional type, std::optional licenseUrl, std::optional certificateUrl, std::optional contentId, std::optional> licenseHeaders, std::optional multiSession, std::optional>>>(const OnGetLicensePayload& /* payload */)>> getLicense): type(type), licenseUrl(licenseUrl), certificateUrl(certificateUrl), contentId(contentId), licenseHeaders(licenseHeaders), multiSession(multiSession), getLicense(getLicense) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ NativeDrmParams <> JS NativeDrmParams (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::NativeDrmParams fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::NativeDrmParams( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "type")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "licenseUrl")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "certificateUrl")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "contentId")), + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "licenseHeaders")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "multiSession")), + JSIConverter>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::fromJSI(runtime, obj.getProperty(runtime, "getLicense")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeDrmParams& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "type", JSIConverter>::toJSI(runtime, arg.type)); + obj.setProperty(runtime, "licenseUrl", JSIConverter>::toJSI(runtime, arg.licenseUrl)); + obj.setProperty(runtime, "certificateUrl", JSIConverter>::toJSI(runtime, arg.certificateUrl)); + obj.setProperty(runtime, "contentId", JSIConverter>::toJSI(runtime, arg.contentId)); + obj.setProperty(runtime, "licenseHeaders", JSIConverter>>::toJSI(runtime, arg.licenseHeaders)); + obj.setProperty(runtime, "multiSession", JSIConverter>::toJSI(runtime, arg.multiSession)); + obj.setProperty(runtime, "getLicense", JSIConverter>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::toJSI(runtime, arg.getLicense)); + 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 (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "type"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "licenseUrl"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "certificateUrl"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "contentId"))) return false; + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "licenseHeaders"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "multiSession"))) return false; + if (!JSIConverter>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::canConvert(runtime, obj.getProperty(runtime, "getLicense"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/NativeExternalSubtitle.hpp b/nitrogen/generated/shared/c++/NativeExternalSubtitle.hpp new file mode 100644 index 00000000..593186bf --- /dev/null +++ b/nitrogen/generated/shared/c++/NativeExternalSubtitle.hpp @@ -0,0 +1,81 @@ +/// +/// NativeExternalSubtitle.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `SubtitleType` to properly resolve imports. +namespace margelo::nitro::video { enum class SubtitleType; } + +#include +#include "SubtitleType.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (NativeExternalSubtitle). + */ + struct NativeExternalSubtitle { + public: + std::string uri SWIFT_PRIVATE; + std::string label SWIFT_PRIVATE; + SubtitleType type SWIFT_PRIVATE; + std::string language SWIFT_PRIVATE; + + public: + NativeExternalSubtitle() = default; + explicit NativeExternalSubtitle(std::string uri, std::string label, SubtitleType type, std::string language): uri(uri), label(label), type(type), language(language) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ NativeExternalSubtitle <> JS NativeExternalSubtitle (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::NativeExternalSubtitle fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::NativeExternalSubtitle( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "uri")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "label")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "type")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "language")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeExternalSubtitle& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "uri", JSIConverter::toJSI(runtime, arg.uri)); + obj.setProperty(runtime, "label", JSIConverter::toJSI(runtime, arg.label)); + obj.setProperty(runtime, "type", JSIConverter::toJSI(runtime, arg.type)); + obj.setProperty(runtime, "language", JSIConverter::toJSI(runtime, arg.language)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "uri"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "label"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "type"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "language"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/NativeVideoConfig.hpp b/nitrogen/generated/shared/c++/NativeVideoConfig.hpp new file mode 100644 index 00000000..a483726b --- /dev/null +++ b/nitrogen/generated/shared/c++/NativeVideoConfig.hpp @@ -0,0 +1,105 @@ +/// +/// NativeVideoConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `NativeExternalSubtitle` to properly resolve imports. +namespace margelo::nitro::video { struct NativeExternalSubtitle; } +// Forward declaration of `NativeDrmParams` to properly resolve imports. +namespace margelo::nitro::video { struct NativeDrmParams; } +// Forward declaration of `BufferConfig` to properly resolve imports. +namespace margelo::nitro::video { struct BufferConfig; } +// Forward declaration of `CustomVideoMetadata` to properly resolve imports. +namespace margelo::nitro::video { struct CustomVideoMetadata; } + +#include +#include "NativeExternalSubtitle.hpp" +#include +#include +#include "NativeDrmParams.hpp" +#include +#include "BufferConfig.hpp" +#include "CustomVideoMetadata.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (NativeVideoConfig). + */ + struct NativeVideoConfig { + public: + std::string uri SWIFT_PRIVATE; + std::optional> externalSubtitles SWIFT_PRIVATE; + std::optional drm SWIFT_PRIVATE; + std::optional> headers SWIFT_PRIVATE; + std::optional bufferConfig SWIFT_PRIVATE; + std::optional metadata SWIFT_PRIVATE; + std::optional initializeOnCreation SWIFT_PRIVATE; + + public: + NativeVideoConfig() = default; + explicit NativeVideoConfig(std::string uri, std::optional> externalSubtitles, std::optional drm, std::optional> headers, std::optional bufferConfig, std::optional metadata, std::optional initializeOnCreation): uri(uri), externalSubtitles(externalSubtitles), drm(drm), headers(headers), bufferConfig(bufferConfig), metadata(metadata), initializeOnCreation(initializeOnCreation) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ NativeVideoConfig <> JS NativeVideoConfig (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::NativeVideoConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::NativeVideoConfig( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "uri")), + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "externalSubtitles")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "drm")), + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, "headers")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "bufferConfig")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "metadata")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "initializeOnCreation")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeVideoConfig& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "uri", JSIConverter::toJSI(runtime, arg.uri)); + obj.setProperty(runtime, "externalSubtitles", JSIConverter>>::toJSI(runtime, arg.externalSubtitles)); + obj.setProperty(runtime, "drm", JSIConverter>::toJSI(runtime, arg.drm)); + obj.setProperty(runtime, "headers", JSIConverter>>::toJSI(runtime, arg.headers)); + obj.setProperty(runtime, "bufferConfig", JSIConverter>::toJSI(runtime, arg.bufferConfig)); + obj.setProperty(runtime, "metadata", JSIConverter>::toJSI(runtime, arg.metadata)); + obj.setProperty(runtime, "initializeOnCreation", JSIConverter>::toJSI(runtime, arg.initializeOnCreation)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "uri"))) return false; + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "externalSubtitles"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "drm"))) return false; + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, "headers"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "bufferConfig"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "metadata"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "initializeOnCreation"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/OnGetLicensePayload.hpp b/nitrogen/generated/shared/c++/OnGetLicensePayload.hpp new file mode 100644 index 00000000..3ed04ab7 --- /dev/null +++ b/nitrogen/generated/shared/c++/OnGetLicensePayload.hpp @@ -0,0 +1,79 @@ +/// +/// OnGetLicensePayload.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (OnGetLicensePayload). + */ + struct OnGetLicensePayload { + public: + std::string contentId SWIFT_PRIVATE; + std::string licenseUrl SWIFT_PRIVATE; + std::string keyUrl SWIFT_PRIVATE; + std::string spc SWIFT_PRIVATE; + + public: + OnGetLicensePayload() = default; + explicit OnGetLicensePayload(std::string contentId, std::string licenseUrl, std::string keyUrl, std::string spc): contentId(contentId), licenseUrl(licenseUrl), keyUrl(keyUrl), spc(spc) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ OnGetLicensePayload <> JS OnGetLicensePayload (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::OnGetLicensePayload fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::OnGetLicensePayload( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "contentId")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "licenseUrl")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "keyUrl")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "spc")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::OnGetLicensePayload& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "contentId", JSIConverter::toJSI(runtime, arg.contentId)); + obj.setProperty(runtime, "licenseUrl", JSIConverter::toJSI(runtime, arg.licenseUrl)); + obj.setProperty(runtime, "keyUrl", JSIConverter::toJSI(runtime, arg.keyUrl)); + obj.setProperty(runtime, "spc", JSIConverter::toJSI(runtime, arg.spc)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "contentId"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "licenseUrl"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "keyUrl"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "spc"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/ResizeMode.hpp b/nitrogen/generated/shared/c++/ResizeMode.hpp new file mode 100644 index 00000000..c1db4467 --- /dev/null +++ b/nitrogen/generated/shared/c++/ResizeMode.hpp @@ -0,0 +1,84 @@ +/// +/// ResizeMode.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (ResizeMode). + */ + enum class ResizeMode { + CONTAIN SWIFT_NAME(contain) = 0, + COVER SWIFT_NAME(cover) = 1, + STRETCH SWIFT_NAME(stretch) = 2, + NONE SWIFT_NAME(none) = 3, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ ResizeMode <> JS ResizeMode (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::ResizeMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("contain"): return margelo::nitro::video::ResizeMode::CONTAIN; + case hashString("cover"): return margelo::nitro::video::ResizeMode::COVER; + case hashString("stretch"): return margelo::nitro::video::ResizeMode::STRETCH; + case hashString("none"): return margelo::nitro::video::ResizeMode::NONE; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum ResizeMode - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::ResizeMode arg) { + switch (arg) { + case margelo::nitro::video::ResizeMode::CONTAIN: return JSIConverter::toJSI(runtime, "contain"); + case margelo::nitro::video::ResizeMode::COVER: return JSIConverter::toJSI(runtime, "cover"); + case margelo::nitro::video::ResizeMode::STRETCH: return JSIConverter::toJSI(runtime, "stretch"); + case margelo::nitro::video::ResizeMode::NONE: return JSIConverter::toJSI(runtime, "none"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert ResizeMode 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("contain"): + case hashString("cover"): + case hashString("stretch"): + case hashString("none"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/Resolution.hpp b/nitrogen/generated/shared/c++/Resolution.hpp new file mode 100644 index 00000000..4a858147 --- /dev/null +++ b/nitrogen/generated/shared/c++/Resolution.hpp @@ -0,0 +1,71 @@ +/// +/// Resolution.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + + + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (Resolution). + */ + struct Resolution { + public: + double width SWIFT_PRIVATE; + double height SWIFT_PRIVATE; + + public: + Resolution() = default; + explicit Resolution(double width, double height): width(width), height(height) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ Resolution <> JS Resolution (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::Resolution fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::Resolution( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::Resolution& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); + obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/SourceType.hpp b/nitrogen/generated/shared/c++/SourceType.hpp new file mode 100644 index 00000000..31ea01d2 --- /dev/null +++ b/nitrogen/generated/shared/c++/SourceType.hpp @@ -0,0 +1,76 @@ +/// +/// SourceType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (SourceType). + */ + enum class SourceType { + LOCAL SWIFT_NAME(local) = 0, + NETWORK SWIFT_NAME(network) = 1, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ SourceType <> JS SourceType (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::SourceType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("local"): return margelo::nitro::video::SourceType::LOCAL; + case hashString("network"): return margelo::nitro::video::SourceType::NETWORK; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum SourceType - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SourceType arg) { + switch (arg) { + case margelo::nitro::video::SourceType::LOCAL: return JSIConverter::toJSI(runtime, "local"); + case margelo::nitro::video::SourceType::NETWORK: return JSIConverter::toJSI(runtime, "network"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert SourceType 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("local"): + case hashString("network"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/SubtitleType.hpp b/nitrogen/generated/shared/c++/SubtitleType.hpp new file mode 100644 index 00000000..f76312a3 --- /dev/null +++ b/nitrogen/generated/shared/c++/SubtitleType.hpp @@ -0,0 +1,88 @@ +/// +/// SubtitleType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (SubtitleType). + */ + enum class SubtitleType { + AUTO SWIFT_NAME(auto) = 0, + VTT SWIFT_NAME(vtt) = 1, + SRT SWIFT_NAME(srt) = 2, + SSA SWIFT_NAME(ssa) = 3, + ASS SWIFT_NAME(ass) = 4, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ SubtitleType <> JS SubtitleType (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::SubtitleType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("auto"): return margelo::nitro::video::SubtitleType::AUTO; + case hashString("vtt"): return margelo::nitro::video::SubtitleType::VTT; + case hashString("srt"): return margelo::nitro::video::SubtitleType::SRT; + case hashString("ssa"): return margelo::nitro::video::SubtitleType::SSA; + case hashString("ass"): return margelo::nitro::video::SubtitleType::ASS; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum SubtitleType - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SubtitleType arg) { + switch (arg) { + case margelo::nitro::video::SubtitleType::AUTO: return JSIConverter::toJSI(runtime, "auto"); + case margelo::nitro::video::SubtitleType::VTT: return JSIConverter::toJSI(runtime, "vtt"); + case margelo::nitro::video::SubtitleType::SRT: return JSIConverter::toJSI(runtime, "srt"); + case margelo::nitro::video::SubtitleType::SSA: return JSIConverter::toJSI(runtime, "ssa"); + case margelo::nitro::video::SubtitleType::ASS: return JSIConverter::toJSI(runtime, "ass"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert SubtitleType 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("auto"): + case hashString("vtt"): + case hashString("srt"): + case hashString("ssa"): + case hashString("ass"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/SurfaceType.hpp b/nitrogen/generated/shared/c++/SurfaceType.hpp new file mode 100644 index 00000000..4b8b3817 --- /dev/null +++ b/nitrogen/generated/shared/c++/SurfaceType.hpp @@ -0,0 +1,76 @@ +/// +/// SurfaceType.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (SurfaceType). + */ + enum class SurfaceType { + SURFACE SWIFT_NAME(surface) = 0, + TEXTURE SWIFT_NAME(texture) = 1, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ SurfaceType <> JS SurfaceType (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::SurfaceType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("surface"): return margelo::nitro::video::SurfaceType::SURFACE; + case hashString("texture"): return margelo::nitro::video::SurfaceType::TEXTURE; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum SurfaceType - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SurfaceType arg) { + switch (arg) { + case margelo::nitro::video::SurfaceType::SURFACE: return JSIConverter::toJSI(runtime, "surface"); + case margelo::nitro::video::SurfaceType::TEXTURE: return JSIConverter::toJSI(runtime, "texture"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert SurfaceType 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("surface"): + case hashString("texture"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/TextTrack.hpp b/nitrogen/generated/shared/c++/TextTrack.hpp new file mode 100644 index 00000000..94b15f79 --- /dev/null +++ b/nitrogen/generated/shared/c++/TextTrack.hpp @@ -0,0 +1,80 @@ +/// +/// TextTrack.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (TextTrack). + */ + struct TextTrack { + public: + std::string id SWIFT_PRIVATE; + std::string label SWIFT_PRIVATE; + std::optional language SWIFT_PRIVATE; + bool selected SWIFT_PRIVATE; + + public: + TextTrack() = default; + explicit TextTrack(std::string id, std::string label, std::optional language, bool selected): id(id), label(label), language(language), selected(selected) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ TextTrack <> JS TextTrack (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::TextTrack fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::TextTrack( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "id")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "label")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "language")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "selected")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TextTrack& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "id", JSIConverter::toJSI(runtime, arg.id)); + obj.setProperty(runtime, "label", JSIConverter::toJSI(runtime, arg.label)); + obj.setProperty(runtime, "language", JSIConverter>::toJSI(runtime, arg.language)); + obj.setProperty(runtime, "selected", JSIConverter::toJSI(runtime, arg.selected)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "id"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "label"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "language"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "selected"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/TimedMetadata.hpp b/nitrogen/generated/shared/c++/TimedMetadata.hpp new file mode 100644 index 00000000..6fe6b661 --- /dev/null +++ b/nitrogen/generated/shared/c++/TimedMetadata.hpp @@ -0,0 +1,69 @@ +/// +/// TimedMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `TimedMetadataObject` to properly resolve imports. +namespace margelo::nitro::video { struct TimedMetadataObject; } + +#include "TimedMetadataObject.hpp" +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (TimedMetadata). + */ + struct TimedMetadata { + public: + std::vector metadata SWIFT_PRIVATE; + + public: + TimedMetadata() = default; + explicit TimedMetadata(std::vector metadata): metadata(metadata) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ TimedMetadata <> JS TimedMetadata (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::TimedMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::TimedMetadata( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "metadata")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TimedMetadata& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "metadata", JSIConverter>::toJSI(runtime, arg.metadata)); + 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 (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "metadata"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/TimedMetadataObject.hpp b/nitrogen/generated/shared/c++/TimedMetadataObject.hpp new file mode 100644 index 00000000..a9760760 --- /dev/null +++ b/nitrogen/generated/shared/c++/TimedMetadataObject.hpp @@ -0,0 +1,71 @@ +/// +/// TimedMetadataObject.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + +#include + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (TimedMetadataObject). + */ + struct TimedMetadataObject { + public: + std::string value SWIFT_PRIVATE; + std::string identifier SWIFT_PRIVATE; + + public: + TimedMetadataObject() = default; + explicit TimedMetadataObject(std::string value, std::string identifier): value(value), identifier(identifier) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ TimedMetadataObject <> JS TimedMetadataObject (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::TimedMetadataObject fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::TimedMetadataObject( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "value")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "identifier")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TimedMetadataObject& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "value", JSIConverter::toJSI(runtime, arg.value)); + obj.setProperty(runtime, "identifier", JSIConverter::toJSI(runtime, arg.identifier)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "value"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "identifier"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/VideoInformation.hpp b/nitrogen/generated/shared/c++/VideoInformation.hpp new file mode 100644 index 00000000..fea666f2 --- /dev/null +++ b/nitrogen/generated/shared/c++/VideoInformation.hpp @@ -0,0 +1,96 @@ +/// +/// VideoInformation.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } + +#include "VideoOrientation.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (VideoInformation). + */ + struct VideoInformation { + public: + double bitrate SWIFT_PRIVATE; + double width SWIFT_PRIVATE; + double height SWIFT_PRIVATE; + int64_t duration SWIFT_PRIVATE; + int64_t fileSize SWIFT_PRIVATE; + bool isHDR SWIFT_PRIVATE; + bool isLive SWIFT_PRIVATE; + VideoOrientation orientation SWIFT_PRIVATE; + + public: + VideoInformation() = default; + explicit VideoInformation(double bitrate, double width, double height, int64_t duration, int64_t fileSize, bool isHDR, bool isLive, VideoOrientation orientation): bitrate(bitrate), width(width), height(height), duration(duration), fileSize(fileSize), isHDR(isHDR), isLive(isLive), orientation(orientation) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ VideoInformation <> JS VideoInformation (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::VideoInformation fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::VideoInformation( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "bitrate")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "duration")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "fileSize")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "isHDR")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "isLive")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "orientation")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::VideoInformation& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "bitrate", JSIConverter::toJSI(runtime, arg.bitrate)); + obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); + obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); + obj.setProperty(runtime, "duration", JSIConverter::toJSI(runtime, arg.duration)); + obj.setProperty(runtime, "fileSize", JSIConverter::toJSI(runtime, arg.fileSize)); + obj.setProperty(runtime, "isHDR", JSIConverter::toJSI(runtime, arg.isHDR)); + obj.setProperty(runtime, "isLive", JSIConverter::toJSI(runtime, arg.isLive)); + obj.setProperty(runtime, "orientation", JSIConverter::toJSI(runtime, arg.orientation)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "bitrate"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "duration"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "fileSize"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "isHDR"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "isLive"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "orientation"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/VideoOrientation.hpp b/nitrogen/generated/shared/c++/VideoOrientation.hpp new file mode 100644 index 00000000..2d9444ce --- /dev/null +++ b/nitrogen/generated/shared/c++/VideoOrientation.hpp @@ -0,0 +1,96 @@ +/// +/// VideoOrientation.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (VideoOrientation). + */ + enum class VideoOrientation { + PORTRAIT SWIFT_NAME(portrait) = 0, + LANDSCAPE SWIFT_NAME(landscape) = 1, + PORTRAIT_UPSIDE_DOWN SWIFT_NAME(portraitUpsideDown) = 2, + LANDSCAPE_LEFT SWIFT_NAME(landscapeLeft) = 3, + LANDSCAPE_RIGHT SWIFT_NAME(landscapeRight) = 4, + SQUARE SWIFT_NAME(square) = 5, + UNKNOWN SWIFT_NAME(unknown) = 6, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ VideoOrientation <> JS VideoOrientation (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::VideoOrientation fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("portrait"): return margelo::nitro::video::VideoOrientation::PORTRAIT; + case hashString("landscape"): return margelo::nitro::video::VideoOrientation::LANDSCAPE; + case hashString("portrait-upside-down"): return margelo::nitro::video::VideoOrientation::PORTRAIT_UPSIDE_DOWN; + case hashString("landscape-left"): return margelo::nitro::video::VideoOrientation::LANDSCAPE_LEFT; + case hashString("landscape-right"): return margelo::nitro::video::VideoOrientation::LANDSCAPE_RIGHT; + case hashString("square"): return margelo::nitro::video::VideoOrientation::SQUARE; + case hashString("unknown"): return margelo::nitro::video::VideoOrientation::UNKNOWN; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum VideoOrientation - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::VideoOrientation arg) { + switch (arg) { + case margelo::nitro::video::VideoOrientation::PORTRAIT: return JSIConverter::toJSI(runtime, "portrait"); + case margelo::nitro::video::VideoOrientation::LANDSCAPE: return JSIConverter::toJSI(runtime, "landscape"); + case margelo::nitro::video::VideoOrientation::PORTRAIT_UPSIDE_DOWN: return JSIConverter::toJSI(runtime, "portrait-upside-down"); + case margelo::nitro::video::VideoOrientation::LANDSCAPE_LEFT: return JSIConverter::toJSI(runtime, "landscape-left"); + case margelo::nitro::video::VideoOrientation::LANDSCAPE_RIGHT: return JSIConverter::toJSI(runtime, "landscape-right"); + case margelo::nitro::video::VideoOrientation::SQUARE: return JSIConverter::toJSI(runtime, "square"); + case margelo::nitro::video::VideoOrientation::UNKNOWN: return JSIConverter::toJSI(runtime, "unknown"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert VideoOrientation 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("portrait"): + case hashString("landscape"): + case hashString("portrait-upside-down"): + case hashString("landscape-left"): + case hashString("landscape-right"): + case hashString("square"): + case hashString("unknown"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/VideoPlayerStatus.hpp b/nitrogen/generated/shared/c++/VideoPlayerStatus.hpp new file mode 100644 index 00000000..aeb15403 --- /dev/null +++ b/nitrogen/generated/shared/c++/VideoPlayerStatus.hpp @@ -0,0 +1,84 @@ +/// +/// VideoPlayerStatus.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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::video { + + /** + * An enum which can be represented as a JavaScript union (VideoPlayerStatus). + */ + enum class VideoPlayerStatus { + IDLE SWIFT_NAME(idle) = 0, + LOADING SWIFT_NAME(loading) = 1, + READYTOPLAY SWIFT_NAME(readytoplay) = 2, + ERROR SWIFT_NAME(error) = 3, + } CLOSED_ENUM; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ VideoPlayerStatus <> JS VideoPlayerStatus (union) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::VideoPlayerStatus fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("idle"): return margelo::nitro::video::VideoPlayerStatus::IDLE; + case hashString("loading"): return margelo::nitro::video::VideoPlayerStatus::LOADING; + case hashString("readyToPlay"): return margelo::nitro::video::VideoPlayerStatus::READYTOPLAY; + case hashString("error"): return margelo::nitro::video::VideoPlayerStatus::ERROR; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum VideoPlayerStatus - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::VideoPlayerStatus arg) { + switch (arg) { + case margelo::nitro::video::VideoPlayerStatus::IDLE: return JSIConverter::toJSI(runtime, "idle"); + case margelo::nitro::video::VideoPlayerStatus::LOADING: return JSIConverter::toJSI(runtime, "loading"); + case margelo::nitro::video::VideoPlayerStatus::READYTOPLAY: return JSIConverter::toJSI(runtime, "readyToPlay"); + case margelo::nitro::video::VideoPlayerStatus::ERROR: return JSIConverter::toJSI(runtime, "error"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert VideoPlayerStatus 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("idle"): + case hashString("loading"): + case hashString("readyToPlay"): + case hashString("error"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/onLoadData.hpp b/nitrogen/generated/shared/c++/onLoadData.hpp new file mode 100644 index 00000000..6cd3bc6e --- /dev/null +++ b/nitrogen/generated/shared/c++/onLoadData.hpp @@ -0,0 +1,84 @@ +/// +/// onLoadData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `VideoOrientation` to properly resolve imports. +namespace margelo::nitro::video { enum class VideoOrientation; } + +#include "VideoOrientation.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (onLoadData). + */ + struct onLoadData { + public: + double currentTime SWIFT_PRIVATE; + double duration SWIFT_PRIVATE; + double height SWIFT_PRIVATE; + double width SWIFT_PRIVATE; + VideoOrientation orientation SWIFT_PRIVATE; + + public: + onLoadData() = default; + explicit onLoadData(double currentTime, double duration, double height, double width, VideoOrientation orientation): currentTime(currentTime), duration(duration), height(height), width(width), orientation(orientation) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ onLoadData <> JS onLoadData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::onLoadData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::onLoadData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "currentTime")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "duration")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "orientation")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onLoadData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "currentTime", JSIConverter::toJSI(runtime, arg.currentTime)); + obj.setProperty(runtime, "duration", JSIConverter::toJSI(runtime, arg.duration)); + obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); + obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); + obj.setProperty(runtime, "orientation", JSIConverter::toJSI(runtime, arg.orientation)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "currentTime"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "duration"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "orientation"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/onLoadStartData.hpp b/nitrogen/generated/shared/c++/onLoadStartData.hpp new file mode 100644 index 00000000..a0eb6500 --- /dev/null +++ b/nitrogen/generated/shared/c++/onLoadStartData.hpp @@ -0,0 +1,76 @@ +/// +/// onLoadStartData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + +// Forward declaration of `SourceType` to properly resolve imports. +namespace margelo::nitro::video { enum class SourceType; } +// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports. +namespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; } + +#include "SourceType.hpp" +#include +#include "HybridVideoPlayerSourceSpec.hpp" + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (onLoadStartData). + */ + struct onLoadStartData { + public: + SourceType sourceType SWIFT_PRIVATE; + std::shared_ptr source SWIFT_PRIVATE; + + public: + onLoadStartData() = default; + explicit onLoadStartData(SourceType sourceType, std::shared_ptr source): sourceType(sourceType), source(source) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ onLoadStartData <> JS onLoadStartData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::onLoadStartData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::onLoadStartData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "sourceType")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "source")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onLoadStartData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "sourceType", JSIConverter::toJSI(runtime, arg.sourceType)); + obj.setProperty(runtime, "source", JSIConverter>::toJSI(runtime, arg.source)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "sourceType"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "source"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/onPlaybackStateChangeData.hpp b/nitrogen/generated/shared/c++/onPlaybackStateChangeData.hpp new file mode 100644 index 00000000..cd1cdbaa --- /dev/null +++ b/nitrogen/generated/shared/c++/onPlaybackStateChangeData.hpp @@ -0,0 +1,71 @@ +/// +/// onPlaybackStateChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + + + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (onPlaybackStateChangeData). + */ + struct onPlaybackStateChangeData { + public: + bool isPlaying SWIFT_PRIVATE; + bool isBuffering SWIFT_PRIVATE; + + public: + onPlaybackStateChangeData() = default; + explicit onPlaybackStateChangeData(bool isPlaying, bool isBuffering): isPlaying(isPlaying), isBuffering(isBuffering) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ onPlaybackStateChangeData <> JS onPlaybackStateChangeData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::onPlaybackStateChangeData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::onPlaybackStateChangeData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "isPlaying")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "isBuffering")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onPlaybackStateChangeData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "isPlaying", JSIConverter::toJSI(runtime, arg.isPlaying)); + obj.setProperty(runtime, "isBuffering", JSIConverter::toJSI(runtime, arg.isBuffering)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "isPlaying"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "isBuffering"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/onProgressData.hpp b/nitrogen/generated/shared/c++/onProgressData.hpp new file mode 100644 index 00000000..c641f623 --- /dev/null +++ b/nitrogen/generated/shared/c++/onProgressData.hpp @@ -0,0 +1,71 @@ +/// +/// onProgressData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + + + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (onProgressData). + */ + struct onProgressData { + public: + double currentTime SWIFT_PRIVATE; + double bufferDuration SWIFT_PRIVATE; + + public: + onProgressData() = default; + explicit onProgressData(double currentTime, double bufferDuration): currentTime(currentTime), bufferDuration(bufferDuration) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ onProgressData <> JS onProgressData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::onProgressData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::onProgressData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "currentTime")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "bufferDuration")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onProgressData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "currentTime", JSIConverter::toJSI(runtime, arg.currentTime)); + obj.setProperty(runtime, "bufferDuration", JSIConverter::toJSI(runtime, arg.bufferDuration)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "currentTime"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "bufferDuration"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/onVolumeChangeData.hpp b/nitrogen/generated/shared/c++/onVolumeChangeData.hpp new file mode 100644 index 00000000..9fb9fd1b --- /dev/null +++ b/nitrogen/generated/shared/c++/onVolumeChangeData.hpp @@ -0,0 +1,71 @@ +/// +/// onVolumeChangeData.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2025 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 + + + + + +namespace margelo::nitro::video { + + /** + * A struct which can be represented as a JavaScript object (onVolumeChangeData). + */ + struct onVolumeChangeData { + public: + double volume SWIFT_PRIVATE; + bool muted SWIFT_PRIVATE; + + public: + onVolumeChangeData() = default; + explicit onVolumeChangeData(double volume, bool muted): volume(volume), muted(muted) {} + }; + +} // namespace margelo::nitro::video + +namespace margelo::nitro { + + // C++ onVolumeChangeData <> JS onVolumeChangeData (object) + template <> + struct JSIConverter final { + static inline margelo::nitro::video::onVolumeChangeData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::video::onVolumeChangeData( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "volume")), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "muted")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onVolumeChangeData& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "volume", JSIConverter::toJSI(runtime, arg.volume)); + obj.setProperty(runtime, "muted", JSIConverter::toJSI(runtime, arg.muted)); + 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 (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "volume"))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "muted"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/package.json b/package.json new file mode 100644 index 00000000..55e49b4a --- /dev/null +++ b/package.json @@ -0,0 +1,160 @@ +{ + "name": "react-native-video", + "version": "7.0.0-alpha.5", + "description": "