mirror of
https://github.com/zoriya/react-native-video.git
synced 2025-12-05 23:06:14 +00:00
Compare commits
29 Commits
v7
...
b1b5fa1717
| Author | SHA1 | Date | |
|---|---|---|---|
| b1b5fa1717 | |||
| 7f04c16e3e | |||
| 959c23d6f2 | |||
| 958778e647 | |||
| c49b2f17f2 | |||
| ccf9497313 | |||
| bcc084e083 | |||
| c356fa10ec | |||
| f3fdb8b648 | |||
| 52a22aa10e | |||
| 771196dd0f | |||
| 82ff34fa9c | |||
| b2cf9d63f1 | |||
| 937d34d73e | |||
| a092578cab | |||
| d6803b2b4c | |||
| 6703499e60 | |||
| ecf5849f2c | |||
| 8ad923750b | |||
| 796c0edfa0 | |||
| 57039bb564 | |||
|
|
9b74665fb4 | ||
|
|
1671c63dab | ||
|
|
02044de0e9 | ||
|
|
375fbeb0eb | ||
|
|
4ebc9b7f05 | ||
|
|
a97581ab8a | ||
|
|
58a268c022 | ||
| 07b55755d1 |
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
5
biome.json
Normal file
5
biome.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"formatter": {
|
||||
"useEditorconfig": true
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"allowUnusedLabels": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": ["ESNext"],
|
||||
"lib": ["ESNext", "dom"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": true,
|
||||
@@ -33,4 +33,4 @@
|
||||
"target": "ESNext",
|
||||
"verbatimModuleSyntax": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,17 +87,17 @@ import { VideoPlayer } from 'react-native-video';
|
||||
|
||||
const player = new VideoPlayer('https://example.com/video.mp4');
|
||||
|
||||
player.onLoad = (data) => {
|
||||
player.addEventListener('onLoad', (data) => {
|
||||
console.log('Video loaded! Duration:', data.duration);
|
||||
};
|
||||
});
|
||||
|
||||
player.onProgress = (data) => {
|
||||
player.addEventListener('onProgress', (data) => {
|
||||
console.log('Current time:', data.currentTime);
|
||||
};
|
||||
});
|
||||
|
||||
player.onError = (error) => {
|
||||
player.addEventListener('onError', (error) => {
|
||||
console.error('Player Error:', error.code, error.message);
|
||||
};
|
||||
});
|
||||
|
||||
player.play();
|
||||
```
|
||||
@@ -105,4 +105,4 @@ player.play();
|
||||
## Clearing Events
|
||||
|
||||
- The `player.clearEvent(eventName)` method can be used to clear a specific native event handler.
|
||||
- When a player instance is no longer needed and `player.release()` is called, all event listeners are automatically cleared
|
||||
- When a player instance is no longer needed and `player.release()` is called, all event listeners are automatically cleared
|
||||
|
||||
@@ -53,6 +53,7 @@ export default App;
|
||||
| `autoEnterPictureInPicture` | `boolean` | No | `false` | Whether the video should automatically enter PiP mode when it starts playing and the app is backgrounded (behavior might vary by platform). |
|
||||
| `resizeMode` | `'contain' \| 'cover' \| 'stretch' \| 'none'` | No | `'none'` | How the video should be resized to fit the view. |
|
||||
| `keepScreenAwake` | `boolean` | No | `true` | Whether to keep the device screen awake while the video view is mounted. |
|
||||
| `surfaceType` | `'surface' \| 'texture'` | No (Android only) | `'surface'` | (Android) Underlying native view type. `'surface'` uses a SurfaceView (better performance, no transforms/overlap), `'texture'` uses a TextureView (supports animations, transforms, overlapping UI) at a small performance cost. Ignored on iOS. |
|
||||
|
||||
## Events
|
||||
|
||||
@@ -104,4 +105,26 @@ Available methods on the `VideoViewRef`:
|
||||
| `exitFullscreen()` | `() => void` | Programmatically requests the video view to exit fullscreen mode. |
|
||||
| `enterPictureInPicture()` | `() => void` | Programmatically requests the video view to enter picture-in-picture mode. |
|
||||
| `exitPictureInPicture()` | `() => void` | Programmatically requests the video view to exit picture-in-picture mode. |
|
||||
| `canEnterPictureInPicture()` | `() => boolean` | Checks if picture-in-picture mode is currently available and supported. Returns `true` if PiP can be entered, `false` otherwise. |
|
||||
| `canEnterPictureInPicture()` | `() => boolean` | Checks if picture-in-picture mode is currently available and supported. Returns `true` if PiP can be entered, `false` otherwise. |
|
||||
|
||||
## Android: Choosing a surface type
|
||||
|
||||
On Android the default rendering path uses a `SurfaceView` (set via `surfaceType="surface"`) for optimal decoding performance and lower latency. However `SurfaceView` lives in a separate window and can't be:
|
||||
|
||||
- Animated with transforms (scale, rotate, opacity fade)
|
||||
- Clipped by parent views (rounded corners, masks)
|
||||
- Overlapped reliably with sibling views (z-order issues)
|
||||
|
||||
If you need those UI effects, switch to `TextureView`:
|
||||
|
||||
```tsx
|
||||
<VideoView
|
||||
player={player}
|
||||
surfaceType="texture"
|
||||
style={{ width: 300, height: 170, borderRadius: 16, overflow: 'hidden' }}
|
||||
resizeMode="cover"
|
||||
controls
|
||||
/>
|
||||
```
|
||||
|
||||
Use `TextureView` only when required, as it can be slightly less performant and may increase power consumption on some devices.
|
||||
@@ -8,7 +8,7 @@ PODS:
|
||||
- hermes-engine (0.77.2):
|
||||
- hermes-engine/Pre-built (= 0.77.2)
|
||||
- hermes-engine/Pre-built (0.77.2)
|
||||
- NitroModules (0.28.0):
|
||||
- NitroModules (0.29.8):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1565,7 +1565,7 @@ PODS:
|
||||
- React-logger (= 0.77.2)
|
||||
- React-perflogger (= 0.77.2)
|
||||
- React-utils (= 0.77.2)
|
||||
- ReactNativeVideo (7.0.0-alpha.4):
|
||||
- ReactNativeVideo (7.0.0-alpha.5):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1844,7 +1844,7 @@ SPEC CHECKSUMS:
|
||||
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
|
||||
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
|
||||
hermes-engine: 8eb265241fa1d7095d3a40d51fd90f7dce68217c
|
||||
NitroModules: 1e4150c3e3676e05209234a8a5e0e8886fc0311a
|
||||
NitroModules: b4cd8f92604355343f12fc93772ff5a19571d41f
|
||||
RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82
|
||||
RCTDeprecation: 85b72250b63cfb54f29ca96ceb108cb9ef3c2079
|
||||
RCTRequired: 567cb8f5d42b990331bfd93faad1d8999b1c1736
|
||||
@@ -1904,7 +1904,7 @@ SPEC CHECKSUMS:
|
||||
ReactAppDependencyProvider: f334cebc0beed0a72490492e978007082c03d533
|
||||
ReactCodegen: 474fbb3e4bb0f1ee6c255d1955db76e13d509269
|
||||
ReactCommon: 7763e59534d58e15f8f22121cdfe319040e08888
|
||||
ReactNativeVideo: f365bc4f1a57ab50ddb655cda2f47bc06698a53b
|
||||
ReactNativeVideo: 705a2a90d9f04afff9afd90d4ef194e1bc1135d5
|
||||
ReactNativeVideoDrm: 62840ae0e184f711a2e6495c18e342a74cb598f8
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
Yoga: 31a098f74c16780569aebd614a0f37a907de0189
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
{
|
||||
"name": "react-native-video-example",
|
||||
"version": "7.0.0-alpha.4",
|
||||
"version": "7.0.0-alpha.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc",
|
||||
"start": "react-native start --client-logs"
|
||||
"start": "react-native start --client-logs",
|
||||
"bundle-install": "bundle install",
|
||||
"pods": "cd ios && pod install && cd .."
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-community/slider": "^4.5.6",
|
||||
"react": "18.3.1",
|
||||
"react-native": "^0.77.0",
|
||||
"react-native-nitro-modules": "^0.28.0",
|
||||
"react-native-nitro-modules": "^0.29.0",
|
||||
"react-native-video": "*",
|
||||
"@twg/react-native-video-drm": "*"
|
||||
},
|
||||
|
||||
@@ -146,6 +146,7 @@ const VideoDemo = () => {
|
||||
player.playWhenInactive = settings.playWhenInactive;
|
||||
player.mixAudioMode = settings.mixAudioMode;
|
||||
player.ignoreSilentSwitchMode = settings.ignoreSilentSwitchMode;
|
||||
player.showNotificationControls = settings.showNotificationControls;
|
||||
}, [settings, player]);
|
||||
|
||||
const handleSeek = (val: number) => {
|
||||
@@ -315,6 +316,13 @@ const VideoDemo = () => {
|
||||
value={settings.playWhenInactive}
|
||||
onValueChange={(value) => updateSetting('playWhenInactive', value)}
|
||||
/>
|
||||
<SwitchControl
|
||||
label="Notification Controls"
|
||||
value={settings.showNotificationControls}
|
||||
onValueChange={(value) =>
|
||||
updateSetting('showNotificationControls', value)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface VideoSettings {
|
||||
ignoreSilentSwitchMode: IgnoreSilentSwitchMode;
|
||||
playInBackground: boolean;
|
||||
playWhenInactive: boolean;
|
||||
showNotificationControls: boolean;
|
||||
}
|
||||
|
||||
export const defaultSettings: VideoSettings = {
|
||||
@@ -32,4 +33,5 @@ export const defaultSettings: VideoSettings = {
|
||||
ignoreSilentSwitchMode: 'auto',
|
||||
playInBackground: true,
|
||||
playWhenInactive: false,
|
||||
showNotificationControls: true,
|
||||
};
|
||||
|
||||
@@ -103,5 +103,14 @@ export const getVideoSource = (type: VideoType): VideoConfig => {
|
||||
type: 'vtt',
|
||||
},
|
||||
],
|
||||
metadata: {
|
||||
title: 'Big Buck Bunny',
|
||||
artist: 'Blender Foundation',
|
||||
imageUri:
|
||||
'https://peach.blender.org/wp-content/uploads/title_anouncement.jpg',
|
||||
subtitle: 'By the Blender Institute',
|
||||
description:
|
||||
'Big Buck Bunny is a short computer-animated comedy film by the Blender Institute, part of the Blender Foundation. It was made using Blender, a free and open-source 3D creation suite.',
|
||||
},
|
||||
} as VideoConfig;
|
||||
};
|
||||
|
||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-native-video-monorepo",
|
||||
"packageManager": "bun@1.1.42",
|
||||
"version": "7.0.0-alpha.4",
|
||||
"version": "7.0.0-alpha.5",
|
||||
"private": true,
|
||||
"repository": "https://github.com/TheWidlarzGroup/react-native-video",
|
||||
"author": "TheWidlarzGroup <hi@thewidlarzgroup.com> (https://github.com/TheWidlarzGroup)",
|
||||
@@ -64,7 +64,8 @@
|
||||
"release": true
|
||||
},
|
||||
"hooks": {
|
||||
"before:release": "bun run --cwd packages/react-native-video build"
|
||||
"before:release": "bun run --cwd packages/react-native-video build && bun run --cwd packages/drm-plugin build",
|
||||
"before:git": "bun install && bun example bundle-install && bun example pods && git add bun.lock && git add example/ios/Podfile.lock"
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/bumper": {
|
||||
@@ -73,6 +74,10 @@
|
||||
"file": "packages/react-native-video/package.json",
|
||||
"path": "version"
|
||||
},
|
||||
{
|
||||
"file": "packages/drm-plugin/package.json",
|
||||
"path": "version"
|
||||
},
|
||||
{
|
||||
"file": "example/package.json",
|
||||
"path": "version"
|
||||
@@ -91,6 +96,10 @@
|
||||
"type": "fix",
|
||||
"section": "Bug Fixes 🐛"
|
||||
},
|
||||
{
|
||||
"type": "refactor",
|
||||
"section": "Code Refactoring 🛠"
|
||||
},
|
||||
{
|
||||
"type": "chore(deps)",
|
||||
"section": "Dependency Upgrades 📦"
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideoDrm+autolinking.cmake)
|
||||
# ```
|
||||
|
||||
# Define a flag to check if we are building properly
|
||||
add_definitions(-DBUILDING_REACTNATIVEVIDEODRM_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++"
|
||||
@@ -32,12 +38,9 @@ target_sources(
|
||||
../nitrogen/generated/android/c++/JHybridPluginManagerSpec.cpp
|
||||
)
|
||||
|
||||
# Define a flag to check if we are building properly
|
||||
add_definitions(-DBUILDING_REACTNATIVEVIDEODRM_WITH_GENERATED_CMAKE_PROJECT)
|
||||
|
||||
# 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(
|
||||
target_compile_definitions(
|
||||
ReactNativeVideoDrm PRIVATE
|
||||
-DFOLLY_NO_CONFIG=1
|
||||
-DFOLLY_HAVE_CLOCK_GETTIME=1
|
||||
|
||||
@@ -35,8 +35,7 @@ int initialize(JavaVM* vm) {
|
||||
[]() -> std::shared_ptr<HybridObject> {
|
||||
static DefaultConstructableObject<JHybridPluginManagerSpec::javaobject> object("com/margelo/nitro/videodrm/PluginManager");
|
||||
auto instance = object.create();
|
||||
auto globalRef = jni::make_global(instance);
|
||||
return globalRef->cthis()->shared();
|
||||
return instance->cthis()->shared();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
namespace margelo::nitro::videodrm::bridge::swift {
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridPluginManagerSpec>
|
||||
std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideoDrm::HybridPluginManagerSpec_cxx swiftPart = ReactNativeVideoDrm::HybridPluginManagerSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::videodrm::HybridPluginManagerSpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::videodrm::HybridPluginManagerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::videodrm::HybridPluginManagerSpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
|
||||
@@ -32,19 +32,19 @@ namespace margelo::nitro::videodrm::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<HybridPluginManagerSpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridPluginManagerSpec_ = std::shared_ptr<HybridPluginManagerSpec>;
|
||||
std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType);
|
||||
std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept;
|
||||
void* NON_NULL get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType) noexcept;
|
||||
|
||||
// pragma MARK: std::weak_ptr<HybridPluginManagerSpec>
|
||||
using std__weak_ptr_HybridPluginManagerSpec_ = std::weak_ptr<HybridPluginManagerSpec>;
|
||||
inline std__weak_ptr_HybridPluginManagerSpec_ weakify_std__shared_ptr_HybridPluginManagerSpec_(const std::shared_ptr<HybridPluginManagerSpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridPluginManagerSpec_ weakify_std__shared_ptr_HybridPluginManagerSpec_(const std::shared_ptr<HybridPluginManagerSpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<void>
|
||||
using Result_void_ = Result<void>;
|
||||
inline Result_void_ create_Result_void_() {
|
||||
inline Result_void_ create_Result_void_() noexcept {
|
||||
return Result<void>::withValue();
|
||||
}
|
||||
inline Result_void_ create_Result_void_(const std::exception_ptr& error) {
|
||||
inline Result_void_ create_Result_void_(const std::exception_ptr& error) noexcept {
|
||||
return Result<void>::withError(error);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@twg/react-native-video-drm",
|
||||
"version": "0.1.0",
|
||||
"version": "7.0.0-alpha.5",
|
||||
"description": "DRM plugin for react-native-video",
|
||||
"main": "./lib/module/index.js",
|
||||
"types": "./lib/typescript/src/index.d.ts",
|
||||
@@ -40,8 +40,8 @@
|
||||
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
||||
"prepare": "bun run build",
|
||||
"build": "bob build",
|
||||
"specs": "nitro-codegen",
|
||||
"release": "release-it --only-version"
|
||||
"specs": "nitrogen",
|
||||
"release": "release-it --preRelease alpha --npm.tag=next"
|
||||
},
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -71,12 +71,12 @@
|
||||
"eslint": "^8.51.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"nitro-codegen": "^0.28.0",
|
||||
"nitrogen": "^0.29.0",
|
||||
"prettier": "^3.0.3",
|
||||
"react": "18.3.1",
|
||||
"react-native": "^0.77.0",
|
||||
"react-native-builder-bob": "^0.40.13",
|
||||
"react-native-nitro-modules": "^0.28.0",
|
||||
"react-native-nitro-modules": "^0.29.0",
|
||||
"release-it": "^17.10.0",
|
||||
"typescript": "^5.8.3",
|
||||
"react-native-video": "*"
|
||||
|
||||
@@ -120,7 +120,7 @@ android {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
|
||||
arguments "-DANDROID_STL=c++_shared"
|
||||
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
||||
abiFilters (*reactNativeArchitectures())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
RNVideo_kotlinVersion=1.9.24
|
||||
RNVideo_minKotlinVersion=1.8.0
|
||||
RNVideo_minSdkVersion=23
|
||||
RNVideo_targetSdkVersion=34
|
||||
RNVideo_compileSdkVersion=34
|
||||
RNVideo_ndkversion=26.1.10909125
|
||||
RNVideo_minSdkVersion=24
|
||||
RNVideo_targetSdkVersion=35
|
||||
RNVideo_compileSdkVersion=35
|
||||
RNVideo_ndkversion=27.1.12297006
|
||||
|
||||
RNVideo_useExoplayerDash=true
|
||||
RNVideo_useExoplayerHls=true
|
||||
|
||||
@@ -42,7 +42,11 @@ fun VideoPlaybackService.Companion.stopService(
|
||||
serviceConnection: VideoPlaybackServiceConnection
|
||||
) {
|
||||
try {
|
||||
NitroModules.applicationContext?.currentActivity?.unbindService(serviceConnection)
|
||||
// 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) {}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ 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
|
||||
@@ -39,6 +41,10 @@ fun createMediaItemFromVideoConfig(
|
||||
mediaItemBuilder.setLiveConfiguration(getLiveConfiguration(livePlaybackParams))
|
||||
}
|
||||
|
||||
source.config.metadata?.let { metadata ->
|
||||
mediaItemBuilder.setMediaMetadata(getCustomMetadata(metadata))
|
||||
}
|
||||
|
||||
return PluginsRegistry.shared.overrideMediaItemBuilder(
|
||||
source,
|
||||
mediaItemBuilder
|
||||
@@ -122,3 +128,14 @@ fun getLiveConfiguration(
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ fun buildExternalSubtitlesMediaSource(context: Context, source: HybridVideoPlaye
|
||||
.setUri(source.uri.toUri())
|
||||
.setSubtitleConfigurations(getSubtitlesConfiguration(source.config))
|
||||
|
||||
source.config.metadata?.let { metadata ->
|
||||
mediaItemBuilderWithSubtitles.setMediaMetadata(getCustomMetadata(metadata))
|
||||
}
|
||||
|
||||
val mediaItemBuilder = PluginsRegistry.shared.overrideMediaItemBuilder(
|
||||
source,
|
||||
mediaItemBuilderWithSubtitles
|
||||
|
||||
@@ -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<CommandButton>,
|
||||
showPauseButton: Boolean
|
||||
): ImmutableList<CommandButton> {
|
||||
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<CommandButton>,
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,41 @@ 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<CommandButton> {
|
||||
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 {
|
||||
@@ -23,36 +51,46 @@ class VideoPlaybackCallback : MediaSession.Callback {
|
||||
).setAvailableSessionCommands(
|
||||
MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
|
||||
.add(
|
||||
SessionCommand(
|
||||
VideoPlaybackService.Companion.COMMAND.SEEK_FORWARD.stringValue,
|
||||
Bundle.EMPTY
|
||||
)
|
||||
SessionCommand(
|
||||
CustomMediaNotificationProvider.Companion.COMMAND.SEEK_FORWARD.stringValue,
|
||||
Bundle.EMPTY
|
||||
)
|
||||
)
|
||||
.add(
|
||||
SessionCommand(
|
||||
VideoPlaybackService.Companion.COMMAND.SEEK_BACKWARD.stringValue,
|
||||
Bundle.EMPTY
|
||||
CustomMediaNotificationProvider.Companion.COMMAND.SEEK_BACKWARD.stringValue,
|
||||
Bundle.EMPTY
|
||||
)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
.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<SessionResult> {
|
||||
VideoPlaybackService.Companion.handleCommand(
|
||||
VideoPlaybackService.Companion.commandFromString(
|
||||
customCommand.customAction
|
||||
), session
|
||||
CustomMediaNotificationProvider.Companion.handleCommand(
|
||||
CustomMediaNotificationProvider.Companion.commandFromString(
|
||||
customCommand.customAction
|
||||
), session
|
||||
)
|
||||
|
||||
return super.onCustomCommand(session, controller, customCommand, args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
package com.twg.video.core.services.playback
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import androidx.media3.common.util.BitmapLoader
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.session.CommandButton
|
||||
import androidx.media3.session.DefaultMediaNotificationProvider
|
||||
import androidx.media3.session.SimpleBitmapLoader
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.session.MediaSessionService
|
||||
import androidx.media3.session.MediaStyleNotificationHelper
|
||||
import androidx.media3.session.SessionCommand
|
||||
import androidx.media3.ui.R
|
||||
import com.margelo.nitro.NitroModules
|
||||
import com.margelo.nitro.video.HybridVideoPlayer
|
||||
import okhttp3.internal.immutableListOf
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class VideoPlaybackServiceBinder(val service: VideoPlaybackService): Binder()
|
||||
|
||||
@@ -32,26 +24,12 @@ class VideoPlaybackServiceBinder(val service: VideoPlaybackService): Binder()
|
||||
class VideoPlaybackService : MediaSessionService() {
|
||||
private var mediaSessionsList = mutableMapOf<HybridVideoPlayer, MediaSession>()
|
||||
private var binder = VideoPlaybackServiceBinder(this)
|
||||
private var sourceActivity: Class<Activity>? = null
|
||||
private var placeholderCanceled = false
|
||||
private var sourceActivity: Class<Activity>? = null // retained for future deep-links; currently unused
|
||||
|
||||
// Controls for Android 13+ - see buildNotification function
|
||||
private val commandSeekForward = SessionCommand(COMMAND.SEEK_FORWARD.stringValue, Bundle.EMPTY)
|
||||
private val commandSeekBackward = SessionCommand(COMMAND.SEEK_BACKWARD.stringValue, Bundle.EMPTY)
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
private val seekForwardBtn = CommandButton.Builder()
|
||||
.setDisplayName("forward")
|
||||
.setSessionCommand(commandSeekForward)
|
||||
.setIconResId(R.drawable.exo_notification_fastforward)
|
||||
.build()
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
private val seekBackwardBtn = CommandButton.Builder()
|
||||
.setDisplayName("backward")
|
||||
.setSessionCommand(commandSeekBackward)
|
||||
.setIconResId(R.drawable.exo_notification_rewind)
|
||||
.build()
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
setMediaNotificationProvider(CustomMediaNotificationProvider(this))
|
||||
}
|
||||
|
||||
// Player Registry
|
||||
fun registerPlayer(player: HybridVideoPlayer, from: Class<Activity>) {
|
||||
@@ -60,27 +38,54 @@ class VideoPlaybackService : MediaSessionService() {
|
||||
}
|
||||
sourceActivity = from
|
||||
|
||||
val mediaSession = MediaSession.Builder(this, player.player)
|
||||
val builder = MediaSession.Builder(this, player.player)
|
||||
.setId("RNVideoPlaybackService_" + player.hashCode())
|
||||
.setCallback(VideoPlaybackCallback())
|
||||
.setCustomLayout(immutableListOf(seekBackwardBtn, seekForwardBtn))
|
||||
.build()
|
||||
|
||||
// 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)
|
||||
|
||||
// Manually trigger initial notification creation for the registered player
|
||||
// This ensures the player notification appears immediately, even if not playing
|
||||
onUpdateNotification(mediaSession, true)
|
||||
}
|
||||
|
||||
fun unregisterPlayer(player: HybridVideoPlayer) {
|
||||
hidePlayerNotification(player.player)
|
||||
val session = mediaSessionsList.remove(player)
|
||||
session?.release()
|
||||
if (mediaSessionsList.isEmpty()) {
|
||||
cleanup()
|
||||
stopSelf()
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,235 +98,41 @@ class VideoPlaybackService : MediaSessionService() {
|
||||
return binder
|
||||
}
|
||||
|
||||
override fun onUpdateNotification(session: MediaSession, startInForegroundRequired: Boolean) {
|
||||
val notification = buildNotification(session)
|
||||
val notificationId = session.player.hashCode()
|
||||
val notificationManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
// Always cancel the placeholder notification once we have a real player notification
|
||||
if (!placeholderCanceled) {
|
||||
notificationManager.cancel(PLACEHOLDER_NOTIFICATION_ID)
|
||||
placeholderCanceled = true
|
||||
}
|
||||
|
||||
if (startInForegroundRequired) {
|
||||
startForeground(notificationId, notification)
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANEL_ID,
|
||||
NOTIFICATION_CHANEL_ID,
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (session.player.currentMediaItem == null) {
|
||||
notificationManager.cancel(notificationId)
|
||||
return
|
||||
}
|
||||
|
||||
notificationManager.notify(notificationId, notification)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
stopForegroundSafely()
|
||||
cleanup()
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
stopForegroundSafely()
|
||||
cleanup()
|
||||
val notificationManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.deleteNotificationChannel(NOTIFICATION_CHANEL_ID)
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun buildNotification(session: MediaSession): Notification {
|
||||
val returnToPlayer = Intent(this, sourceActivity ?: this.javaClass).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
}
|
||||
|
||||
/*
|
||||
* On Android 13+ controls are automatically handled via media session
|
||||
* On Android 12 and bellow we need to add controls manually
|
||||
*/
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID)
|
||||
.setSmallIcon(androidx.media3.session.R.drawable.media3_icon_circular_play)
|
||||
.setStyle(MediaStyleNotificationHelper.MediaStyle(session))
|
||||
.setContentIntent(PendingIntent.getActivity(this, 0, returnToPlayer, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
|
||||
.build()
|
||||
} else {
|
||||
val playerId = session.player.hashCode()
|
||||
|
||||
// Action for COMMAND.SEEK_BACKWARD
|
||||
val seekBackwardIntent = Intent(this, VideoPlaybackService::class.java).apply {
|
||||
putExtra("PLAYER_ID", playerId)
|
||||
putExtra("ACTION", COMMAND.SEEK_BACKWARD.stringValue)
|
||||
}
|
||||
val seekBackwardPendingIntent = PendingIntent.getService(
|
||||
this,
|
||||
playerId * 10,
|
||||
seekBackwardIntent,
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// ACTION FOR COMMAND.TOGGLE_PLAY
|
||||
val togglePlayIntent = Intent(this, VideoPlaybackService::class.java).apply {
|
||||
putExtra("PLAYER_ID", playerId)
|
||||
putExtra("ACTION", COMMAND.TOGGLE_PLAY.stringValue)
|
||||
}
|
||||
val togglePlayPendingIntent = PendingIntent.getService(
|
||||
this,
|
||||
playerId * 10 + 1,
|
||||
togglePlayIntent,
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// ACTION FOR COMMAND.SEEK_FORWARD
|
||||
val seekForwardIntent = Intent(this, VideoPlaybackService::class.java).apply {
|
||||
putExtra("PLAYER_ID", playerId)
|
||||
putExtra("ACTION", COMMAND.SEEK_FORWARD.stringValue)
|
||||
}
|
||||
val seekForwardPendingIntent = PendingIntent.getService(
|
||||
this,
|
||||
playerId * 10 + 2,
|
||||
seekForwardIntent,
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID)
|
||||
// Show controls on lock screen even when user hides sensitive content.
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setSmallIcon(androidx.media3.session.R.drawable.media3_icon_circular_play)
|
||||
// Add media control buttons that invoke intents in your media service
|
||||
.addAction(androidx.media3.session.R.drawable.media3_icon_rewind, "Seek Backward", seekBackwardPendingIntent) // #0
|
||||
.addAction(
|
||||
if (session.player.isPlaying) {
|
||||
androidx.media3.session.R.drawable.media3_icon_pause
|
||||
} else {
|
||||
androidx.media3.session.R.drawable.media3_icon_play
|
||||
},
|
||||
"Toggle Play",
|
||||
togglePlayPendingIntent
|
||||
) // #1
|
||||
.addAction(androidx.media3.session.R.drawable.media3_icon_fast_forward, "Seek Forward", seekForwardPendingIntent) // #2
|
||||
// Apply the media style template
|
||||
.setStyle(MediaStyleNotificationHelper.MediaStyle(session).setShowActionsInCompactView(0, 1, 2))
|
||||
.setContentTitle(session.player.mediaMetadata.title)
|
||||
.setContentText(session.player.mediaMetadata.description)
|
||||
.setContentIntent(PendingIntent.getActivity(this, 0, returnToPlayer, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
|
||||
.setLargeIcon(session.player.mediaMetadata.artworkUri?.let { session.bitmapLoader.loadBitmap(it).get() })
|
||||
.setOngoing(true)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hidePlayerNotification(player: ExoPlayer) {
|
||||
val notificationManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.cancel(player.hashCode())
|
||||
}
|
||||
|
||||
private fun hideAllNotifications() {
|
||||
val notificationManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.cancelAll()
|
||||
private fun stopForegroundSafely() {
|
||||
try {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
|
||||
private fun cleanup() {
|
||||
hideAllNotifications()
|
||||
stopForegroundSafely()
|
||||
stopSelf()
|
||||
mediaSessionsList.forEach { (_, session) ->
|
||||
session.release()
|
||||
}
|
||||
mediaSessionsList.clear()
|
||||
placeholderCanceled = false
|
||||
}
|
||||
|
||||
private fun createPlaceholderNotification(): Notification {
|
||||
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANEL_ID,
|
||||
NOTIFICATION_CHANEL_ID,
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
)
|
||||
// Stop the service if there are no active media sessions (no players need it)
|
||||
fun stopIfNoPlayers() {
|
||||
if (mediaSessionsList.isEmpty()) {
|
||||
cleanup()
|
||||
}
|
||||
|
||||
return NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID)
|
||||
.setSmallIcon(androidx.media3.session.R.drawable.media3_icon_circular_play)
|
||||
.setContentTitle("Media playback")
|
||||
.setContentText("Preparing playback")
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !placeholderCanceled) {
|
||||
startForeground(PLACEHOLDER_NOTIFICATION_ID, createPlaceholderNotification())
|
||||
}
|
||||
|
||||
intent?.let {
|
||||
val playerId = it.getIntExtra("PLAYER_ID", -1)
|
||||
val actionCommand = it.getStringExtra("ACTION")
|
||||
|
||||
if (playerId < 0) {
|
||||
Log.w(TAG, "Received Command without playerId")
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
if (actionCommand == null) {
|
||||
Log.w(TAG, "Received Command without action command")
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
val session = mediaSessionsList.values.find { s -> s.player.hashCode() == playerId } ?: return super.onStartCommand(intent, flags, startId)
|
||||
|
||||
handleCommand(commandFromString(actionCommand), session)
|
||||
}
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SEEK_INTERVAL_MS = 10000L
|
||||
private const val TAG = "VideoPlaybackService"
|
||||
private const val PLACEHOLDER_NOTIFICATION_ID = 9999
|
||||
|
||||
const val NOTIFICATION_CHANEL_ID = "RNVIDEO_SESSION_NOTIFICATION"
|
||||
const val VIDEO_PLAYBACK_SERVICE_INTERFACE = SERVICE_INTERFACE
|
||||
|
||||
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?")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,10 @@ class VideoPlaybackServiceConnection (private val player: WeakReference<HybridVi
|
||||
}
|
||||
|
||||
serviceBinder = binder as? VideoPlaybackServiceBinder
|
||||
serviceBinder?.service?.registerPlayer(player, activity.javaClass)
|
||||
// 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)
|
||||
}
|
||||
|
||||
@@ -102,6 +102,23 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
||||
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 },
|
||||
@@ -172,16 +189,18 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
||||
|
||||
override var playInBackground: Boolean = false
|
||||
set(value) {
|
||||
// playback in background was disabled and is now enabled
|
||||
if (value == true && field == false) {
|
||||
val shouldRun = (value || showNotificationControls)
|
||||
val wasRunning = (field || showNotificationControls)
|
||||
|
||||
if (shouldRun && !wasRunning) {
|
||||
VideoPlaybackService.startService(context, videoPlaybackServiceConnection)
|
||||
field = true
|
||||
}
|
||||
// playback in background was enabled and is now disabled
|
||||
else if (field == true) {
|
||||
if (!shouldRun && wasRunning) {
|
||||
VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)
|
||||
field = false
|
||||
}
|
||||
field = value
|
||||
// Update preferences to refresh notifications/registration
|
||||
try { videoPlaybackServiceConnection.serviceBinder?.service?.updatePlayerPreferences(this) } catch (_: Exception) {}
|
||||
}
|
||||
|
||||
override var playWhenInactive: Boolean = false
|
||||
@@ -323,7 +342,7 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() {
|
||||
}
|
||||
|
||||
private fun release() {
|
||||
if (playInBackground) {
|
||||
if (playInBackground || showNotificationControls) {
|
||||
VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,16 @@ import com.facebook.proguard.annotations.DoNotStrip
|
||||
@DoNotStrip
|
||||
class HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec() {
|
||||
override fun fromUri(uri: String): HybridVideoPlayerSourceSpec {
|
||||
val config = NativeVideoConfig(uri, null, null, null, null, true)
|
||||
val config = NativeVideoConfig(
|
||||
uri = uri,
|
||||
externalSubtitles = null,
|
||||
drm = null,
|
||||
headers = null,
|
||||
bufferConfig = null,
|
||||
metadata = null,
|
||||
initializeOnCreation = true
|
||||
)
|
||||
|
||||
return HybridVideoPlayerSource(config)
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,12 @@ class HybridVideoViewViewManager(nitroId: Int): HybridVideoViewViewManagerSpec()
|
||||
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) {
|
||||
|
||||
@@ -8,6 +8,7 @@ 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
|
||||
@@ -22,6 +23,7 @@ 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
|
||||
@@ -36,6 +38,8 @@ 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(
|
||||
@@ -90,6 +94,20 @@ class VideoView @JvmOverloads constructor(
|
||||
|
||||
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
|
||||
@@ -101,7 +119,9 @@ class VideoView @JvmOverloads constructor(
|
||||
var keepScreenAwake: Boolean
|
||||
get() = playerView.keepScreenOn
|
||||
set(value) {
|
||||
playerView.keepScreenOn = value
|
||||
runOnMainThread {
|
||||
playerView.keepScreenOn = value
|
||||
}
|
||||
}
|
||||
|
||||
var events = object : VideoViewEvents {
|
||||
@@ -114,15 +134,7 @@ class VideoView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
var onNitroIdChange: ((Int?) -> Unit)? = null
|
||||
var playerView = PlayerView(context).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()
|
||||
}
|
||||
var playerView = createPlayerView()
|
||||
var isInFullscreen: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
@@ -153,6 +165,22 @@ class VideoView @JvmOverloads constructor(
|
||||
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),
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/player_view_surface"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:surface_type="surface_view" />
|
||||
@@ -0,0 +1,7 @@
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/player_view_texture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:surface_type="texture_view" />
|
||||
@@ -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<AVPlayer>.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
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,16 @@ class VideoManager {
|
||||
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 {
|
||||
@@ -133,7 +143,11 @@ class VideoManager {
|
||||
player.mixAudioMode == .donotmix
|
||||
}
|
||||
|
||||
if isAnyPlayerPlaying || anyPlayerNeedsNotMixWithOthers {
|
||||
let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in
|
||||
player.showNotificationControls
|
||||
}
|
||||
|
||||
if isAnyPlayerPlaying || anyPlayerNeedsNotMixWithOthers || anyPlayerNeedsNotificationControls || remoteControlEventsActive {
|
||||
activateAudioSession()
|
||||
} else {
|
||||
deactivateAudioSession()
|
||||
@@ -162,6 +176,10 @@ class VideoManager {
|
||||
player.playInBackground
|
||||
}
|
||||
|
||||
let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in
|
||||
player.showNotificationControls
|
||||
}
|
||||
|
||||
if isAudioSessionManagementDisabled {
|
||||
return
|
||||
}
|
||||
@@ -172,7 +190,7 @@ class VideoManager {
|
||||
earpiece: false, // TODO: Pass actual value after we add prop
|
||||
pip: anyViewNeedsPictureInPicture,
|
||||
backgroundPlayback: anyPlayerNeedsBackgroundPlayback,
|
||||
notificationControls: false // TODO: Pass actual value after we add prop
|
||||
notificationControls: anyPlayerNeedsNotificationControls
|
||||
)
|
||||
|
||||
let audioMixingMode = determineAudioMixingMode()
|
||||
|
||||
@@ -22,6 +22,7 @@ extension HybridVideoPlayer: VideoPlayerObserverDelegate {
|
||||
|
||||
func onRateChanged(rate: Float) {
|
||||
eventEmitter.onPlaybackRateChange(Double(rate))
|
||||
NowPlayingInfoCenterManager.shared.updateNowPlayingInfo()
|
||||
updateAndEmitPlaybackState()
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,16 @@ class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {
|
||||
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<Void> {
|
||||
return Promise.async { [weak self] in
|
||||
guard let self else {
|
||||
@@ -174,6 +184,7 @@ class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {
|
||||
}
|
||||
|
||||
func release() {
|
||||
NowPlayingInfoCenterManager.shared.removePlayer(player: player)
|
||||
self.player.replaceCurrentItem(with: nil)
|
||||
self.playerItem = nil
|
||||
|
||||
@@ -270,6 +281,7 @@ class HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {
|
||||
self.source = source
|
||||
self.playerItem = try await self.initializePlayerItem()
|
||||
self.player.replaceCurrentItem(with: self.playerItem)
|
||||
NowPlayingInfoCenterManager.shared.updateNowPlayingInfo()
|
||||
promise.resolve(withResult: ())
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,22 @@
|
||||
import Foundation
|
||||
|
||||
class HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec {
|
||||
func fromVideoConfig(config: NativeVideoConfig) throws -> any HybridVideoPlayerSourceSpec {
|
||||
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, initializeOnCreation: true)
|
||||
let config = NativeVideoConfig(
|
||||
uri: uri,
|
||||
externalSubtitles: nil,
|
||||
drm: nil,
|
||||
headers: nil,
|
||||
bufferConfig: nil,
|
||||
metadata: nil,
|
||||
initializeOnCreation: true
|
||||
)
|
||||
return try HybridVideoPlayerSource(config: config)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,9 @@ class HybridVideoViewViewManager: HybridVideoViewViewManagerSpec {
|
||||
}
|
||||
}
|
||||
|
||||
// Android only - no-op on iOS
|
||||
var surfaceType: SurfaceType = .surface
|
||||
|
||||
func enterFullscreen() throws {
|
||||
guard let view else {
|
||||
throw VideoViewError.viewIsDeallocated.error()
|
||||
|
||||
@@ -148,6 +148,9 @@ import AVKit
|
||||
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)
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
# 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++"
|
||||
@@ -44,12 +50,9 @@ target_sources(
|
||||
../nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp
|
||||
)
|
||||
|
||||
# Define a flag to check if we are building properly
|
||||
add_definitions(-DBUILDING_REACTNATIVEVIDEO_WITH_GENERATED_CMAKE_PROJECT)
|
||||
|
||||
# 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(
|
||||
target_compile_definitions(
|
||||
ReactNativeVideo PRIVATE
|
||||
-DFOLLY_NO_CONFIG=1
|
||||
-DFOLLY_HAVE_CLOCK_GETTIME=1
|
||||
|
||||
@@ -75,8 +75,7 @@ int initialize(JavaVM* vm) {
|
||||
[]() -> std::shared_ptr<HybridObject> {
|
||||
static DefaultConstructableObject<JHybridVideoPlayerFactorySpec::javaobject> object("com/margelo/nitro/video/HybridVideoPlayerFactory");
|
||||
auto instance = object.create();
|
||||
auto globalRef = jni::make_global(instance);
|
||||
return globalRef->cthis()->shared();
|
||||
return instance->cthis()->shared();
|
||||
}
|
||||
);
|
||||
HybridObjectRegistry::registerHybridObjectConstructor(
|
||||
@@ -84,8 +83,7 @@ int initialize(JavaVM* vm) {
|
||||
[]() -> std::shared_ptr<HybridObject> {
|
||||
static DefaultConstructableObject<JHybridVideoPlayerSourceFactorySpec::javaobject> object("com/margelo/nitro/video/HybridVideoPlayerSourceFactory");
|
||||
auto instance = object.create();
|
||||
auto globalRef = jni::make_global(instance);
|
||||
return globalRef->cthis()->shared();
|
||||
return instance->cthis()->shared();
|
||||
}
|
||||
);
|
||||
HybridObjectRegistry::registerHybridObjectConstructor(
|
||||
@@ -93,8 +91,7 @@ int initialize(JavaVM* vm) {
|
||||
[]() -> std::shared_ptr<HybridObject> {
|
||||
static DefaultConstructableObject<JHybridVideoViewViewManagerFactorySpec::javaobject> object("com/margelo/nitro/video/HybridVideoViewViewManagerFactory");
|
||||
auto instance = object.create();
|
||||
auto globalRef = jni::make_global(instance);
|
||||
return globalRef->cthis()->shared();
|
||||
return instance->cthis()->shared();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
70
packages/react-native-video/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp
generated
Normal file
70
packages/react-native-video/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp
generated
Normal file
@@ -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 <fbjni/fbjni.h>
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
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<JCustomVideoMetadata> {
|
||||
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<jni::JString>("title");
|
||||
jni::local_ref<jni::JString> title = this->getFieldValue(fieldTitle);
|
||||
static const auto fieldSubtitle = clazz->getField<jni::JString>("subtitle");
|
||||
jni::local_ref<jni::JString> subtitle = this->getFieldValue(fieldSubtitle);
|
||||
static const auto fieldDescription = clazz->getField<jni::JString>("description");
|
||||
jni::local_ref<jni::JString> description = this->getFieldValue(fieldDescription);
|
||||
static const auto fieldArtist = clazz->getField<jni::JString>("artist");
|
||||
jni::local_ref<jni::JString> artist = this->getFieldValue(fieldArtist);
|
||||
static const auto fieldImageUri = clazz->getField<jni::JString>("imageUri");
|
||||
jni::local_ref<jni::JString> 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<JCustomVideoMetadata::javaobject> 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
|
||||
@@ -25,6 +25,8 @@ namespace margelo::nitro::video { struct BufferConfig; }
|
||||
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 <memory>
|
||||
#include "HybridVideoPlayerSourceSpec.hpp"
|
||||
@@ -53,6 +55,8 @@ namespace margelo::nitro::video { struct Resolution; }
|
||||
#include "JLivePlaybackParams.hpp"
|
||||
#include "Resolution.hpp"
|
||||
#include "JResolution.hpp"
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
#include "JCustomVideoMetadata.hpp"
|
||||
|
||||
namespace margelo::nitro::video {
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace margelo::nitro::video { struct BufferConfig; }
|
||||
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.
|
||||
@@ -52,6 +54,8 @@ namespace margelo::nitro::video { enum class VideoOrientation; }
|
||||
#include "JLivePlaybackParams.hpp"
|
||||
#include "Resolution.hpp"
|
||||
#include "JResolution.hpp"
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
#include "JCustomVideoMetadata.hpp"
|
||||
#include "VideoInformation.hpp"
|
||||
#include "JVideoInformation.hpp"
|
||||
#include "VideoOrientation.hpp"
|
||||
|
||||
@@ -72,6 +72,15 @@ namespace margelo::nitro::video {
|
||||
auto __result = method(_javaPart);
|
||||
return __result->cthis()->shared_cast<JHybridVideoPlayerEventEmitterSpec>();
|
||||
}
|
||||
bool JHybridVideoPlayerSpec::getShowNotificationControls() {
|
||||
static const auto method = javaClassStatic()->getMethod<jboolean()>("getShowNotificationControls");
|
||||
auto __result = method(_javaPart);
|
||||
return static_cast<bool>(__result);
|
||||
}
|
||||
void JHybridVideoPlayerSpec::setShowNotificationControls(bool showNotificationControls) {
|
||||
static const auto method = javaClassStatic()->getMethod<void(jboolean /* showNotificationControls */)>("setShowNotificationControls");
|
||||
method(_javaPart, showNotificationControls);
|
||||
}
|
||||
VideoPlayerStatus JHybridVideoPlayerSpec::getStatus() {
|
||||
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JVideoPlayerStatus>()>("getStatus");
|
||||
auto __result = method(_javaPart);
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace margelo::nitro::video {
|
||||
// Properties
|
||||
std::shared_ptr<HybridVideoPlayerSourceSpec> getSource() override;
|
||||
std::shared_ptr<HybridVideoPlayerEventEmitterSpec> getEventEmitter() override;
|
||||
bool getShowNotificationControls() override;
|
||||
void setShowNotificationControls(bool showNotificationControls) override;
|
||||
VideoPlayerStatus getStatus() override;
|
||||
double getDuration() override;
|
||||
double getVolume() override;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
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 <memory>
|
||||
#include "HybridVideoPlayerSpec.hpp"
|
||||
@@ -18,6 +20,8 @@ namespace margelo::nitro::video { enum class ResizeMode; }
|
||||
#include "JHybridVideoPlayerSpec.hpp"
|
||||
#include "ResizeMode.hpp"
|
||||
#include "JResizeMode.hpp"
|
||||
#include "SurfaceType.hpp"
|
||||
#include "JSurfaceType.hpp"
|
||||
#include <functional>
|
||||
#include "JFunc_void_bool.hpp"
|
||||
#include "JFunc_void.hpp"
|
||||
@@ -99,6 +103,15 @@ namespace margelo::nitro::video {
|
||||
static const auto method = javaClassStatic()->getMethod<void(jboolean /* keepScreenAwake */)>("setKeepScreenAwake");
|
||||
method(_javaPart, keepScreenAwake);
|
||||
}
|
||||
SurfaceType JHybridVideoViewViewManagerSpec::getSurfaceType() {
|
||||
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JSurfaceType>()>("getSurfaceType");
|
||||
auto __result = method(_javaPart);
|
||||
return __result->toCpp();
|
||||
}
|
||||
void JHybridVideoViewViewManagerSpec::setSurfaceType(SurfaceType surfaceType) {
|
||||
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JSurfaceType> /* surfaceType */)>("setSurfaceType");
|
||||
method(_javaPart, JSurfaceType::fromCpp(surfaceType));
|
||||
}
|
||||
std::optional<std::function<void(bool /* isInPictureInPicture */)>> JHybridVideoViewViewManagerSpec::getOnPictureInPictureChange() {
|
||||
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JFunc_void_bool::javaobject>()>("getOnPictureInPictureChange_cxx");
|
||||
auto __result = method(_javaPart);
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace margelo::nitro::video {
|
||||
void setResizeMode(ResizeMode resizeMode) override;
|
||||
bool getKeepScreenAwake() override;
|
||||
void setKeepScreenAwake(bool keepScreenAwake) override;
|
||||
SurfaceType getSurfaceType() override;
|
||||
void setSurfaceType(SurfaceType surfaceType) override;
|
||||
std::optional<std::function<void(bool /* isInPictureInPicture */)>> getOnPictureInPictureChange() override;
|
||||
void setOnPictureInPictureChange(const std::optional<std::function<void(bool /* isInPictureInPicture */)>>& onPictureInPictureChange) override;
|
||||
std::optional<std::function<void(bool /* fullscreen */)>> getOnFullscreenChange() override;
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#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"
|
||||
@@ -62,6 +64,8 @@ namespace margelo::nitro::video {
|
||||
jni::local_ref<jni::JMap<jni::JString, jni::JString>> headers = this->getFieldValue(fieldHeaders);
|
||||
static const auto fieldBufferConfig = clazz->getField<JBufferConfig>("bufferConfig");
|
||||
jni::local_ref<JBufferConfig> bufferConfig = this->getFieldValue(fieldBufferConfig);
|
||||
static const auto fieldMetadata = clazz->getField<JCustomVideoMetadata>("metadata");
|
||||
jni::local_ref<JCustomVideoMetadata> metadata = this->getFieldValue(fieldMetadata);
|
||||
static const auto fieldInitializeOnCreation = clazz->getField<jni::JBoolean>("initializeOnCreation");
|
||||
jni::local_ref<jni::JBoolean> initializeOnCreation = this->getFieldValue(fieldInitializeOnCreation);
|
||||
return NativeVideoConfig(
|
||||
@@ -86,6 +90,7 @@ namespace margelo::nitro::video {
|
||||
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<bool>(initializeOnCreation->value())) : std::nullopt
|
||||
);
|
||||
}
|
||||
@@ -116,6 +121,7 @@ namespace margelo::nitro::video {
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
59
packages/react-native-video/nitrogen/generated/android/c++/JSurfaceType.hpp
generated
Normal file
59
packages/react-native-video/nitrogen/generated/android/c++/JSurfaceType.hpp
generated
Normal file
@@ -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 <fbjni/fbjni.h>
|
||||
#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<JSurfaceType> {
|
||||
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<int>("value");
|
||||
int ordinal = this->getFieldValue(fieldOrdinal);
|
||||
return static_cast<SurfaceType>(ordinal);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a Java/Kotlin-based enum with the given C++ enum's value.
|
||||
*/
|
||||
[[maybe_unused]]
|
||||
static jni::alias_ref<JSurfaceType> fromCpp(SurfaceType value) {
|
||||
static const auto clazz = javaClassStatic();
|
||||
static const auto fieldSURFACE = clazz->getStaticField<JSurfaceType>("SURFACE");
|
||||
static const auto fieldTEXTURE = clazz->getStaticField<JSurfaceType>("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<int>(value));
|
||||
throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace margelo::nitro::video
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -45,6 +45,12 @@ abstract class HybridVideoPlayerSpec: HybridObject() {
|
||||
@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
|
||||
|
||||
@@ -73,6 +73,12 @@ abstract class HybridVideoViewViewManagerSpec: HybridObject() {
|
||||
@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?
|
||||
|
||||
@@ -38,6 +38,9 @@ data class NativeVideoConfig
|
||||
val bufferConfig: BufferConfig?,
|
||||
@DoNotStrip
|
||||
@Keep
|
||||
val metadata: CustomVideoMetadata?,
|
||||
@DoNotStrip
|
||||
@Keep
|
||||
val initializeOnCreation: Boolean?
|
||||
) {
|
||||
/* main constructor */
|
||||
|
||||
21
packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt
generated
Normal file
21
packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt
generated
Normal file
@@ -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);
|
||||
}
|
||||
@@ -20,11 +20,11 @@
|
||||
namespace margelo::nitro::video::bridge::swift {
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerSourceSpec>
|
||||
std::shared_ptr<HybridVideoPlayerSourceSpec> create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoPlayerSourceSpec> create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -36,11 +36,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerEventEmitterSpec>
|
||||
std::shared_ptr<HybridVideoPlayerEventEmitterSpec> create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoPlayerEventEmitterSpec> create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -52,7 +52,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void()>
|
||||
Func_void create_Func_void(void* _Nonnull swiftClosureWrapper) {
|
||||
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();
|
||||
@@ -60,7 +60,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const std::exception_ptr& /* error */)>
|
||||
Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -68,11 +68,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerSpec>
|
||||
std::shared_ptr<HybridVideoPlayerSpec> create_std__shared_ptr_HybridVideoPlayerSpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoPlayerSpec> create_std__shared_ptr_HybridVideoPlayerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoPlayerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoPlayerSpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -84,11 +84,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerFactorySpec>
|
||||
std::shared_ptr<HybridVideoPlayerFactorySpec> create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoPlayerFactorySpec> create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -100,7 +100,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(bool /* hasAudioFocus */)>
|
||||
Func_void_bool create_Func_void_bool(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -108,7 +108,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const BandwidthData& /* data */)>
|
||||
Func_void_BandwidthData create_Func_void_BandwidthData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -116,7 +116,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const onLoadData& /* data */)>
|
||||
Func_void_onLoadData create_Func_void_onLoadData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -124,7 +124,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const onLoadStartData& /* data */)>
|
||||
Func_void_onLoadStartData create_Func_void_onLoadStartData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -132,7 +132,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const onPlaybackStateChangeData& /* data */)>
|
||||
Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -140,7 +140,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(double /* rate */)>
|
||||
Func_void_double create_Func_void_double(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -148,7 +148,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const onProgressData& /* data */)>
|
||||
Func_void_onProgressData create_Func_void_onProgressData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -156,7 +156,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const TimedMetadata& /* metadata */)>
|
||||
Func_void_TimedMetadata create_Func_void_TimedMetadata(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -164,7 +164,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const std::vector<std::string>& /* texts */)>
|
||||
Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* _Nonnull swiftClosureWrapper) {
|
||||
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<std::string>& texts) mutable -> void {
|
||||
swiftClosure.call(texts);
|
||||
@@ -172,7 +172,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const std::optional<TextTrack>& /* track */)>
|
||||
Func_void_std__optional_TextTrack_ create_Func_void_std__optional_TextTrack_(void* _Nonnull swiftClosureWrapper) {
|
||||
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<TextTrack>& track) mutable -> void {
|
||||
swiftClosure.call(track);
|
||||
@@ -180,7 +180,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const onVolumeChangeData& /* data */)>
|
||||
Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -188,7 +188,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(VideoPlayerStatus /* status */)>
|
||||
Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* _Nonnull swiftClosureWrapper) {
|
||||
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<int>(status));
|
||||
@@ -196,7 +196,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const std::string& /* result */)>
|
||||
Func_void_std__string create_Func_void_std__string(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -204,7 +204,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(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* _Nonnull swiftClosureWrapper) {
|
||||
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<Promise<std::shared_ptr<Promise<std::string>>>> {
|
||||
auto __result = swiftClosure.call(payload);
|
||||
@@ -213,7 +213,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>
|
||||
Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* _Nonnull swiftClosureWrapper) {
|
||||
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<Promise<std::string>>& result) mutable -> void {
|
||||
swiftClosure.call(result);
|
||||
@@ -221,7 +221,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const VideoInformation& /* result */)>
|
||||
Func_void_VideoInformation create_Func_void_VideoInformation(void* _Nonnull swiftClosureWrapper) {
|
||||
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);
|
||||
@@ -229,11 +229,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerSourceFactorySpec>
|
||||
std::shared_ptr<HybridVideoPlayerSourceFactorySpec> create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoPlayerSourceFactorySpec> create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -245,11 +245,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoViewViewManagerSpec>
|
||||
std::shared_ptr<HybridVideoViewViewManagerSpec> create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoViewViewManagerSpec> create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
@@ -261,11 +261,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoViewViewManagerFactorySpec>
|
||||
std::shared_ptr<HybridVideoViewViewManagerFactorySpec> create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* _Nonnull swiftUnsafePointer) {
|
||||
std::shared_ptr<HybridVideoViewViewManagerFactorySpec> create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
||||
ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);
|
||||
return std::make_shared<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift>(swiftPart);
|
||||
}
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType) {
|
||||
void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType) noexcept {
|
||||
std::shared_ptr<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift>(cppType);
|
||||
#ifdef NITRO_DEBUG
|
||||
if (swiftWrapper == nullptr) [[unlikely]] {
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
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.
|
||||
@@ -82,6 +84,7 @@ 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"
|
||||
@@ -107,6 +110,7 @@ namespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; }
|
||||
#include "onPlaybackStateChangeData.hpp"
|
||||
#include "onProgressData.hpp"
|
||||
#include "onVolumeChangeData.hpp"
|
||||
#include <NitroModules/FastVectorCopy.hpp>
|
||||
#include <NitroModules/Promise.hpp>
|
||||
#include <NitroModules/PromiseHolder.hpp>
|
||||
#include <NitroModules/Result.hpp>
|
||||
@@ -129,34 +133,34 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<HybridVideoPlayerSourceSpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoPlayerSourceSpec_ = std::shared_ptr<HybridVideoPlayerSourceSpec>;
|
||||
std::shared_ptr<HybridVideoPlayerSourceSpec> create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType);
|
||||
std::shared_ptr<HybridVideoPlayerSourceSpec> 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<HybridVideoPlayerSourceSpec>
|
||||
using std__weak_ptr_HybridVideoPlayerSourceSpec_ = std::weak_ptr<HybridVideoPlayerSourceSpec>;
|
||||
inline std__weak_ptr_HybridVideoPlayerSourceSpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(const std::shared_ptr<HybridVideoPlayerSourceSpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoPlayerSourceSpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(const std::shared_ptr<HybridVideoPlayerSourceSpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerEventEmitterSpec>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<HybridVideoPlayerEventEmitterSpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ = std::shared_ptr<HybridVideoPlayerEventEmitterSpec>;
|
||||
std::shared_ptr<HybridVideoPlayerEventEmitterSpec> create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType);
|
||||
std::shared_ptr<HybridVideoPlayerEventEmitterSpec> 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<HybridVideoPlayerEventEmitterSpec>
|
||||
using std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ = std::weak_ptr<HybridVideoPlayerEventEmitterSpec>;
|
||||
inline std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(const std::shared_ptr<HybridVideoPlayerEventEmitterSpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(const std::shared_ptr<HybridVideoPlayerEventEmitterSpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: std::shared_ptr<Promise<void>>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<Promise<void>>`.
|
||||
*/
|
||||
using std__shared_ptr_Promise_void__ = std::shared_ptr<Promise<void>>;
|
||||
inline std::shared_ptr<Promise<void>> create_std__shared_ptr_Promise_void__() {
|
||||
inline std::shared_ptr<Promise<void>> create_std__shared_ptr_Promise_void__() noexcept {
|
||||
return Promise<void>::create();
|
||||
}
|
||||
inline PromiseHolder<void> wrap_std__shared_ptr_Promise_void__(std::shared_ptr<Promise<void>> promise) {
|
||||
inline PromiseHolder<void> wrap_std__shared_ptr_Promise_void__(std::shared_ptr<Promise<void>> promise) noexcept {
|
||||
return PromiseHolder<void>(std::move(promise));
|
||||
}
|
||||
|
||||
@@ -171,14 +175,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_Wrapper(std::function<void()>&& func): _function(std::make_unique<std::function<void()>>(std::move(func))) {}
|
||||
inline void call() const {
|
||||
inline void call() const noexcept {
|
||||
_function->operator()();
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void()>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void create_Func_void(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_Wrapper wrap_Func_void(Func_void value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -193,14 +197,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_std__exception_ptr_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_std__exception_ptr_Wrapper(std::function<void(const std::exception_ptr& /* error */)>&& func): _function(std::make_unique<std::function<void(const std::exception_ptr& /* error */)>>(std::move(func))) {}
|
||||
inline void call(std::exception_ptr error) const {
|
||||
inline void call(std::exception_ptr error) const noexcept {
|
||||
_function->operator()(error);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const std::exception_ptr& /* error */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_std__exception_ptr_Wrapper wrap_Func_void_std__exception_ptr(Func_void_std__exception_ptr value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -209,28 +213,41 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>>`.
|
||||
*/
|
||||
using std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__ = std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>>;
|
||||
inline std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>> create_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) {
|
||||
inline std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>> create_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) noexcept {
|
||||
return std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::shared_ptr<HybridVideoPlayerSourceSpec> get_std__optional_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSourceSpec>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<std::string>
|
||||
/**
|
||||
* Specialized version of `std::optional<std::string>`.
|
||||
*/
|
||||
using std__optional_std__string_ = std::optional<std::string>;
|
||||
inline std::optional<std::string> create_std__optional_std__string_(const std::string& value) {
|
||||
inline std::optional<std::string> create_std__optional_std__string_(const std::string& value) noexcept {
|
||||
return std::optional<std::string>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__string_(const std::optional<std::string>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::string get_std__optional_std__string_(const std::optional<std::string>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::vector<TextTrack>
|
||||
/**
|
||||
* Specialized version of `std::vector<TextTrack>`.
|
||||
*/
|
||||
using std__vector_TextTrack_ = std::vector<TextTrack>;
|
||||
inline std::vector<TextTrack> create_std__vector_TextTrack_(size_t size) {
|
||||
std::vector<TextTrack> vector;
|
||||
vector.reserve(size);
|
||||
return vector;
|
||||
inline std::vector<TextTrack> copy_std__vector_TextTrack_(const TextTrack* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept {
|
||||
return margelo::nitro::FastVectorCopy<TextTrack>(data, size);
|
||||
}
|
||||
inline const TextTrack* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_TextTrack_(const std::vector<TextTrack>& vector) noexcept {
|
||||
return vector.data();
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<TextTrack>
|
||||
@@ -238,46 +255,52 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<TextTrack>`.
|
||||
*/
|
||||
using std__optional_TextTrack_ = std::optional<TextTrack>;
|
||||
inline std::optional<TextTrack> create_std__optional_TextTrack_(const TextTrack& value) {
|
||||
inline std::optional<TextTrack> create_std__optional_TextTrack_(const TextTrack& value) noexcept {
|
||||
return std::optional<TextTrack>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_TextTrack_(const std::optional<TextTrack>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline TextTrack get_std__optional_TextTrack_(const std::optional<TextTrack>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoPlayerSpec>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<HybridVideoPlayerSpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoPlayerSpec_ = std::shared_ptr<HybridVideoPlayerSpec>;
|
||||
std::shared_ptr<HybridVideoPlayerSpec> create_std__shared_ptr_HybridVideoPlayerSpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType);
|
||||
std::shared_ptr<HybridVideoPlayerSpec> 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<HybridVideoPlayerSpec>
|
||||
using std__weak_ptr_HybridVideoPlayerSpec_ = std::weak_ptr<HybridVideoPlayerSpec>;
|
||||
inline std__weak_ptr_HybridVideoPlayerSpec_ weakify_std__shared_ptr_HybridVideoPlayerSpec_(const std::shared_ptr<HybridVideoPlayerSpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoPlayerSpec_ weakify_std__shared_ptr_HybridVideoPlayerSpec_(const std::shared_ptr<HybridVideoPlayerSpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<std::shared_ptr<Promise<void>>>
|
||||
using Result_std__shared_ptr_Promise_void___ = Result<std::shared_ptr<Promise<void>>>;
|
||||
inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr<Promise<void>>& value) {
|
||||
inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr<Promise<void>>& value) noexcept {
|
||||
return Result<std::shared_ptr<Promise<void>>>::withValue(value);
|
||||
}
|
||||
inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::exception_ptr& error) {
|
||||
inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::shared_ptr<Promise<void>>>::withError(error);
|
||||
}
|
||||
|
||||
// pragma MARK: Result<std::vector<TextTrack>>
|
||||
using Result_std__vector_TextTrack__ = Result<std::vector<TextTrack>>;
|
||||
inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::vector<TextTrack>& value) {
|
||||
inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::vector<TextTrack>& value) noexcept {
|
||||
return Result<std::vector<TextTrack>>::withValue(value);
|
||||
}
|
||||
inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::exception_ptr& error) {
|
||||
inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::vector<TextTrack>>::withError(error);
|
||||
}
|
||||
|
||||
// pragma MARK: Result<void>
|
||||
using Result_void_ = Result<void>;
|
||||
inline Result_void_ create_Result_void_() {
|
||||
inline Result_void_ create_Result_void_() noexcept {
|
||||
return Result<void>::withValue();
|
||||
}
|
||||
inline Result_void_ create_Result_void_(const std::exception_ptr& error) {
|
||||
inline Result_void_ create_Result_void_(const std::exception_ptr& error) noexcept {
|
||||
return Result<void>::withError(error);
|
||||
}
|
||||
|
||||
@@ -286,19 +309,19 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<HybridVideoPlayerFactorySpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoPlayerFactorySpec_ = std::shared_ptr<HybridVideoPlayerFactorySpec>;
|
||||
std::shared_ptr<HybridVideoPlayerFactorySpec> create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType);
|
||||
std::shared_ptr<HybridVideoPlayerFactorySpec> 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<HybridVideoPlayerFactorySpec>
|
||||
using std__weak_ptr_HybridVideoPlayerFactorySpec_ = std::weak_ptr<HybridVideoPlayerFactorySpec>;
|
||||
inline std__weak_ptr_HybridVideoPlayerFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(const std::shared_ptr<HybridVideoPlayerFactorySpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoPlayerFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(const std::shared_ptr<HybridVideoPlayerFactorySpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<std::shared_ptr<HybridVideoPlayerSpec>>
|
||||
using Result_std__shared_ptr_HybridVideoPlayerSpec__ = Result<std::shared_ptr<HybridVideoPlayerSpec>>;
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) {
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoPlayerSpec>>::withValue(value);
|
||||
}
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::exception_ptr& error) {
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoPlayerSpec>>::withError(error);
|
||||
}
|
||||
|
||||
@@ -313,14 +336,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_bool_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_bool_Wrapper(std::function<void(bool /* hasAudioFocus */)>&& func): _function(std::make_unique<std::function<void(bool /* hasAudioFocus */)>>(std::move(func))) {}
|
||||
inline void call(bool hasAudioFocus) const {
|
||||
inline void call(bool hasAudioFocus) const noexcept {
|
||||
_function->operator()(hasAudioFocus);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(bool /* hasAudioFocus */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_bool create_Func_void_bool(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_bool_Wrapper wrap_Func_void_bool(Func_void_bool value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -329,9 +352,15 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<double>`.
|
||||
*/
|
||||
using std__optional_double_ = std::optional<double>;
|
||||
inline std::optional<double> create_std__optional_double_(const double& value) {
|
||||
inline std::optional<double> create_std__optional_double_(const double& value) noexcept {
|
||||
return std::optional<double>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_double_(const std::optional<double>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline double get_std__optional_double_(const std::optional<double>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const BandwidthData& /* data */)>
|
||||
/**
|
||||
@@ -344,14 +373,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_BandwidthData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_BandwidthData_Wrapper(std::function<void(const BandwidthData& /* data */)>&& func): _function(std::make_unique<std::function<void(const BandwidthData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(BandwidthData data) const {
|
||||
inline void call(BandwidthData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const BandwidthData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_BandwidthData create_Func_void_BandwidthData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_BandwidthData_Wrapper wrap_Func_void_BandwidthData(Func_void_BandwidthData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -366,14 +395,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_onLoadData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_onLoadData_Wrapper(std::function<void(const onLoadData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onLoadData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(onLoadData data) const {
|
||||
inline void call(onLoadData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const onLoadData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_onLoadData create_Func_void_onLoadData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_onLoadData_Wrapper wrap_Func_void_onLoadData(Func_void_onLoadData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -388,14 +417,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_onLoadStartData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_onLoadStartData_Wrapper(std::function<void(const onLoadStartData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onLoadStartData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(onLoadStartData data) const {
|
||||
inline void call(onLoadStartData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const onLoadStartData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_onLoadStartData create_Func_void_onLoadStartData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_onLoadStartData_Wrapper wrap_Func_void_onLoadStartData(Func_void_onLoadStartData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -410,14 +439,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_onPlaybackStateChangeData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_onPlaybackStateChangeData_Wrapper(std::function<void(const onPlaybackStateChangeData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onPlaybackStateChangeData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(onPlaybackStateChangeData data) const {
|
||||
inline void call(onPlaybackStateChangeData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const onPlaybackStateChangeData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_onPlaybackStateChangeData_Wrapper wrap_Func_void_onPlaybackStateChangeData(Func_void_onPlaybackStateChangeData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -432,14 +461,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_double_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_double_Wrapper(std::function<void(double /* rate */)>&& func): _function(std::make_unique<std::function<void(double /* rate */)>>(std::move(func))) {}
|
||||
inline void call(double rate) const {
|
||||
inline void call(double rate) const noexcept {
|
||||
_function->operator()(rate);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(double /* rate */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_double create_Func_void_double(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_double_Wrapper wrap_Func_void_double(Func_void_double value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -454,14 +483,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_onProgressData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_onProgressData_Wrapper(std::function<void(const onProgressData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onProgressData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(onProgressData data) const {
|
||||
inline void call(onProgressData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const onProgressData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_onProgressData create_Func_void_onProgressData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_onProgressData_Wrapper wrap_Func_void_onProgressData(Func_void_onProgressData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -470,10 +499,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::vector<TimedMetadataObject>`.
|
||||
*/
|
||||
using std__vector_TimedMetadataObject_ = std::vector<TimedMetadataObject>;
|
||||
inline std::vector<TimedMetadataObject> create_std__vector_TimedMetadataObject_(size_t size) {
|
||||
std::vector<TimedMetadataObject> vector;
|
||||
vector.reserve(size);
|
||||
return vector;
|
||||
inline std::vector<TimedMetadataObject> copy_std__vector_TimedMetadataObject_(const TimedMetadataObject* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept {
|
||||
return margelo::nitro::FastVectorCopy<TimedMetadataObject>(data, size);
|
||||
}
|
||||
inline const TimedMetadataObject* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_TimedMetadataObject_(const std::vector<TimedMetadataObject>& vector) noexcept {
|
||||
return vector.data();
|
||||
}
|
||||
|
||||
// pragma MARK: std::function<void(const TimedMetadata& /* metadata */)>
|
||||
@@ -487,14 +517,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_TimedMetadata_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_TimedMetadata_Wrapper(std::function<void(const TimedMetadata& /* metadata */)>&& func): _function(std::make_unique<std::function<void(const TimedMetadata& /* metadata */)>>(std::move(func))) {}
|
||||
inline void call(TimedMetadata metadata) const {
|
||||
inline void call(TimedMetadata metadata) const noexcept {
|
||||
_function->operator()(metadata);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const TimedMetadata& /* metadata */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_TimedMetadata create_Func_void_TimedMetadata(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_TimedMetadata_Wrapper wrap_Func_void_TimedMetadata(Func_void_TimedMetadata value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -503,7 +533,7 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::vector<std::string>`.
|
||||
*/
|
||||
using std__vector_std__string_ = std::vector<std::string>;
|
||||
inline std::vector<std::string> create_std__vector_std__string_(size_t size) {
|
||||
inline std::vector<std::string> create_std__vector_std__string_(size_t size) noexcept {
|
||||
std::vector<std::string> vector;
|
||||
vector.reserve(size);
|
||||
return vector;
|
||||
@@ -520,14 +550,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_std__vector_std__string__Wrapper final {
|
||||
public:
|
||||
explicit Func_void_std__vector_std__string__Wrapper(std::function<void(const std::vector<std::string>& /* texts */)>&& func): _function(std::make_unique<std::function<void(const std::vector<std::string>& /* texts */)>>(std::move(func))) {}
|
||||
inline void call(std::vector<std::string> texts) const {
|
||||
inline void call(std::vector<std::string> texts) const noexcept {
|
||||
_function->operator()(texts);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const std::vector<std::string>& /* texts */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_std__vector_std__string__Wrapper wrap_Func_void_std__vector_std__string_(Func_void_std__vector_std__string_ value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -542,14 +572,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_std__optional_TextTrack__Wrapper final {
|
||||
public:
|
||||
explicit Func_void_std__optional_TextTrack__Wrapper(std::function<void(const std::optional<TextTrack>& /* track */)>&& func): _function(std::make_unique<std::function<void(const std::optional<TextTrack>& /* track */)>>(std::move(func))) {}
|
||||
inline void call(std::optional<TextTrack> track) const {
|
||||
inline void call(std::optional<TextTrack> track) const noexcept {
|
||||
_function->operator()(track);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const std::optional<TextTrack>& /* track */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_std__optional_TextTrack_ create_Func_void_std__optional_TextTrack_(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_std__optional_TextTrack__Wrapper wrap_Func_void_std__optional_TextTrack_(Func_void_std__optional_TextTrack_ value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -564,14 +594,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_onVolumeChangeData_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_onVolumeChangeData_Wrapper(std::function<void(const onVolumeChangeData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onVolumeChangeData& /* data */)>>(std::move(func))) {}
|
||||
inline void call(onVolumeChangeData data) const {
|
||||
inline void call(onVolumeChangeData data) const noexcept {
|
||||
_function->operator()(data);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const onVolumeChangeData& /* data */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_onVolumeChangeData_Wrapper wrap_Func_void_onVolumeChangeData(Func_void_onVolumeChangeData value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -586,14 +616,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_VideoPlayerStatus_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_VideoPlayerStatus_Wrapper(std::function<void(VideoPlayerStatus /* status */)>&& func): _function(std::make_unique<std::function<void(VideoPlayerStatus /* status */)>>(std::move(func))) {}
|
||||
inline void call(int status) const {
|
||||
inline void call(int status) const noexcept {
|
||||
_function->operator()(static_cast<VideoPlayerStatus>(status));
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(VideoPlayerStatus /* status */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_VideoPlayerStatus_Wrapper wrap_Func_void_VideoPlayerStatus(Func_void_VideoPlayerStatus value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -602,10 +632,11 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::vector<NativeExternalSubtitle>`.
|
||||
*/
|
||||
using std__vector_NativeExternalSubtitle_ = std::vector<NativeExternalSubtitle>;
|
||||
inline std::vector<NativeExternalSubtitle> create_std__vector_NativeExternalSubtitle_(size_t size) {
|
||||
std::vector<NativeExternalSubtitle> vector;
|
||||
vector.reserve(size);
|
||||
return vector;
|
||||
inline std::vector<NativeExternalSubtitle> copy_std__vector_NativeExternalSubtitle_(const NativeExternalSubtitle* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept {
|
||||
return margelo::nitro::FastVectorCopy<NativeExternalSubtitle>(data, size);
|
||||
}
|
||||
inline const NativeExternalSubtitle* CONTIGUOUS_MEMORY NON_NULL get_data_std__vector_NativeExternalSubtitle_(const std::vector<NativeExternalSubtitle>& vector) noexcept {
|
||||
return vector.data();
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<std::vector<NativeExternalSubtitle>>
|
||||
@@ -613,21 +644,27 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<std::vector<NativeExternalSubtitle>>`.
|
||||
*/
|
||||
using std__optional_std__vector_NativeExternalSubtitle__ = std::optional<std::vector<NativeExternalSubtitle>>;
|
||||
inline std::optional<std::vector<NativeExternalSubtitle>> create_std__optional_std__vector_NativeExternalSubtitle__(const std::vector<NativeExternalSubtitle>& value) {
|
||||
inline std::optional<std::vector<NativeExternalSubtitle>> create_std__optional_std__vector_NativeExternalSubtitle__(const std::vector<NativeExternalSubtitle>& value) noexcept {
|
||||
return std::optional<std::vector<NativeExternalSubtitle>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__vector_NativeExternalSubtitle__(const std::optional<std::vector<NativeExternalSubtitle>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::vector<NativeExternalSubtitle> get_std__optional_std__vector_NativeExternalSubtitle__(const std::optional<std::vector<NativeExternalSubtitle>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::unordered_map<std::string, std::string>
|
||||
/**
|
||||
* Specialized version of `std::unordered_map<std::string, std::string>`.
|
||||
*/
|
||||
using std__unordered_map_std__string__std__string_ = std::unordered_map<std::string, std::string>;
|
||||
inline std::unordered_map<std::string, std::string> create_std__unordered_map_std__string__std__string_(size_t size) {
|
||||
inline std::unordered_map<std::string, std::string> create_std__unordered_map_std__string__std__string_(size_t size) noexcept {
|
||||
std::unordered_map<std::string, std::string> map;
|
||||
map.reserve(size);
|
||||
return map;
|
||||
}
|
||||
inline std::vector<std::string> get_std__unordered_map_std__string__std__string__keys(const std__unordered_map_std__string__std__string_& map) {
|
||||
inline std::vector<std::string> get_std__unordered_map_std__string__std__string__keys(const std__unordered_map_std__string__std__string_& map) noexcept {
|
||||
std::vector<std::string> keys;
|
||||
keys.reserve(map.size());
|
||||
for (const auto& entry : map) {
|
||||
@@ -635,10 +672,10 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
}
|
||||
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) {
|
||||
return map.at(key);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -647,28 +684,40 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<std::unordered_map<std::string, std::string>>`.
|
||||
*/
|
||||
using std__optional_std__unordered_map_std__string__std__string__ = std::optional<std::unordered_map<std::string, std::string>>;
|
||||
inline std::optional<std::unordered_map<std::string, std::string>> create_std__optional_std__unordered_map_std__string__std__string__(const std::unordered_map<std::string, std::string>& value) {
|
||||
inline std::optional<std::unordered_map<std::string, std::string>> create_std__optional_std__unordered_map_std__string__std__string__(const std::unordered_map<std::string, std::string>& value) noexcept {
|
||||
return std::optional<std::unordered_map<std::string, std::string>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__unordered_map_std__string__std__string__(const std::optional<std::unordered_map<std::string, std::string>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::unordered_map<std::string, std::string> get_std__optional_std__unordered_map_std__string__std__string__(const std::optional<std::unordered_map<std::string, std::string>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<bool>
|
||||
/**
|
||||
* Specialized version of `std::optional<bool>`.
|
||||
*/
|
||||
using std__optional_bool_ = std::optional<bool>;
|
||||
inline std::optional<bool> create_std__optional_bool_(const bool& value) {
|
||||
inline std::optional<bool> create_std__optional_bool_(const bool& value) noexcept {
|
||||
return std::optional<bool>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_bool_(const std::optional<bool>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline bool get_std__optional_bool_(const std::optional<bool>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<Promise<std::string>>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<Promise<std::string>>`.
|
||||
*/
|
||||
using std__shared_ptr_Promise_std__string__ = std::shared_ptr<Promise<std::string>>;
|
||||
inline std::shared_ptr<Promise<std::string>> create_std__shared_ptr_Promise_std__string__() {
|
||||
inline std::shared_ptr<Promise<std::string>> create_std__shared_ptr_Promise_std__string__() noexcept {
|
||||
return Promise<std::string>::create();
|
||||
}
|
||||
inline PromiseHolder<std::string> wrap_std__shared_ptr_Promise_std__string__(std::shared_ptr<Promise<std::string>> promise) {
|
||||
inline PromiseHolder<std::string> wrap_std__shared_ptr_Promise_std__string__(std::shared_ptr<Promise<std::string>> promise) noexcept {
|
||||
return PromiseHolder<std::string>(std::move(promise));
|
||||
}
|
||||
|
||||
@@ -683,14 +732,14 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_std__string_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_std__string_Wrapper(std::function<void(const std::string& /* result */)>&& func): _function(std::make_unique<std::function<void(const std::string& /* result */)>>(std::move(func))) {}
|
||||
inline void call(std::string result) const {
|
||||
inline void call(std::string result) const noexcept {
|
||||
_function->operator()(result);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const std::string& /* result */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_std__string create_Func_void_std__string(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_std__string_Wrapper wrap_Func_void_std__string(Func_void_std__string value) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -705,15 +754,15 @@ namespace margelo::nitro::video::bridge::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<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>&& func): _function(std::make_unique<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>(std::move(func))) {}
|
||||
inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> call(OnGetLicensePayload payload) const {
|
||||
inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> call(OnGetLicensePayload payload) const noexcept {
|
||||
auto __result = _function->operator()(payload);
|
||||
return __result;
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(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* _Nonnull swiftClosureWrapper);
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -722,10 +771,10 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>`.
|
||||
*/
|
||||
using std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ = std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>;
|
||||
inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____() {
|
||||
inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____() noexcept {
|
||||
return Promise<std::shared_ptr<Promise<std::string>>>::create();
|
||||
}
|
||||
inline PromiseHolder<std::shared_ptr<Promise<std::string>>> wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> promise) {
|
||||
inline PromiseHolder<std::shared_ptr<Promise<std::string>>> wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> promise) noexcept {
|
||||
return PromiseHolder<std::shared_ptr<Promise<std::string>>>(std::move(promise));
|
||||
}
|
||||
|
||||
@@ -740,14 +789,14 @@ namespace margelo::nitro::video::bridge::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<void(const std::shared_ptr<Promise<std::string>>& /* result */)>&& func): _function(std::make_unique<std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>>(std::move(func))) {}
|
||||
inline void call(std::shared_ptr<Promise<std::string>> result) const {
|
||||
inline void call(std::shared_ptr<Promise<std::string>> result) const noexcept {
|
||||
_function->operator()(result);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* _Nonnull swiftClosureWrapper);
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -756,55 +805,94 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& / * payload * /)>>`.
|
||||
*/
|
||||
using std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ = std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>;
|
||||
inline std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& value) {
|
||||
inline std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& value) noexcept {
|
||||
return std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(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<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)> get_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<NativeDrmParams>
|
||||
/**
|
||||
* Specialized version of `std::optional<NativeDrmParams>`.
|
||||
*/
|
||||
using std__optional_NativeDrmParams_ = std::optional<NativeDrmParams>;
|
||||
inline std::optional<NativeDrmParams> create_std__optional_NativeDrmParams_(const NativeDrmParams& value) {
|
||||
inline std::optional<NativeDrmParams> create_std__optional_NativeDrmParams_(const NativeDrmParams& value) noexcept {
|
||||
return std::optional<NativeDrmParams>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_NativeDrmParams_(const std::optional<NativeDrmParams>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline NativeDrmParams get_std__optional_NativeDrmParams_(const std::optional<NativeDrmParams>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<LivePlaybackParams>
|
||||
/**
|
||||
* Specialized version of `std::optional<LivePlaybackParams>`.
|
||||
*/
|
||||
using std__optional_LivePlaybackParams_ = std::optional<LivePlaybackParams>;
|
||||
inline std::optional<LivePlaybackParams> create_std__optional_LivePlaybackParams_(const LivePlaybackParams& value) {
|
||||
inline std::optional<LivePlaybackParams> create_std__optional_LivePlaybackParams_(const LivePlaybackParams& value) noexcept {
|
||||
return std::optional<LivePlaybackParams>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_LivePlaybackParams_(const std::optional<LivePlaybackParams>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline LivePlaybackParams get_std__optional_LivePlaybackParams_(const std::optional<LivePlaybackParams>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<Resolution>
|
||||
/**
|
||||
* Specialized version of `std::optional<Resolution>`.
|
||||
*/
|
||||
using std__optional_Resolution_ = std::optional<Resolution>;
|
||||
inline std::optional<Resolution> create_std__optional_Resolution_(const Resolution& value) {
|
||||
inline std::optional<Resolution> create_std__optional_Resolution_(const Resolution& value) noexcept {
|
||||
return std::optional<Resolution>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_Resolution_(const std::optional<Resolution>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline Resolution get_std__optional_Resolution_(const std::optional<Resolution>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<BufferConfig>
|
||||
/**
|
||||
* Specialized version of `std::optional<BufferConfig>`.
|
||||
*/
|
||||
using std__optional_BufferConfig_ = std::optional<BufferConfig>;
|
||||
inline std::optional<BufferConfig> create_std__optional_BufferConfig_(const BufferConfig& value) {
|
||||
inline std::optional<BufferConfig> create_std__optional_BufferConfig_(const BufferConfig& value) noexcept {
|
||||
return std::optional<BufferConfig>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_BufferConfig_(const std::optional<BufferConfig>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline BufferConfig get_std__optional_BufferConfig_(const std::optional<BufferConfig>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<CustomVideoMetadata>
|
||||
/**
|
||||
* Specialized version of `std::optional<CustomVideoMetadata>`.
|
||||
*/
|
||||
using std__optional_CustomVideoMetadata_ = std::optional<CustomVideoMetadata>;
|
||||
inline std::optional<CustomVideoMetadata> create_std__optional_CustomVideoMetadata_(const CustomVideoMetadata& value) {
|
||||
return std::optional<CustomVideoMetadata>(value);
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<Promise<VideoInformation>>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<Promise<VideoInformation>>`.
|
||||
*/
|
||||
using std__shared_ptr_Promise_VideoInformation__ = std::shared_ptr<Promise<VideoInformation>>;
|
||||
inline std::shared_ptr<Promise<VideoInformation>> create_std__shared_ptr_Promise_VideoInformation__() {
|
||||
inline std::shared_ptr<Promise<VideoInformation>> create_std__shared_ptr_Promise_VideoInformation__() noexcept {
|
||||
return Promise<VideoInformation>::create();
|
||||
}
|
||||
inline PromiseHolder<VideoInformation> wrap_std__shared_ptr_Promise_VideoInformation__(std::shared_ptr<Promise<VideoInformation>> promise) {
|
||||
inline PromiseHolder<VideoInformation> wrap_std__shared_ptr_Promise_VideoInformation__(std::shared_ptr<Promise<VideoInformation>> promise) noexcept {
|
||||
return PromiseHolder<VideoInformation>(std::move(promise));
|
||||
}
|
||||
|
||||
@@ -819,23 +907,23 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
class Func_void_VideoInformation_Wrapper final {
|
||||
public:
|
||||
explicit Func_void_VideoInformation_Wrapper(std::function<void(const VideoInformation& /* result */)>&& func): _function(std::make_unique<std::function<void(const VideoInformation& /* result */)>>(std::move(func))) {}
|
||||
inline void call(VideoInformation result) const {
|
||||
inline void call(VideoInformation result) const noexcept {
|
||||
_function->operator()(result);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<std::function<void(const VideoInformation& /* result */)>> _function;
|
||||
} SWIFT_NONCOPYABLE;
|
||||
Func_void_VideoInformation create_Func_void_VideoInformation(void* _Nonnull swiftClosureWrapper);
|
||||
inline Func_void_VideoInformation_Wrapper wrap_Func_void_VideoInformation(Func_void_VideoInformation value) {
|
||||
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<std::shared_ptr<Promise<VideoInformation>>>
|
||||
using Result_std__shared_ptr_Promise_VideoInformation___ = Result<std::shared_ptr<Promise<VideoInformation>>>;
|
||||
inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::shared_ptr<Promise<VideoInformation>>& value) {
|
||||
inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::shared_ptr<Promise<VideoInformation>>& value) noexcept {
|
||||
return Result<std::shared_ptr<Promise<VideoInformation>>>::withValue(value);
|
||||
}
|
||||
inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::exception_ptr& error) {
|
||||
inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::shared_ptr<Promise<VideoInformation>>>::withError(error);
|
||||
}
|
||||
|
||||
@@ -844,19 +932,19 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<HybridVideoPlayerSourceFactorySpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ = std::shared_ptr<HybridVideoPlayerSourceFactorySpec>;
|
||||
std::shared_ptr<HybridVideoPlayerSourceFactorySpec> create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType);
|
||||
std::shared_ptr<HybridVideoPlayerSourceFactorySpec> 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<HybridVideoPlayerSourceFactorySpec>
|
||||
using std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ = std::weak_ptr<HybridVideoPlayerSourceFactorySpec>;
|
||||
inline std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(const std::shared_ptr<HybridVideoPlayerSourceFactorySpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(const std::shared_ptr<HybridVideoPlayerSourceFactorySpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>
|
||||
using Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ = Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>;
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) {
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>::withValue(value);
|
||||
}
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::exception_ptr& error) {
|
||||
inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>::withError(error);
|
||||
}
|
||||
|
||||
@@ -865,55 +953,79 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::optional<std::shared_ptr<HybridVideoPlayerSpec>>`.
|
||||
*/
|
||||
using std__optional_std__shared_ptr_HybridVideoPlayerSpec__ = std::optional<std::shared_ptr<HybridVideoPlayerSpec>>;
|
||||
inline std::optional<std::shared_ptr<HybridVideoPlayerSpec>> create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) {
|
||||
inline std::optional<std::shared_ptr<HybridVideoPlayerSpec>> create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) noexcept {
|
||||
return std::optional<std::shared_ptr<HybridVideoPlayerSpec>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::shared_ptr<HybridVideoPlayerSpec> get_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<std::function<void(bool /* isInPictureInPicture */)>>
|
||||
/**
|
||||
* Specialized version of `std::optional<std::function<void(bool / * isInPictureInPicture * /)>>`.
|
||||
*/
|
||||
using std__optional_std__function_void_bool____isInPictureInPicture______ = std::optional<std::function<void(bool /* isInPictureInPicture */)>>;
|
||||
inline std::optional<std::function<void(bool /* isInPictureInPicture */)>> create_std__optional_std__function_void_bool____isInPictureInPicture______(const std::function<void(bool /* isInPictureInPicture */)>& value) {
|
||||
inline std::optional<std::function<void(bool /* isInPictureInPicture */)>> create_std__optional_std__function_void_bool____isInPictureInPicture______(const std::function<void(bool /* isInPictureInPicture */)>& value) noexcept {
|
||||
return std::optional<std::function<void(bool /* isInPictureInPicture */)>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__function_void_bool____isInPictureInPicture______(const std::optional<std::function<void(bool /* isInPictureInPicture */)>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::function<void(bool /* isInPictureInPicture */)> get_std__optional_std__function_void_bool____isInPictureInPicture______(const std::optional<std::function<void(bool /* isInPictureInPicture */)>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<std::function<void(bool /* fullscreen */)>>
|
||||
/**
|
||||
* Specialized version of `std::optional<std::function<void(bool / * fullscreen * /)>>`.
|
||||
*/
|
||||
using std__optional_std__function_void_bool____fullscreen______ = std::optional<std::function<void(bool /* fullscreen */)>>;
|
||||
inline std::optional<std::function<void(bool /* fullscreen */)>> create_std__optional_std__function_void_bool____fullscreen______(const std::function<void(bool /* fullscreen */)>& value) {
|
||||
inline std::optional<std::function<void(bool /* fullscreen */)>> create_std__optional_std__function_void_bool____fullscreen______(const std::function<void(bool /* fullscreen */)>& value) noexcept {
|
||||
return std::optional<std::function<void(bool /* fullscreen */)>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__function_void_bool____fullscreen______(const std::optional<std::function<void(bool /* fullscreen */)>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::function<void(bool /* fullscreen */)> get_std__optional_std__function_void_bool____fullscreen______(const std::optional<std::function<void(bool /* fullscreen */)>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::optional<std::function<void()>>
|
||||
/**
|
||||
* Specialized version of `std::optional<std::function<void()>>`.
|
||||
*/
|
||||
using std__optional_std__function_void____ = std::optional<std::function<void()>>;
|
||||
inline std::optional<std::function<void()>> create_std__optional_std__function_void____(const std::function<void()>& value) {
|
||||
inline std::optional<std::function<void()>> create_std__optional_std__function_void____(const std::function<void()>& value) noexcept {
|
||||
return std::optional<std::function<void()>>(value);
|
||||
}
|
||||
inline bool has_value_std__optional_std__function_void____(const std::optional<std::function<void()>>& optional) noexcept {
|
||||
return optional.has_value();
|
||||
}
|
||||
inline std::function<void()> get_std__optional_std__function_void____(const std::optional<std::function<void()>>& optional) noexcept {
|
||||
return *optional;
|
||||
}
|
||||
|
||||
// pragma MARK: std::shared_ptr<HybridVideoViewViewManagerSpec>
|
||||
/**
|
||||
* Specialized version of `std::shared_ptr<HybridVideoViewViewManagerSpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoViewViewManagerSpec_ = std::shared_ptr<HybridVideoViewViewManagerSpec>;
|
||||
std::shared_ptr<HybridVideoViewViewManagerSpec> create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType);
|
||||
std::shared_ptr<HybridVideoViewViewManagerSpec> 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<HybridVideoViewViewManagerSpec>
|
||||
using std__weak_ptr_HybridVideoViewViewManagerSpec_ = std::weak_ptr<HybridVideoViewViewManagerSpec>;
|
||||
inline std__weak_ptr_HybridVideoViewViewManagerSpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(const std::shared_ptr<HybridVideoViewViewManagerSpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoViewViewManagerSpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(const std::shared_ptr<HybridVideoViewViewManagerSpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<bool>
|
||||
using Result_bool_ = Result<bool>;
|
||||
inline Result_bool_ create_Result_bool_(bool value) {
|
||||
inline Result_bool_ create_Result_bool_(bool value) noexcept {
|
||||
return Result<bool>::withValue(std::move(value));
|
||||
}
|
||||
inline Result_bool_ create_Result_bool_(const std::exception_ptr& error) {
|
||||
inline Result_bool_ create_Result_bool_(const std::exception_ptr& error) noexcept {
|
||||
return Result<bool>::withError(error);
|
||||
}
|
||||
|
||||
@@ -922,19 +1034,19 @@ namespace margelo::nitro::video::bridge::swift {
|
||||
* Specialized version of `std::shared_ptr<HybridVideoViewViewManagerFactorySpec>`.
|
||||
*/
|
||||
using std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ = std::shared_ptr<HybridVideoViewViewManagerFactorySpec>;
|
||||
std::shared_ptr<HybridVideoViewViewManagerFactorySpec> create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* _Nonnull swiftUnsafePointer);
|
||||
void* _Nonnull get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType);
|
||||
std::shared_ptr<HybridVideoViewViewManagerFactorySpec> 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<HybridVideoViewViewManagerFactorySpec>
|
||||
using std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ = std::weak_ptr<HybridVideoViewViewManagerFactorySpec>;
|
||||
inline std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(const std::shared_ptr<HybridVideoViewViewManagerFactorySpec>& strong) { return strong; }
|
||||
inline std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(const std::shared_ptr<HybridVideoViewViewManagerFactorySpec>& strong) noexcept { return strong; }
|
||||
|
||||
// pragma MARK: Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>
|
||||
using Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ = Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>;
|
||||
inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::shared_ptr<HybridVideoViewViewManagerSpec>& value) {
|
||||
inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::shared_ptr<HybridVideoViewViewManagerSpec>& value) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>::withValue(value);
|
||||
}
|
||||
inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::exception_ptr& error) {
|
||||
inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::exception_ptr& error) noexcept {
|
||||
return Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>::withError(error);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
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.
|
||||
@@ -48,6 +50,8 @@ namespace margelo::nitro::video { struct Resolution; }
|
||||
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.
|
||||
@@ -74,6 +78,7 @@ 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"
|
||||
@@ -92,6 +97,7 @@ namespace margelo::nitro::video { struct onVolumeChangeData; }
|
||||
#include "Resolution.hpp"
|
||||
#include "SourceType.hpp"
|
||||
#include "SubtitleType.hpp"
|
||||
#include "SurfaceType.hpp"
|
||||
#include "TextTrack.hpp"
|
||||
#include "TimedMetadata.hpp"
|
||||
#include "TimedMetadataObject.hpp"
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace margelo::nitro::video { struct BufferConfig; }
|
||||
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 <memory>
|
||||
#include "HybridVideoPlayerSourceSpec.hpp"
|
||||
@@ -47,6 +49,7 @@ namespace margelo::nitro::video { struct Resolution; }
|
||||
#include "BufferConfig.hpp"
|
||||
#include "LivePlaybackParams.hpp"
|
||||
#include "Resolution.hpp"
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
|
||||
#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp"
|
||||
|
||||
@@ -98,7 +101,7 @@ namespace margelo::nitro::video {
|
||||
return __value;
|
||||
}
|
||||
inline std::shared_ptr<HybridVideoPlayerSourceSpec> fromVideoConfig(const NativeVideoConfig& config) override {
|
||||
auto __result = _swiftPart.fromVideoConfig(config);
|
||||
auto __result = _swiftPart.fromVideoConfig(std::forward<decltype(config)>(config));
|
||||
if (__result.hasError()) [[unlikely]] {
|
||||
std::rethrow_exception(__result.error());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace margelo::nitro::video { struct BufferConfig; }
|
||||
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.
|
||||
@@ -47,6 +49,7 @@ namespace margelo::nitro::video { enum class VideoOrientation; }
|
||||
#include "BufferConfig.hpp"
|
||||
#include "LivePlaybackParams.hpp"
|
||||
#include "Resolution.hpp"
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
#include "VideoInformation.hpp"
|
||||
#include "VideoOrientation.hpp"
|
||||
|
||||
@@ -92,8 +95,7 @@ namespace margelo::nitro::video {
|
||||
return __result;
|
||||
}
|
||||
inline NativeVideoConfig getConfig() noexcept override {
|
||||
auto __result = _swiftPart.getConfig();
|
||||
return __result;
|
||||
return _swiftPart.getConfig();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -82,6 +82,12 @@ namespace margelo::nitro::video {
|
||||
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<decltype(showNotificationControls)>(showNotificationControls));
|
||||
}
|
||||
inline VideoPlayerStatus getStatus() noexcept override {
|
||||
auto __result = _swiftPart.getStatus();
|
||||
return static_cast<VideoPlayerStatus>(__result);
|
||||
|
||||
@@ -16,11 +16,14 @@ namespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; }
|
||||
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 <memory>
|
||||
#include "HybridVideoPlayerSpec.hpp"
|
||||
#include <optional>
|
||||
#include "ResizeMode.hpp"
|
||||
#include "SurfaceType.hpp"
|
||||
#include <functional>
|
||||
|
||||
#include "ReactNativeVideo-Swift-Cxx-Umbrella.hpp"
|
||||
@@ -98,6 +101,13 @@ namespace margelo::nitro::video {
|
||||
inline void setKeepScreenAwake(bool keepScreenAwake) noexcept override {
|
||||
_swiftPart.setKeepScreenAwake(std::forward<decltype(keepScreenAwake)>(keepScreenAwake));
|
||||
}
|
||||
inline SurfaceType getSurfaceType() noexcept override {
|
||||
auto __result = _swiftPart.getSurfaceType();
|
||||
return static_cast<SurfaceType>(__result);
|
||||
}
|
||||
inline void setSurfaceType(SurfaceType surfaceType) noexcept override {
|
||||
_swiftPart.setSurfaceType(static_cast<int>(surfaceType));
|
||||
}
|
||||
inline std::optional<std::function<void(bool /* isInPictureInPicture */)>> getOnPictureInPictureChange() noexcept override {
|
||||
auto __result = _swiftPart.getOnPictureInPictureChange();
|
||||
return __result;
|
||||
|
||||
@@ -91,13 +91,7 @@ public extension BufferConfig {
|
||||
var livePlayback: LivePlaybackParams? {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> LivePlaybackParams? in
|
||||
if let __unwrapped = self.__livePlayback.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
return self.__livePlayback.value
|
||||
}
|
||||
@inline(__always)
|
||||
set {
|
||||
@@ -233,13 +227,7 @@ public extension BufferConfig {
|
||||
var preferredMaximumResolution: Resolution? {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> Resolution? in
|
||||
if let __unwrapped = self.__preferredMaximumResolution.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
return self.__preferredMaximumResolution.value
|
||||
}
|
||||
@inline(__always)
|
||||
set {
|
||||
@@ -273,13 +261,7 @@ public extension BufferConfig {
|
||||
var preferredMaximumResolutionForExpensiveNetworks: Resolution? {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> Resolution? in
|
||||
if let __unwrapped = self.__preferredMaximumResolutionForExpensiveNetworks.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
return self.__preferredMaximumResolutionForExpensiveNetworks.value
|
||||
}
|
||||
@inline(__always)
|
||||
set {
|
||||
|
||||
169
packages/react-native-video/nitrogen/generated/ios/swift/CustomVideoMetadata.swift
generated
Normal file
169
packages/react-native-video/nitrogen/generated/ios/swift/CustomVideoMetadata.swift
generated
Normal file
@@ -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()
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,7 @@ public final class Func_void_std__optional_TextTrack_ {
|
||||
|
||||
@inline(__always)
|
||||
public func call(track: bridge.std__optional_TextTrack_) -> Void {
|
||||
self.closure({ () -> TextTrack? in
|
||||
if let __unwrapped = track.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}())
|
||||
self.closure(track.value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ 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 }
|
||||
|
||||
@@ -126,6 +126,17 @@ open class HybridVideoPlayerSpec_cxx {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -264,7 +275,8 @@ open class HybridVideoPlayerSpec_cxx {
|
||||
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 let __unwrapped = source.value {
|
||||
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)
|
||||
@@ -293,13 +305,9 @@ open class HybridVideoPlayerSpec_cxx {
|
||||
public final func getAvailableTextTracks() -> bridge.Result_std__vector_TextTrack__ {
|
||||
do {
|
||||
let __result = try self.__implementation.getAvailableTextTracks()
|
||||
let __resultCpp = { () -> bridge.std__vector_TextTrack_ in
|
||||
var __vector = bridge.create_std__vector_TextTrack_(__result.count)
|
||||
for __item in __result {
|
||||
__vector.push_back(__item)
|
||||
}
|
||||
return __vector
|
||||
}()
|
||||
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()
|
||||
@@ -310,13 +318,7 @@ open class HybridVideoPlayerSpec_cxx {
|
||||
@inline(__always)
|
||||
public final func selectTextTrack(textTrack: bridge.std__optional_TextTrack_) -> bridge.Result_void_ {
|
||||
do {
|
||||
try self.__implementation.selectTextTrack(textTrack: { () -> TextTrack? in
|
||||
if let __unwrapped = textTrack.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}())
|
||||
try self.__implementation.selectTextTrack(textTrack: textTrack.value)
|
||||
return bridge.create_Result_void_()
|
||||
} catch (let __error) {
|
||||
let __exceptionPtr = __error.toCpp()
|
||||
|
||||
@@ -17,6 +17,7 @@ public protocol HybridVideoViewViewManagerSpec_protocol: HybridObject {
|
||||
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 }
|
||||
|
||||
@@ -123,7 +123,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.player = { () -> (any HybridVideoPlayerSpec)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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)
|
||||
@@ -191,6 +192,17 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -208,7 +220,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.onPictureInPictureChange = { () -> ((_ isInPictureInPicture: Bool) -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
@@ -239,7 +252,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.onFullscreenChange = { () -> ((_ fullscreen: Bool) -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
@@ -270,7 +284,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.willEnterFullscreen = { () -> (() -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
@@ -301,7 +316,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.willExitFullscreen = { () -> (() -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
@@ -332,7 +348,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.willEnterPictureInPicture = { () -> (() -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
@@ -363,7 +380,8 @@ open class HybridVideoViewViewManagerSpec_cxx {
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__implementation.willExitPictureInPicture = { () -> (() -> Void)? in
|
||||
if let __unwrapped = newValue.value {
|
||||
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
|
||||
|
||||
@@ -77,7 +77,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> String? in
|
||||
if let __unwrapped = self.__type.value {
|
||||
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
|
||||
@@ -100,7 +101,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> String? in
|
||||
if let __unwrapped = self.__licenseUrl.value {
|
||||
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
|
||||
@@ -123,7 +125,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> String? in
|
||||
if let __unwrapped = self.__certificateUrl.value {
|
||||
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
|
||||
@@ -146,7 +149,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> String? in
|
||||
if let __unwrapped = self.__contentId.value {
|
||||
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
|
||||
@@ -169,7 +173,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> Dictionary<String, String>? in
|
||||
if let __unwrapped = self.__licenseHeaders.value {
|
||||
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<String, String> in
|
||||
var __dictionary = Dictionary<String, String>(minimumCapacity: __unwrapped.size())
|
||||
let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped)
|
||||
@@ -223,7 +228,8 @@ public extension NativeDrmParams {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> ((_ payload: OnGetLicensePayload) -> Promise<Promise<String>>)? in
|
||||
if let __unwrapped = self.__getLicense.value {
|
||||
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<Promise<String>> in
|
||||
let __wrappedFunction = bridge.wrap_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrapped)
|
||||
return { (__payload: OnGetLicensePayload) -> Promise<Promise<String>> in
|
||||
|
||||
@@ -18,16 +18,12 @@ public extension NativeVideoConfig {
|
||||
/**
|
||||
* Create a new instance of `NativeVideoConfig`.
|
||||
*/
|
||||
init(uri: String, externalSubtitles: [NativeExternalSubtitle]?, drm: NativeDrmParams?, headers: Dictionary<String, String>?, bufferConfig: BufferConfig?, initializeOnCreation: Bool?) {
|
||||
init(uri: String, externalSubtitles: [NativeExternalSubtitle]?, drm: NativeDrmParams?, headers: Dictionary<String, String>?, 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__({ () -> bridge.std__vector_NativeExternalSubtitle_ in
|
||||
var __vector = bridge.create_std__vector_NativeExternalSubtitle_(__unwrappedValue.count)
|
||||
for __item in __unwrappedValue {
|
||||
__vector.push_back(__item)
|
||||
}
|
||||
return __vector
|
||||
}())
|
||||
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()
|
||||
}
|
||||
@@ -55,6 +51,12 @@ public extension NativeVideoConfig {
|
||||
} 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)
|
||||
@@ -79,8 +81,13 @@ public extension NativeVideoConfig {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> [NativeExternalSubtitle]? in
|
||||
if let __unwrapped = self.__externalSubtitles.value {
|
||||
return __unwrapped.map({ __item in __item })
|
||||
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
|
||||
}
|
||||
@@ -90,13 +97,9 @@ public extension NativeVideoConfig {
|
||||
set {
|
||||
self.__externalSubtitles = { () -> bridge.std__optional_std__vector_NativeExternalSubtitle__ in
|
||||
if let __unwrappedValue = newValue {
|
||||
return bridge.create_std__optional_std__vector_NativeExternalSubtitle__({ () -> bridge.std__vector_NativeExternalSubtitle_ in
|
||||
var __vector = bridge.create_std__vector_NativeExternalSubtitle_(__unwrappedValue.count)
|
||||
for __item in __unwrappedValue {
|
||||
__vector.push_back(__item)
|
||||
}
|
||||
return __vector
|
||||
}())
|
||||
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()
|
||||
}
|
||||
@@ -107,13 +110,7 @@ public extension NativeVideoConfig {
|
||||
var drm: NativeDrmParams? {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> NativeDrmParams? in
|
||||
if let __unwrapped = self.__drm.value {
|
||||
return __unwrapped
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
return self.__drm.value
|
||||
}
|
||||
@inline(__always)
|
||||
set {
|
||||
@@ -131,7 +128,8 @@ public extension NativeVideoConfig {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> Dictionary<String, String>? in
|
||||
if let __unwrapped = self.__headers.value {
|
||||
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<String, String> in
|
||||
var __dictionary = Dictionary<String, String>(minimumCapacity: __unwrapped.size())
|
||||
let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped)
|
||||
@@ -167,8 +165,25 @@ public extension NativeVideoConfig {
|
||||
var bufferConfig: BufferConfig? {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> BufferConfig? in
|
||||
if let __unwrapped = self.__bufferConfig.value {
|
||||
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
|
||||
@@ -177,9 +192,9 @@ public extension NativeVideoConfig {
|
||||
}
|
||||
@inline(__always)
|
||||
set {
|
||||
self.__bufferConfig = { () -> bridge.std__optional_BufferConfig_ in
|
||||
self.__metadata = { () -> bridge.std__optional_CustomVideoMetadata_ in
|
||||
if let __unwrappedValue = newValue {
|
||||
return bridge.create_std__optional_BufferConfig_(__unwrappedValue)
|
||||
return bridge.create_std__optional_CustomVideoMetadata_(__unwrappedValue)
|
||||
} else {
|
||||
return .init()
|
||||
}
|
||||
|
||||
40
packages/react-native-video/nitrogen/generated/ios/swift/SurfaceType.swift
generated
Normal file
40
packages/react-native-video/nitrogen/generated/ios/swift/SurfaceType.swift
generated
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,8 @@ public extension TextTrack {
|
||||
@inline(__always)
|
||||
get {
|
||||
return { () -> String? in
|
||||
if let __unwrapped = self.__language.value {
|
||||
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
|
||||
|
||||
@@ -19,29 +19,25 @@ public extension TimedMetadata {
|
||||
* Create a new instance of `TimedMetadata`.
|
||||
*/
|
||||
init(metadata: [TimedMetadataObject]) {
|
||||
self.init({ () -> bridge.std__vector_TimedMetadataObject_ in
|
||||
var __vector = bridge.create_std__vector_TimedMetadataObject_(metadata.count)
|
||||
for __item in metadata {
|
||||
__vector.push_back(__item)
|
||||
}
|
||||
return __vector
|
||||
}())
|
||||
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 self.__metadata.map({ __item in __item })
|
||||
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 = { () -> bridge.std__vector_TimedMetadataObject_ in
|
||||
var __vector = bridge.create_std__vector_TimedMetadataObject_(newValue.count)
|
||||
for __item in newValue {
|
||||
__vector.push_back(__item)
|
||||
}
|
||||
return __vector
|
||||
}()
|
||||
self.__metadata = newValue.withUnsafeBufferPointer { __pointer -> bridge.std__vector_TimedMetadataObject_ in
|
||||
return bridge.copy_std__vector_TimedMetadataObject_(__pointer.baseAddress!, newValue.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
84
packages/react-native-video/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp
generated
Normal file
84
packages/react-native-video/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp
generated
Normal file
@@ -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(<NitroModules/JSIConverter.hpp>)
|
||||
#include <NitroModules/JSIConverter.hpp>
|
||||
#else
|
||||
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
||||
#endif
|
||||
#if __has_include(<NitroModules/NitroDefines.hpp>)
|
||||
#include <NitroModules/NitroDefines.hpp>
|
||||
#else
|
||||
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace margelo::nitro::video {
|
||||
|
||||
/**
|
||||
* A struct which can be represented as a JavaScript object (CustomVideoMetadata).
|
||||
*/
|
||||
struct CustomVideoMetadata {
|
||||
public:
|
||||
std::optional<std::string> title SWIFT_PRIVATE;
|
||||
std::optional<std::string> subtitle SWIFT_PRIVATE;
|
||||
std::optional<std::string> description SWIFT_PRIVATE;
|
||||
std::optional<std::string> artist SWIFT_PRIVATE;
|
||||
std::optional<std::string> imageUri SWIFT_PRIVATE;
|
||||
|
||||
public:
|
||||
CustomVideoMetadata() = default;
|
||||
explicit CustomVideoMetadata(std::optional<std::string> title, std::optional<std::string> subtitle, std::optional<std::string> description, std::optional<std::string> artist, std::optional<std::string> 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<margelo::nitro::video::CustomVideoMetadata> 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<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "title")),
|
||||
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "subtitle")),
|
||||
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "description")),
|
||||
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "artist")),
|
||||
JSIConverter<std::optional<std::string>>::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<std::optional<std::string>>::toJSI(runtime, arg.title));
|
||||
obj.setProperty(runtime, "subtitle", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subtitle));
|
||||
obj.setProperty(runtime, "description", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.description));
|
||||
obj.setProperty(runtime, "artist", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.artist));
|
||||
obj.setProperty(runtime, "imageUri", JSIConverter<std::optional<std::string>>::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<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "title"))) return false;
|
||||
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "subtitle"))) return false;
|
||||
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "description"))) return false;
|
||||
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "artist"))) return false;
|
||||
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "imageUri"))) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace margelo::nitro
|
||||
@@ -16,6 +16,8 @@ namespace margelo::nitro::video {
|
||||
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);
|
||||
|
||||
@@ -66,6 +66,8 @@ namespace margelo::nitro::video {
|
||||
// Properties
|
||||
virtual std::shared_ptr<HybridVideoPlayerSourceSpec> getSource() = 0;
|
||||
virtual std::shared_ptr<HybridVideoPlayerEventEmitterSpec> getEventEmitter() = 0;
|
||||
virtual bool getShowNotificationControls() = 0;
|
||||
virtual void setShowNotificationControls(bool showNotificationControls) = 0;
|
||||
virtual VideoPlayerStatus getStatus() = 0;
|
||||
virtual double getDuration() = 0;
|
||||
virtual double getVolume() = 0;
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace margelo::nitro::video {
|
||||
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);
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
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 <memory>
|
||||
#include "HybridVideoPlayerSpec.hpp"
|
||||
#include <optional>
|
||||
#include "ResizeMode.hpp"
|
||||
#include "SurfaceType.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace margelo::nitro::video {
|
||||
@@ -63,6 +66,8 @@ namespace margelo::nitro::video {
|
||||
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<std::function<void(bool /* isInPictureInPicture */)>> getOnPictureInPictureChange() = 0;
|
||||
virtual void setOnPictureInPictureChange(const std::optional<std::function<void(bool /* isInPictureInPicture */)>>& onPictureInPictureChange) = 0;
|
||||
virtual std::optional<std::function<void(bool /* fullscreen */)>> getOnFullscreenChange() = 0;
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace margelo::nitro::video { struct NativeExternalSubtitle; }
|
||||
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 <string>
|
||||
#include "NativeExternalSubtitle.hpp"
|
||||
@@ -32,6 +34,7 @@ namespace margelo::nitro::video { struct BufferConfig; }
|
||||
#include "NativeDrmParams.hpp"
|
||||
#include <unordered_map>
|
||||
#include "BufferConfig.hpp"
|
||||
#include "CustomVideoMetadata.hpp"
|
||||
|
||||
namespace margelo::nitro::video {
|
||||
|
||||
@@ -45,11 +48,12 @@ namespace margelo::nitro::video {
|
||||
std::optional<NativeDrmParams> drm SWIFT_PRIVATE;
|
||||
std::optional<std::unordered_map<std::string, std::string>> headers SWIFT_PRIVATE;
|
||||
std::optional<BufferConfig> bufferConfig SWIFT_PRIVATE;
|
||||
std::optional<CustomVideoMetadata> metadata SWIFT_PRIVATE;
|
||||
std::optional<bool> initializeOnCreation SWIFT_PRIVATE;
|
||||
|
||||
public:
|
||||
NativeVideoConfig() = default;
|
||||
explicit NativeVideoConfig(std::string uri, std::optional<std::vector<NativeExternalSubtitle>> externalSubtitles, std::optional<NativeDrmParams> drm, std::optional<std::unordered_map<std::string, std::string>> headers, std::optional<BufferConfig> bufferConfig, std::optional<bool> initializeOnCreation): uri(uri), externalSubtitles(externalSubtitles), drm(drm), headers(headers), bufferConfig(bufferConfig), initializeOnCreation(initializeOnCreation) {}
|
||||
explicit NativeVideoConfig(std::string uri, std::optional<std::vector<NativeExternalSubtitle>> externalSubtitles, std::optional<NativeDrmParams> drm, std::optional<std::unordered_map<std::string, std::string>> headers, std::optional<BufferConfig> bufferConfig, std::optional<CustomVideoMetadata> metadata, std::optional<bool> initializeOnCreation): uri(uri), externalSubtitles(externalSubtitles), drm(drm), headers(headers), bufferConfig(bufferConfig), metadata(metadata), initializeOnCreation(initializeOnCreation) {}
|
||||
};
|
||||
|
||||
} // namespace margelo::nitro::video
|
||||
@@ -67,6 +71,7 @@ namespace margelo::nitro {
|
||||
JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::fromJSI(runtime, obj.getProperty(runtime, "drm")),
|
||||
JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, "headers")),
|
||||
JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::fromJSI(runtime, obj.getProperty(runtime, "bufferConfig")),
|
||||
JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::fromJSI(runtime, obj.getProperty(runtime, "metadata")),
|
||||
JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "initializeOnCreation"))
|
||||
);
|
||||
}
|
||||
@@ -77,6 +82,7 @@ namespace margelo::nitro {
|
||||
obj.setProperty(runtime, "drm", JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::toJSI(runtime, arg.drm));
|
||||
obj.setProperty(runtime, "headers", JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::toJSI(runtime, arg.headers));
|
||||
obj.setProperty(runtime, "bufferConfig", JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::toJSI(runtime, arg.bufferConfig));
|
||||
obj.setProperty(runtime, "metadata", JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::toJSI(runtime, arg.metadata));
|
||||
obj.setProperty(runtime, "initializeOnCreation", JSIConverter<std::optional<bool>>::toJSI(runtime, arg.initializeOnCreation));
|
||||
return obj;
|
||||
}
|
||||
@@ -90,6 +96,7 @@ namespace margelo::nitro {
|
||||
if (!JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::canConvert(runtime, obj.getProperty(runtime, "drm"))) return false;
|
||||
if (!JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::canConvert(runtime, obj.getProperty(runtime, "headers"))) return false;
|
||||
if (!JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::canConvert(runtime, obj.getProperty(runtime, "bufferConfig"))) return false;
|
||||
if (!JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::canConvert(runtime, obj.getProperty(runtime, "metadata"))) return false;
|
||||
if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, "initializeOnCreation"))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
76
packages/react-native-video/nitrogen/generated/shared/c++/SurfaceType.hpp
generated
Normal file
76
packages/react-native-video/nitrogen/generated/shared/c++/SurfaceType.hpp
generated
Normal file
@@ -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(<NitroModules/NitroHash.hpp>)
|
||||
#include <NitroModules/NitroHash.hpp>
|
||||
#else
|
||||
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
||||
#endif
|
||||
#if __has_include(<NitroModules/JSIConverter.hpp>)
|
||||
#include <NitroModules/JSIConverter.hpp>
|
||||
#else
|
||||
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
||||
#endif
|
||||
#if __has_include(<NitroModules/NitroDefines.hpp>)
|
||||
#include <NitroModules/NitroDefines.hpp>
|
||||
#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<margelo::nitro::video::SurfaceType> final {
|
||||
static inline margelo::nitro::video::SurfaceType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
||||
std::string unionValue = JSIConverter<std::string>::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<std::string>::toJSI(runtime, "surface");
|
||||
case margelo::nitro::video::SurfaceType::TEXTURE: return JSIConverter<std::string>::toJSI(runtime, "texture");
|
||||
default: [[unlikely]]
|
||||
throw std::invalid_argument("Cannot convert SurfaceType to JS - invalid value: "
|
||||
+ std::to_string(static_cast<int>(arg)) + "!");
|
||||
}
|
||||
}
|
||||
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
||||
if (!value.isString()) {
|
||||
return false;
|
||||
}
|
||||
std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
|
||||
switch (hashString(unionValue.c_str(), unionValue.size())) {
|
||||
case hashString("surface"):
|
||||
case hashString("texture"):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace margelo::nitro
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-video",
|
||||
"version": "7.0.0-alpha.4",
|
||||
"version": "7.0.0-alpha.5",
|
||||
"description": "<Video /> Component for React Native",
|
||||
"source": "./src/index.tsx",
|
||||
"main": "./lib/commonjs/index.js",
|
||||
@@ -52,7 +52,7 @@
|
||||
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
||||
"prepare": "bun run build",
|
||||
"build": "bob build",
|
||||
"specs": "nitro-codegen",
|
||||
"specs": "nitrogen",
|
||||
"release": "release-it --preRelease alpha --npm.tag=next"
|
||||
},
|
||||
"keywords": [
|
||||
@@ -75,19 +75,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@expo/config-plugins": "^10.0.2",
|
||||
"@react-native/eslint-config": "^0.77.0",
|
||||
"@types/react": "^18.2.44",
|
||||
"@types/react-native-web": "^0.19.2",
|
||||
"del-cli": "^5.1.0",
|
||||
"eslint": "^8.51.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"nitro-codegen": "^0.28.0",
|
||||
"nitrogen": "^0.29.0",
|
||||
"prettier": "^3.0.3",
|
||||
"react": "18.3.1",
|
||||
"react-native": "^0.77.0",
|
||||
"@react-native/eslint-config": "^0.77.0",
|
||||
"react-native-builder-bob": "^0.40.0",
|
||||
"react-native-nitro-modules": "^0.28.0",
|
||||
"typescript": "^5.2.2"
|
||||
"react-native-nitro-modules": "^0.29.0",
|
||||
"typescript": "^5.2.2",
|
||||
"video.js": "^8.23.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import { Platform } from 'react-native';
|
||||
import { NitroModules } from 'react-native-nitro-modules';
|
||||
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 { Platform } from "react-native";
|
||||
import { NitroModules } from "react-native-nitro-modules";
|
||||
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 {
|
||||
tryParseNativeVideoError,
|
||||
VideoRuntimeError,
|
||||
} from './types/VideoError';
|
||||
import type { VideoPlayerBase } from './types/VideoPlayerBase';
|
||||
import type { VideoPlayerStatus } from './types/VideoPlayerStatus';
|
||||
import { createPlayer } from './utils/playerFactory';
|
||||
import { createSource } from './utils/sourceFactory';
|
||||
import { VideoPlayerEvents } from './VideoPlayerEvents';
|
||||
} from "./types/VideoError";
|
||||
import type { VideoPlayerBase } from "./types/VideoPlayerBase";
|
||||
import type { VideoPlayerStatus } from "./types/VideoPlayerStatus";
|
||||
import { createPlayer } from "./utils/playerFactory";
|
||||
import { createSource } from "./utils/sourceFactory";
|
||||
import { VideoPlayerEvents } from "./VideoPlayerEvents";
|
||||
import type { AudioTrack } from "./types/AudioTrack";
|
||||
import type { VideoTrack } from "./types/VideoTrack";
|
||||
import type { QualityLevel } from "./types/QualityLevel";
|
||||
|
||||
class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
protected player: VideoPlayerImpl;
|
||||
|
||||
public onError?: (error: VideoRuntimeError) => void = undefined;
|
||||
|
||||
constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {
|
||||
const hybridSource = createSource(source);
|
||||
const player = createPlayer(hybridSource);
|
||||
@@ -57,8 +58,10 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
private throwError(error: unknown) {
|
||||
const parsedError = tryParseNativeVideoError(error);
|
||||
|
||||
if (parsedError instanceof VideoRuntimeError && this.onError) {
|
||||
this.onError(parsedError);
|
||||
if (
|
||||
parsedError instanceof VideoRuntimeError &&
|
||||
this.triggerEvent("onError", parsedError)
|
||||
) {
|
||||
// We don't throw errors if onError is provided
|
||||
return;
|
||||
}
|
||||
@@ -153,9 +156,9 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
}
|
||||
|
||||
set ignoreSilentSwitchMode(value: IgnoreSilentSwitchMode) {
|
||||
if (__DEV__ && !['ios'].includes(Platform.OS)) {
|
||||
if (__DEV__ && !["ios"].includes(Platform.OS)) {
|
||||
console.warn(
|
||||
'ignoreSilentSwitchMode is not supported on this platform, it wont have any effect'
|
||||
"ignoreSilentSwitchMode is not supported on this platform, it wont have any effect",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -185,6 +188,14 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
return this.player.isPlaying;
|
||||
}
|
||||
|
||||
get showNotificationControls(): boolean {
|
||||
return this.player.showNotificationControls;
|
||||
}
|
||||
|
||||
set showNotificationControls(value: boolean) {
|
||||
this.player.showNotificationControls = value;
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
await this.wrapPromise(this.player.initialize());
|
||||
|
||||
@@ -240,12 +251,16 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
}
|
||||
|
||||
async replaceSourceAsync(
|
||||
source: VideoSource | VideoConfig | NoAutocomplete<VideoPlayerSource> | null
|
||||
source:
|
||||
| VideoSource
|
||||
| VideoConfig
|
||||
| NoAutocomplete<VideoPlayerSource>
|
||||
| null,
|
||||
): Promise<void> {
|
||||
await this.wrapPromise(
|
||||
this.player.replaceSourceAsync(
|
||||
source === null ? null : createSource(source)
|
||||
)
|
||||
source === null ? null : createSource(source),
|
||||
),
|
||||
);
|
||||
|
||||
NitroModules.updateMemorySize(this.player);
|
||||
@@ -273,6 +288,43 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
get selectedTrack(): TextTrack | undefined {
|
||||
return this.player.selectedTrack;
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
getAvailableAudioTracks(): AudioTrack[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
selectAudioTrack(_: AudioTrack | null): void {}
|
||||
|
||||
get selectedAudioTrack(): AudioTrack | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getAvailableVideoTracks(): VideoTrack[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
selectVideoTrack(_: VideoTrack | null): void {}
|
||||
|
||||
get selectedVideoTrack(): VideoTrack | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// quality
|
||||
|
||||
getAvailableQualities(): QualityLevel[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
selectQuality(_: QualityLevel | null): void {}
|
||||
|
||||
get currentQuality(): QualityLevel | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get autoQualityEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export { VideoPlayer };
|
||||
|
||||
413
packages/react-native-video/src/core/VideoPlayer.web.ts
Normal file
413
packages/react-native-video/src/core/VideoPlayer.web.ts
Normal file
@@ -0,0 +1,413 @@
|
||||
import videojs from "video.js";
|
||||
import type { VideoPlayerSource } from "../spec/nitro/VideoPlayerSource.nitro";
|
||||
import type { AudioTrack } from "./types/AudioTrack";
|
||||
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 {
|
||||
NativeVideoConfig,
|
||||
VideoConfig,
|
||||
VideoSource,
|
||||
} from "./types/VideoConfig";
|
||||
import type { VideoPlayerBase } from "./types/VideoPlayerBase";
|
||||
import type { VideoPlayerSourceBase } from "./types/VideoPlayerSourceBase";
|
||||
import type { VideoPlayerStatus } from "./types/VideoPlayerStatus";
|
||||
import { VideoPlayerEvents } from "./VideoPlayerEvents";
|
||||
import { MediaSessionHandler } from "./web/MediaSession";
|
||||
import { WebEventEmiter } from "./web/WebEventEmiter";
|
||||
import type { VideoTrack } from "./types/VideoTrack";
|
||||
import type { QualityLevel } from "./types/QualityLevel";
|
||||
|
||||
type VideoJsPlayer = ReturnType<typeof videojs>;
|
||||
|
||||
// declared https://github.com/videojs/video.js/blob/main/src/js/tracks/track-list.js#L58
|
||||
export type VideoJsTextTracks = {
|
||||
length: number;
|
||||
[i: number]: {
|
||||
// declared: https://github.com/videojs/video.js/blob/main/src/js/tracks/track.js
|
||||
id: string;
|
||||
label: string;
|
||||
language: string;
|
||||
// declared https://github.com/videojs/video.js/blob/20f8d76cd24325a97ccedf0b013cd1a90ad0bcd7/src/js/tracks/text-track.js
|
||||
default: boolean;
|
||||
mode: "showing" | "disabled" | "hidden";
|
||||
};
|
||||
};
|
||||
|
||||
export type VideoJsTracks = {
|
||||
length: number;
|
||||
[i: number]: {
|
||||
id: string;
|
||||
label: string;
|
||||
language: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
// declared https://github.com/videojs/videojs-contrib-quality-levels/blob/main/src/quality-level.js#L32
|
||||
export type VideoJsQualityArray = {
|
||||
length: number;
|
||||
selectedIndex: number;
|
||||
[i: number]: {
|
||||
id: string;
|
||||
label: string;
|
||||
width: number;
|
||||
height: number;
|
||||
bitrate: number;
|
||||
frameRate: number;
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
protected video: HTMLVideoElement;
|
||||
public player: VideoJsPlayer;
|
||||
private mediaSession: MediaSessionHandler;
|
||||
private _source: NativeVideoConfig | undefined;
|
||||
|
||||
constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {
|
||||
const video = document.createElement("video");
|
||||
const player = videojs(video, { qualityLevels: true });
|
||||
|
||||
super(new WebEventEmiter(player));
|
||||
|
||||
this.video = video;
|
||||
this.player = player;
|
||||
this.mediaSession = new MediaSessionHandler(this.player);
|
||||
|
||||
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.dispose();
|
||||
}
|
||||
|
||||
__getNativeRef() {
|
||||
return this.video;
|
||||
}
|
||||
|
||||
// Source
|
||||
get source(): VideoPlayerSourceBase {
|
||||
return {
|
||||
uri: this._source?.uri!,
|
||||
config: this._source!,
|
||||
getAssetInformationAsync: async () => {
|
||||
return {
|
||||
bitrate: NaN,
|
||||
width: this.player.videoWidth(),
|
||||
height: this.player.videoHeight(),
|
||||
duration: BigInt(this.duration),
|
||||
fileSize: BigInt(NaN),
|
||||
isHDR: false,
|
||||
isLive: false,
|
||||
orientation: "landscape",
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Status
|
||||
get status(): VideoPlayerStatus {
|
||||
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(): number {
|
||||
return this.player.duration() ?? NaN;
|
||||
}
|
||||
|
||||
// Volume
|
||||
get volume(): number {
|
||||
return this.player.volume() ?? 1;
|
||||
}
|
||||
|
||||
set volume(value: number) {
|
||||
this.player.volume(value);
|
||||
}
|
||||
|
||||
// Current Time
|
||||
get currentTime(): number {
|
||||
return this.player.currentTime() ?? NaN;
|
||||
}
|
||||
|
||||
set currentTime(value: number) {
|
||||
this.player.currentTime(value);
|
||||
}
|
||||
|
||||
// Muted
|
||||
get muted(): boolean {
|
||||
return this.player.muted() ?? false;
|
||||
}
|
||||
|
||||
set muted(value: boolean) {
|
||||
this.player.muted(value);
|
||||
}
|
||||
|
||||
// Loop
|
||||
get loop(): boolean {
|
||||
return this.player.loop() ?? false;
|
||||
}
|
||||
|
||||
set loop(value: boolean) {
|
||||
this.player.loop(value);
|
||||
}
|
||||
|
||||
// Rate
|
||||
get rate(): number {
|
||||
return this.player.playbackRate() ?? 1;
|
||||
}
|
||||
|
||||
set rate(value: number) {
|
||||
this.player.playbackRate(value);
|
||||
}
|
||||
|
||||
// Mix Audio Mode
|
||||
get mixAudioMode(): MixAudioMode {
|
||||
return "auto";
|
||||
}
|
||||
|
||||
set mixAudioMode(_: MixAudioMode) {}
|
||||
|
||||
// Ignore Silent Switch Mode
|
||||
get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode {
|
||||
return "auto";
|
||||
}
|
||||
|
||||
set ignoreSilentSwitchMode(_: IgnoreSilentSwitchMode) {}
|
||||
|
||||
// Play In Background
|
||||
get playInBackground(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
set playInBackground(_: boolean) {}
|
||||
|
||||
// Play When Inactive
|
||||
get playWhenInactive(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
set playWhenInactive(_: boolean) {}
|
||||
|
||||
get isPlaying(): boolean {
|
||||
return !this.player.paused();
|
||||
}
|
||||
|
||||
get showNotificationControls(): boolean {
|
||||
return this.mediaSession.enabled;
|
||||
}
|
||||
|
||||
set showNotificationControls(value: boolean) {
|
||||
if (!value) {
|
||||
this.mediaSession.disable();
|
||||
return;
|
||||
}
|
||||
this.mediaSession.enable();
|
||||
this.mediaSession.updateMediaSession(this._source?.metadata);
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
// noop on web
|
||||
}
|
||||
|
||||
async preload(): Promise<void> {
|
||||
this.player.load();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
this.__destroy();
|
||||
}
|
||||
|
||||
play(): void {
|
||||
// error are already handled by the `onError` callback, no need to catch it here.
|
||||
this.player.play()?.catch();
|
||||
}
|
||||
|
||||
pause(): void {
|
||||
this.player.pause();
|
||||
}
|
||||
|
||||
seekBy(time: number): void {
|
||||
const now = this.player.currentTime() ?? 0;
|
||||
this.player.currentTime(now + time);
|
||||
}
|
||||
|
||||
seekTo(time: number): void {
|
||||
this.player.currentTime(time);
|
||||
}
|
||||
|
||||
async replaceSourceAsync(
|
||||
source:
|
||||
| VideoSource
|
||||
| VideoConfig
|
||||
| NoAutocomplete<VideoPlayerSource>
|
||||
| null,
|
||||
): Promise<void> {
|
||||
if (!source) {
|
||||
this.player.src([]);
|
||||
this.player.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof source === "string") {
|
||||
source = { uri: source };
|
||||
}
|
||||
|
||||
if (typeof source === "number" || typeof source.uri === "number") {
|
||||
console.error(
|
||||
"A source uri must be a string. Numbers are only supported on native.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
this._source = source as VideoPlayerSource;
|
||||
// TODO: handle start time
|
||||
this.player.src({
|
||||
src: source.uri,
|
||||
type: source.mimeType,
|
||||
});
|
||||
if (this.mediaSession.enabled)
|
||||
this.mediaSession.updateMediaSession(source.metadata);
|
||||
if (source.initializeOnCreation) await this.preload();
|
||||
}
|
||||
|
||||
// Text Track Management
|
||||
|
||||
getAvailableTextTracks(): TextTrack[] {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTextTracks = this.player.textTracks();
|
||||
|
||||
return [...Array(tracks.length)].map((_, i) => ({
|
||||
id: tracks[i]!.id,
|
||||
label: tracks[i]!.label,
|
||||
language: tracks[i]!.language,
|
||||
selected: tracks[i]!.mode === "showing",
|
||||
}));
|
||||
}
|
||||
|
||||
selectTextTrack(textTrack: TextTrack | null): void {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTextTracks = this.player.textTracks();
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
if (tracks[i]!.mode === "showing") tracks[i]!.mode = "disabled";
|
||||
if (tracks[i]!.id === textTrack?.id) tracks[i]!.mode = "showing";
|
||||
}
|
||||
}
|
||||
|
||||
// Selected Text Track
|
||||
get selectedTrack(): TextTrack | undefined {
|
||||
return this.getAvailableTextTracks().find((x) => x.selected);
|
||||
}
|
||||
|
||||
// audio tracks
|
||||
|
||||
getAvailableAudioTracks(): AudioTrack[] {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTracks = this.player.audioTracks();
|
||||
|
||||
return [...Array(tracks.length)].map((_, i) => ({
|
||||
id: tracks[i]!.id,
|
||||
label: tracks[i]!.label,
|
||||
language: tracks[i]!.language,
|
||||
selected: tracks[i]!.enabled,
|
||||
}));
|
||||
}
|
||||
|
||||
selectAudioTrack(track: AudioTrack | null): void {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTracks = this.player.audioTracks();
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
tracks[i]!.enabled = tracks[i]!.id === track?.id;
|
||||
}
|
||||
}
|
||||
|
||||
get selectedAudioTrack(): AudioTrack | undefined {
|
||||
return this.getAvailableAudioTracks().find((x) => x.selected);
|
||||
}
|
||||
|
||||
// video tracks
|
||||
|
||||
getAvailableVideoTracks(): VideoTrack[] {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTracks = this.player.videoTracks();
|
||||
|
||||
return [...Array(tracks.length)].map((_, i) => ({
|
||||
id: tracks[i]!.id,
|
||||
label: tracks[i]!.label,
|
||||
language: tracks[i]!.language,
|
||||
selected: tracks[i]!.enabled,
|
||||
}));
|
||||
}
|
||||
|
||||
selectVideoTrack(track: VideoTrack | null): void {
|
||||
// @ts-expect-error they define length & index properties via prototype
|
||||
const tracks: VideoJsTracks = this.player.videoTracks();
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
tracks[i]!.enabled = tracks[i]!.id === track?.id;
|
||||
}
|
||||
}
|
||||
|
||||
get selectedVideoTrack(): VideoTrack | undefined {
|
||||
return this.getAvailableVideoTracks().find((x) => x.selected);
|
||||
}
|
||||
|
||||
// quality
|
||||
|
||||
getAvailableQualities(): QualityLevel[] {
|
||||
// @ts-expect-error this isn't typed
|
||||
const levels: VideoJsQualityArray = this.player.qualityLevels();
|
||||
return [...Array(levels.length)].map((_, i) => ({
|
||||
id: levels[i]!.id,
|
||||
width: levels[i]!.width,
|
||||
height: levels[i]!.height,
|
||||
bitrate: levels[i]!.bitrate,
|
||||
selected: levels.selectedIndex === i,
|
||||
}));
|
||||
}
|
||||
|
||||
selectQuality(quality: QualityLevel | null): void {
|
||||
// @ts-expect-error this isn't typed
|
||||
const levels: VideoJsQualityArray = this.player.qualityLevels();
|
||||
|
||||
for (let i = 0; i < levels.length; i++) {
|
||||
// if quality is null, enable back auto-quality switch (so enable all lvls)
|
||||
levels[i]!.enabled = !quality || levels[i]!.id === quality.id;
|
||||
}
|
||||
}
|
||||
|
||||
get currentQuality(): QualityLevel | undefined {
|
||||
return this.getAvailableQualities().find((x) => x.selected);
|
||||
}
|
||||
get autoQualityEnabled(): boolean {
|
||||
// @ts-expect-error this isn't typed
|
||||
const levels: VideoJsQualityArray = this.player.qualityLevels();
|
||||
// if we have a quality disabled that means we manually disabled it & disabled auto quality
|
||||
for (let i = 0; i < levels.length; i++) {
|
||||
if (!levels[i]!.enabled) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export { VideoPlayer };
|
||||
@@ -1,33 +1,50 @@
|
||||
import type { VideoPlayerEventEmitter } from '../spec/nitro/VideoPlayerEventEmitter.nitro';
|
||||
import type { VideoPlayerEvents as VideoPlayerEventsInterface } from './types/Events';
|
||||
import {
|
||||
ALL_PLAYER_EVENTS,
|
||||
type VideoPlayerEvents as NativePlayerEvents,
|
||||
type AllPlayerEvents as PlayerEvents,
|
||||
} from "./types/Events";
|
||||
|
||||
export class VideoPlayerEvents implements VideoPlayerEventsInterface {
|
||||
protected eventEmitter: VideoPlayerEventEmitter;
|
||||
export class VideoPlayerEvents {
|
||||
protected eventEmitter: NativePlayerEvents;
|
||||
protected eventListeners: Partial<
|
||||
Record<keyof PlayerEvents, Set<(...params: any[]) => void>>
|
||||
> = {};
|
||||
|
||||
protected readonly supportedEvents: (keyof VideoPlayerEventsInterface)[] = [
|
||||
'onAudioBecomingNoisy',
|
||||
'onAudioFocusChange',
|
||||
'onBandwidthUpdate',
|
||||
'onBuffer',
|
||||
'onControlsVisibleChange',
|
||||
'onEnd',
|
||||
'onExternalPlaybackChange',
|
||||
'onLoad',
|
||||
'onLoadStart',
|
||||
'onPlaybackRateChange',
|
||||
'onPlaybackStateChange',
|
||||
'onProgress',
|
||||
'onReadyToDisplay',
|
||||
'onSeek',
|
||||
'onStatusChange',
|
||||
'onTextTrackDataChanged',
|
||||
'onTimedMetadata',
|
||||
'onTrackChange',
|
||||
'onVolumeChange',
|
||||
];
|
||||
protected readonly supportedEvents: (keyof PlayerEvents)[] =
|
||||
ALL_PLAYER_EVENTS;
|
||||
|
||||
constructor(eventEmitter: VideoPlayerEventEmitter) {
|
||||
constructor(eventEmitter: NativePlayerEvents) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected triggerEvent<Event extends keyof PlayerEvents>(
|
||||
event: Event,
|
||||
...params: Parameters<PlayerEvents[Event]>
|
||||
): boolean {
|
||||
if (!this.eventListeners[event]?.size) return false;
|
||||
for (const fn of this.eventListeners[event]) {
|
||||
fn(...params);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
addEventListener<Event extends keyof PlayerEvents>(
|
||||
event: Event,
|
||||
callback: PlayerEvents[Event],
|
||||
) {
|
||||
this.eventListeners[event] ??= new Set<PlayerEvents[Event]>();
|
||||
this.eventListeners[event].add(callback);
|
||||
}
|
||||
|
||||
removeEventListener<Event extends keyof PlayerEvents>(
|
||||
event: Event,
|
||||
callback: PlayerEvents[Event],
|
||||
) {
|
||||
this.eventListeners[event]?.delete(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,177 +60,7 @@ export class VideoPlayerEvents implements VideoPlayerEventsInterface {
|
||||
* Clears a specific event from the event emitter.
|
||||
* @param event - The name of the event to clear.
|
||||
*/
|
||||
clearEvent(event: keyof VideoPlayerEventsInterface) {
|
||||
this.eventEmitter[event] = VideoPlayerEvents.NOOP;
|
||||
}
|
||||
|
||||
static NOOP = () => {};
|
||||
|
||||
set onAudioBecomingNoisy(
|
||||
value: VideoPlayerEventsInterface['onAudioBecomingNoisy']
|
||||
) {
|
||||
this.eventEmitter.onAudioBecomingNoisy = value;
|
||||
}
|
||||
|
||||
get onAudioBecomingNoisy(): VideoPlayerEventsInterface['onAudioBecomingNoisy'] {
|
||||
return this.eventEmitter.onAudioBecomingNoisy;
|
||||
}
|
||||
|
||||
set onAudioFocusChange(
|
||||
value: VideoPlayerEventsInterface['onAudioFocusChange']
|
||||
) {
|
||||
this.eventEmitter.onAudioFocusChange = value;
|
||||
}
|
||||
|
||||
get onAudioFocusChange(): VideoPlayerEventsInterface['onAudioFocusChange'] {
|
||||
return this.eventEmitter.onAudioFocusChange;
|
||||
}
|
||||
|
||||
set onBandwidthUpdate(
|
||||
value: VideoPlayerEventsInterface['onBandwidthUpdate']
|
||||
) {
|
||||
this.eventEmitter.onBandwidthUpdate = value;
|
||||
}
|
||||
|
||||
get onBandwidthUpdate(): VideoPlayerEventsInterface['onBandwidthUpdate'] {
|
||||
return this.eventEmitter.onBandwidthUpdate;
|
||||
}
|
||||
|
||||
set onBuffer(value: VideoPlayerEventsInterface['onBuffer']) {
|
||||
this.eventEmitter.onBuffer = value;
|
||||
}
|
||||
|
||||
get onBuffer(): VideoPlayerEventsInterface['onBuffer'] {
|
||||
return this.eventEmitter.onBuffer;
|
||||
}
|
||||
|
||||
set onControlsVisibleChange(
|
||||
value: VideoPlayerEventsInterface['onControlsVisibleChange']
|
||||
) {
|
||||
this.eventEmitter.onControlsVisibleChange = value;
|
||||
}
|
||||
|
||||
get onControlsVisibleChange(): VideoPlayerEventsInterface['onControlsVisibleChange'] {
|
||||
return this.eventEmitter.onControlsVisibleChange;
|
||||
}
|
||||
|
||||
set onEnd(value: VideoPlayerEventsInterface['onEnd']) {
|
||||
this.eventEmitter.onEnd = value;
|
||||
}
|
||||
|
||||
get onEnd(): VideoPlayerEventsInterface['onEnd'] {
|
||||
return this.eventEmitter.onEnd;
|
||||
}
|
||||
|
||||
set onExternalPlaybackChange(
|
||||
value: VideoPlayerEventsInterface['onExternalPlaybackChange']
|
||||
) {
|
||||
this.eventEmitter.onExternalPlaybackChange = value;
|
||||
}
|
||||
|
||||
get onExternalPlaybackChange(): VideoPlayerEventsInterface['onExternalPlaybackChange'] {
|
||||
return this.eventEmitter.onExternalPlaybackChange;
|
||||
}
|
||||
|
||||
set onLoad(value: VideoPlayerEventsInterface['onLoad']) {
|
||||
this.eventEmitter.onLoad = value;
|
||||
}
|
||||
|
||||
get onLoad(): VideoPlayerEventsInterface['onLoad'] {
|
||||
return this.eventEmitter.onLoad;
|
||||
}
|
||||
|
||||
set onLoadStart(value: VideoPlayerEventsInterface['onLoadStart']) {
|
||||
this.eventEmitter.onLoadStart = value;
|
||||
}
|
||||
|
||||
get onLoadStart(): VideoPlayerEventsInterface['onLoadStart'] {
|
||||
return this.eventEmitter.onLoadStart;
|
||||
}
|
||||
|
||||
set onPlaybackStateChange(
|
||||
value: VideoPlayerEventsInterface['onPlaybackStateChange']
|
||||
) {
|
||||
this.eventEmitter.onPlaybackStateChange = value;
|
||||
}
|
||||
|
||||
get onPlaybackStateChange(): VideoPlayerEventsInterface['onPlaybackStateChange'] {
|
||||
return this.eventEmitter.onPlaybackStateChange;
|
||||
}
|
||||
|
||||
set onPlaybackRateChange(
|
||||
value: VideoPlayerEventsInterface['onPlaybackRateChange']
|
||||
) {
|
||||
this.eventEmitter.onPlaybackRateChange = value;
|
||||
}
|
||||
|
||||
get onPlaybackRateChange(): VideoPlayerEventsInterface['onPlaybackRateChange'] {
|
||||
return this.eventEmitter.onPlaybackRateChange;
|
||||
}
|
||||
|
||||
set onProgress(value: VideoPlayerEventsInterface['onProgress']) {
|
||||
this.eventEmitter.onProgress = value;
|
||||
}
|
||||
|
||||
get onProgress(): VideoPlayerEventsInterface['onProgress'] {
|
||||
return this.eventEmitter.onProgress;
|
||||
}
|
||||
|
||||
set onReadyToDisplay(value: VideoPlayerEventsInterface['onReadyToDisplay']) {
|
||||
this.eventEmitter.onReadyToDisplay = value;
|
||||
}
|
||||
|
||||
get onReadyToDisplay(): VideoPlayerEventsInterface['onReadyToDisplay'] {
|
||||
return this.eventEmitter.onReadyToDisplay;
|
||||
}
|
||||
|
||||
set onSeek(value: VideoPlayerEventsInterface['onSeek']) {
|
||||
this.eventEmitter.onSeek = value;
|
||||
}
|
||||
|
||||
get onSeek(): VideoPlayerEventsInterface['onSeek'] {
|
||||
return this.eventEmitter.onSeek;
|
||||
}
|
||||
|
||||
set onStatusChange(value: VideoPlayerEventsInterface['onStatusChange']) {
|
||||
this.eventEmitter.onStatusChange = value;
|
||||
}
|
||||
|
||||
get onStatusChange(): VideoPlayerEventsInterface['onStatusChange'] {
|
||||
return this.eventEmitter.onStatusChange;
|
||||
}
|
||||
|
||||
set onTimedMetadata(value: VideoPlayerEventsInterface['onTimedMetadata']) {
|
||||
this.eventEmitter.onTimedMetadata = value;
|
||||
}
|
||||
|
||||
get onTimedMetadata(): VideoPlayerEventsInterface['onTimedMetadata'] {
|
||||
return this.eventEmitter.onTimedMetadata;
|
||||
}
|
||||
|
||||
set onTextTrackDataChanged(
|
||||
value: VideoPlayerEventsInterface['onTextTrackDataChanged']
|
||||
) {
|
||||
this.eventEmitter.onTextTrackDataChanged = value;
|
||||
}
|
||||
|
||||
get onTextTrackDataChanged(): VideoPlayerEventsInterface['onTextTrackDataChanged'] {
|
||||
return this.eventEmitter.onTextTrackDataChanged;
|
||||
}
|
||||
|
||||
set onTrackChange(value: VideoPlayerEventsInterface['onTrackChange']) {
|
||||
this.eventEmitter.onTrackChange = value;
|
||||
}
|
||||
|
||||
get onTrackChange(): VideoPlayerEventsInterface['onTrackChange'] {
|
||||
return this.eventEmitter.onTrackChange;
|
||||
}
|
||||
|
||||
set onVolumeChange(value: VideoPlayerEventsInterface['onVolumeChange']) {
|
||||
this.eventEmitter.onVolumeChange = value;
|
||||
}
|
||||
|
||||
get onVolumeChange(): VideoPlayerEventsInterface['onVolumeChange'] {
|
||||
return this.eventEmitter.onVolumeChange;
|
||||
clearEvent(event: keyof PlayerEvents) {
|
||||
this.eventListeners[event]?.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { VideoPlayer } from '../VideoPlayer';
|
||||
import { type VideoPlayerEvents } from '../types/Events';
|
||||
|
||||
// Omit undefined from events
|
||||
type NonUndefined<T> = T extends undefined ? never : T;
|
||||
|
||||
// Valid events names
|
||||
type Events = keyof VideoPlayerEvents | 'onError';
|
||||
|
||||
// Valid events params
|
||||
type EventsParams<T extends Events> = T extends keyof VideoPlayerEvents
|
||||
? // (Native) Events from VideoPlayerEvents
|
||||
Parameters<VideoPlayerEvents[T]>
|
||||
: // (JS) Events from Video Player
|
||||
Parameters<NonUndefined<VideoPlayer[T]>>;
|
||||
import type { AllPlayerEvents } from '../types/Events';
|
||||
import type { VideoPlayer } from '../VideoPlayer';
|
||||
|
||||
/**
|
||||
* Attaches an event listener to a `VideoPlayer` instance for a specified event.
|
||||
@@ -22,22 +9,14 @@ type EventsParams<T extends Events> = T extends keyof VideoPlayerEvents
|
||||
* @param event - The name of the event to attach the callback to
|
||||
* @param callback - The callback for the event
|
||||
*/
|
||||
export const useEvent = <T extends Events>(
|
||||
export const useEvent = <T extends keyof AllPlayerEvents>(
|
||||
player: VideoPlayer,
|
||||
event: T,
|
||||
callback: (...args: EventsParams<T>) => void
|
||||
callback: AllPlayerEvents[T]
|
||||
) => {
|
||||
useEffect(() => {
|
||||
// @ts-expect-error we narrow the type of the event
|
||||
player[event] = callback;
|
||||
player.addEventListener(event, callback);
|
||||
|
||||
return () => {
|
||||
if (event === 'onError') {
|
||||
// onError is not native event, so we can set it to undefined
|
||||
player.onError = undefined;
|
||||
} else {
|
||||
player.clearEvent(event);
|
||||
}
|
||||
};
|
||||
return () => player.removeEventListener(event, callback);
|
||||
}, [player, event, callback]);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { NoAutocomplete } from '../types/Utils';
|
||||
import type { VideoConfig, VideoSource } from '../types/VideoConfig';
|
||||
import { isVideoPlayerSource } from '../utils/sourceFactory';
|
||||
import { isVideoPlayerSource } from '../utils/sourceUtils';
|
||||
import { VideoPlayer } from '../VideoPlayer';
|
||||
import { useManagedInstance } from './useManagedInstance';
|
||||
|
||||
|
||||
22
packages/react-native-video/src/core/types/AudioTrack.ts
Normal file
22
packages/react-native-video/src/core/types/AudioTrack.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export interface AudioTrack {
|
||||
/**
|
||||
* Unique identifier for the audio track
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Display label for the audio 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;
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { AudioTrack } from './AudioTrack';
|
||||
import type { QualityLevel } from './QualityLevel';
|
||||
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';
|
||||
import type { VideoTrack } from './VideoTrack';
|
||||
|
||||
export interface VideoPlayerEvents {
|
||||
/**
|
||||
@@ -15,6 +19,11 @@ export interface VideoPlayerEvents {
|
||||
* @platform Android
|
||||
*/
|
||||
onAudioFocusChange: (hasAudioFocus: boolean) => void;
|
||||
/**
|
||||
* Called when the audio track changes
|
||||
* @param track The new audio track
|
||||
*/
|
||||
onAudioTrackChange: (track: AudioTrack | null) => void;
|
||||
/**
|
||||
* Called when the bandwidth of the video changes.
|
||||
*/
|
||||
@@ -27,6 +36,7 @@ export interface VideoPlayerEvents {
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
@@ -61,6 +71,10 @@ export interface VideoPlayerEvents {
|
||||
* Called when the player progress changes.
|
||||
*/
|
||||
onProgress: (data: onProgressData) => void;
|
||||
/**
|
||||
* Called when the player quality changes.
|
||||
*/
|
||||
onQualityChange: (quality: QualityLevel) => void;
|
||||
/**
|
||||
* Called when the video is ready to display.
|
||||
*/
|
||||
@@ -71,15 +85,18 @@ export interface VideoPlayerEvents {
|
||||
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;
|
||||
/**
|
||||
@@ -90,6 +107,15 @@ export interface VideoPlayerEvents {
|
||||
* Called when the player status changes.
|
||||
*/
|
||||
onStatusChange: (status: VideoPlayerStatus) => void;
|
||||
/**
|
||||
* Called when the video track changes
|
||||
* @param track The new video track
|
||||
*/
|
||||
onVideoTrackChange: (track: VideoTrack | null) => void;
|
||||
}
|
||||
|
||||
export interface AllPlayerEvents extends VideoPlayerEvents {
|
||||
onError: (error: VideoRuntimeError) => void;
|
||||
}
|
||||
|
||||
export interface VideoViewEvents {
|
||||
@@ -173,7 +199,7 @@ export interface onLoadStartData {
|
||||
/**
|
||||
* The source of the video.
|
||||
*/
|
||||
source: VideoPlayerSource;
|
||||
source: VideoPlayerSourceBase;
|
||||
}
|
||||
|
||||
export interface onPlaybackStateChangeData {
|
||||
@@ -220,3 +246,45 @@ export interface onVolumeChangeData {
|
||||
*/
|
||||
muted: boolean;
|
||||
}
|
||||
|
||||
type CheckAllAndOnly<T, A extends readonly (keyof T)[]> =
|
||||
// Missing keys?
|
||||
Exclude<keyof T, A[number]> extends never
|
||||
? // Extra keys?
|
||||
Exclude<A[number], keyof T> extends never
|
||||
? A
|
||||
: ['Extra keys', Exclude<A[number], keyof T>]
|
||||
: ['Missing keys', Exclude<keyof T, A[number]>];
|
||||
|
||||
function allKeysOf<T>() {
|
||||
return <A extends readonly (keyof T)[]>(...arr: A): CheckAllAndOnly<T, A> => {
|
||||
return arr as CheckAllAndOnly<T, A>;
|
||||
};
|
||||
}
|
||||
|
||||
export const ALL_PLAYER_EVENTS: (keyof AllPlayerEvents)[] =
|
||||
allKeysOf<AllPlayerEvents>()(
|
||||
'onAudioBecomingNoisy',
|
||||
'onAudioFocusChange',
|
||||
'onAudioTrackChange',
|
||||
'onBandwidthUpdate',
|
||||
'onBuffer',
|
||||
'onControlsVisibleChange',
|
||||
'onEnd',
|
||||
'onError',
|
||||
'onExternalPlaybackChange',
|
||||
'onLoad',
|
||||
'onLoadStart',
|
||||
'onPlaybackStateChange',
|
||||
'onPlaybackRateChange',
|
||||
'onProgress',
|
||||
'onQualityChange',
|
||||
'onReadyToDisplay',
|
||||
'onSeek',
|
||||
'onTimedMetadata',
|
||||
'onTextTrackDataChanged',
|
||||
'onTrackChange',
|
||||
'onVolumeChange',
|
||||
'onVideoTrackChange',
|
||||
'onStatusChange'
|
||||
);
|
||||
|
||||
26
packages/react-native-video/src/core/types/QualityLevel.ts
Normal file
26
packages/react-native-video/src/core/types/QualityLevel.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export interface QualityLevel {
|
||||
/**
|
||||
* Unique identifier for the quality
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Width of the quality
|
||||
*/
|
||||
width: number;
|
||||
|
||||
/**
|
||||
* Height of the quality
|
||||
*/
|
||||
height: number;
|
||||
|
||||
/**
|
||||
* Bitrate of the quality
|
||||
*/
|
||||
bitrate: number;
|
||||
|
||||
/**
|
||||
* Whether this quality is currently selected
|
||||
*/
|
||||
selected: boolean;
|
||||
}
|
||||
@@ -14,6 +14,11 @@ export type VideoConfig = {
|
||||
* ```
|
||||
*/
|
||||
uri: VideoSource;
|
||||
/**
|
||||
* complete mime type, used to select a background for playback.
|
||||
* if not specified, the extension of the url might be used
|
||||
*/
|
||||
mimeType?: string
|
||||
/**
|
||||
* The headers to be sent with the request.
|
||||
*/
|
||||
@@ -26,6 +31,11 @@ export type VideoConfig = {
|
||||
* 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).
|
||||
@@ -135,3 +145,11 @@ interface NativeExternalSubtitle {
|
||||
interface NativeDrmParams extends DrmParams {
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface CustomVideoMetadata {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
description?: string;
|
||||
artist?: string;
|
||||
imageUri?: string;
|
||||
}
|
||||
|
||||
22
packages/react-native-video/src/core/types/VideoTrack.ts
Normal file
22
packages/react-native-video/src/core/types/VideoTrack.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export interface VideoTrack {
|
||||
/**
|
||||
* Unique identifier for the video track
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Display label for the video 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;
|
||||
}
|
||||
@@ -5,8 +5,9 @@ import type {
|
||||
} from '../../spec/nitro/VideoPlayer.nitro';
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { VideoConfig, VideoSource } from '../types/VideoConfig';
|
||||
import { createSource, isVideoPlayerSource } from './sourceFactory';
|
||||
import { createSource } from './sourceFactory';
|
||||
import { tryParseNativeVideoError } from '../types/VideoError';
|
||||
import { isVideoPlayerSource } from './sourceUtils';
|
||||
|
||||
const VideoPlayerFactory =
|
||||
NitroModules.createHybridObject<VideoPlayerFactory>('VideoPlayerFactory');
|
||||
|
||||
@@ -12,21 +12,13 @@ import type {
|
||||
VideoSource,
|
||||
} from '../types/VideoConfig';
|
||||
import { tryParseNativeVideoError } from '../types/VideoError';
|
||||
import { isVideoPlayerSource } from './sourceUtils';
|
||||
|
||||
const VideoPlayerSourceFactory =
|
||||
NitroModules.createHybridObject<VideoPlayerSourceFactory>(
|
||||
'VideoPlayerSourceFactory'
|
||||
);
|
||||
|
||||
export const isVideoPlayerSource = (obj: any): obj is VideoPlayerSource => {
|
||||
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'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a `VideoPlayerSource` instance from a URI (string).
|
||||
*
|
||||
|
||||
11
packages/react-native-video/src/core/utils/sourceUtils.ts
Normal file
11
packages/react-native-video/src/core/utils/sourceUtils.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { VideoPlayerSource } from "../../spec/nitro/VideoPlayerSource.nitro";
|
||||
|
||||
export const isVideoPlayerSource = (obj: any): obj is VideoPlayerSource => {
|
||||
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'
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,74 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import type { ViewProps, ViewStyle } from 'react-native';
|
||||
import type { ViewStyle } from 'react-native';
|
||||
import { NitroModules } from 'react-native-nitro-modules';
|
||||
import type {
|
||||
VideoViewViewManager,
|
||||
VideoViewViewManagerFactory,
|
||||
} from '../../spec/nitro/VideoViewViewManager.nitro';
|
||||
import type { VideoViewEvents } from '../types/Events';
|
||||
import type { ResizeMode } from '../types/ResizeMode';
|
||||
import { tryParseNativeVideoError, VideoError } from '../types/VideoError';
|
||||
import type { VideoPlayer } from '../VideoPlayer';
|
||||
import { NativeVideoView } from './NativeVideoView';
|
||||
|
||||
export interface VideoViewProps extends Partial<VideoViewEvents>, 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
import type { VideoViewProps, VideoViewRef } from './ViewViewProps';
|
||||
|
||||
let nitroIdCounter = 1;
|
||||
const VideoViewViewManagerFactory =
|
||||
@@ -104,6 +44,7 @@ const updateProps = (manager: VideoViewViewManager, props: VideoViewProps) => {
|
||||
manager.willEnterPictureInPicture = props.willEnterPictureInPicture;
|
||||
manager.willExitPictureInPicture = props.willExitPictureInPicture;
|
||||
manager.keepScreenAwake = props.keepScreenAwake ?? true;
|
||||
manager.surfaceType = props.surfaceType ?? 'surface';
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
forwardRef,
|
||||
memo,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
type CSSProperties,
|
||||
} from "react";
|
||||
import { View, type ViewStyle } from "react-native";
|
||||
import type { VideoPlayer } from "../VideoPlayer.web";
|
||||
import type { VideoViewProps, VideoViewRef } from "./ViewViewProps";
|
||||
|
||||
/**
|
||||
* 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 = forwardRef<VideoViewRef, VideoViewProps>(
|
||||
(
|
||||
{
|
||||
player: nPlayer,
|
||||
controls = false,
|
||||
resizeMode = "none",
|
||||
// auto pip is unsupported
|
||||
pictureInPicture = false,
|
||||
autoEnterPictureInPicture = false,
|
||||
keepScreenAwake = true,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const player = nPlayer as unknown as VideoPlayer;
|
||||
const vRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
const videoElement = player.__getNativeRef();
|
||||
vRef.current?.appendChild(videoElement);
|
||||
return () => vRef.current?.replaceChildren();
|
||||
}, [player]);
|
||||
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
enterFullscreen: () => {
|
||||
player.player.requestFullscreen({ navigationUI: "hide" });
|
||||
},
|
||||
exitFullscreen: () => {
|
||||
document.exitFullscreen();
|
||||
},
|
||||
enterPictureInPicture: () => {
|
||||
player.player.requestPictureInPicture();
|
||||
},
|
||||
exitPictureInPicture: () => {
|
||||
document.exitPictureInPicture();
|
||||
},
|
||||
canEnterPictureInPicture: () => document.pictureInPictureEnabled,
|
||||
}),
|
||||
[player],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
player.player.controls(controls);
|
||||
}, [player, controls]);
|
||||
|
||||
useEffect(() => {
|
||||
const vid = player.__getNativeRef();
|
||||
const objectFit: CSSProperties["objectFit"] =
|
||||
resizeMode === "stretch" ? "fill" : resizeMode;
|
||||
vid.style = `position: absolute; inset: 0; width: 100%; height: 100%; object-fit: ${objectFit}`;
|
||||
}, [player, resizeMode]);
|
||||
|
||||
return (
|
||||
<View {...props}>
|
||||
<div
|
||||
ref={vRef}
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
VideoView.displayName = "VideoView";
|
||||
|
||||
export default memo(VideoView);
|
||||
@@ -0,0 +1,76 @@
|
||||
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<VideoViewEvents>, 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;
|
||||
}
|
||||
147
packages/react-native-video/src/core/web/MediaSession.ts
Normal file
147
packages/react-native-video/src/core/web/MediaSession.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import type videojs from "video.js";
|
||||
import type { CustomVideoMetadata } from "../types/VideoConfig";
|
||||
|
||||
type VideoJsPlayer = ReturnType<typeof videojs>;
|
||||
|
||||
const mediaSession = window.navigator.mediaSession;
|
||||
|
||||
export class MediaSessionHandler {
|
||||
enabled: boolean = false;
|
||||
|
||||
constructor(private player: VideoJsPlayer) {}
|
||||
|
||||
enable() {
|
||||
this.enabled = true;
|
||||
|
||||
const defaultSkipTime = 15;
|
||||
|
||||
const actionHandlers = [
|
||||
[
|
||||
"play",
|
||||
() => {
|
||||
this.player.play();
|
||||
},
|
||||
],
|
||||
[
|
||||
"pause",
|
||||
() => {
|
||||
this.player.pause();
|
||||
},
|
||||
],
|
||||
[
|
||||
"stop",
|
||||
() => {
|
||||
this.player.pause();
|
||||
this.player.currentTime(0);
|
||||
},
|
||||
],
|
||||
// videojs-contrib-ads
|
||||
[
|
||||
"seekbackward",
|
||||
(details: MediaSessionActionDetails) => {
|
||||
// @ts-expect-error ads is in an optional plugin that isn't typed.
|
||||
if (this.player.usingPlugin("ads") && this.player.ads.inAdBreak()) {
|
||||
return;
|
||||
}
|
||||
this.player.currentTime(
|
||||
Math.max(
|
||||
0,
|
||||
(this.player.currentTime() ?? 0) -
|
||||
(details.seekOffset || defaultSkipTime),
|
||||
),
|
||||
);
|
||||
},
|
||||
],
|
||||
[
|
||||
"seekforward",
|
||||
(details: MediaSessionActionDetails) => {
|
||||
// @ts-expect-error ads is in an optional plugin that isn't typed.
|
||||
if (this.player.usingPlugin("ads") && this.player.ads.inAdBreak()) {
|
||||
return;
|
||||
}
|
||||
this.player.currentTime(
|
||||
Math.min(
|
||||
this.player.duration() ?? 0,
|
||||
(this.player.currentTime() ?? 0) +
|
||||
(details.seekOffset || defaultSkipTime),
|
||||
),
|
||||
);
|
||||
},
|
||||
],
|
||||
[
|
||||
"seekto",
|
||||
(details: MediaSessionActionDetails) => {
|
||||
// @ts-expect-error ads is in an optional plugin that isn't typed.
|
||||
if (this.player.usingPlugin("ads") && this.player.ads.inAdBreak()) {
|
||||
return;
|
||||
}
|
||||
this.player.currentTime(details.seekTime);
|
||||
},
|
||||
],
|
||||
] as const;
|
||||
|
||||
for (const [action, handler] of actionHandlers) {
|
||||
try {
|
||||
mediaSession.setActionHandler(action, handler);
|
||||
} catch {
|
||||
this.player.log.debug(
|
||||
`Couldn't register media session action "${action}".`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const onPlaying = () => {
|
||||
mediaSession.playbackState = "playing";
|
||||
};
|
||||
const onPaused = () => {
|
||||
mediaSession.playbackState = "paused";
|
||||
};
|
||||
const onTimeUpdate = () => {
|
||||
const dur = this.player.duration();
|
||||
|
||||
if (Number.isFinite(dur)) {
|
||||
mediaSession.setPositionState({
|
||||
duration: dur,
|
||||
playbackRate: this.player.playbackRate(),
|
||||
position: this.player.currentTime(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.player.on("playing", onPlaying);
|
||||
this.player.on("paused", onPaused);
|
||||
if ("setPositionState" in mediaSession) {
|
||||
this.player.on("timeupdate", onTimeUpdate);
|
||||
}
|
||||
|
||||
this.disable = () => {
|
||||
this.enabled = false;
|
||||
this.player.off("playing", onPlaying);
|
||||
this.player.off("paused", onPaused);
|
||||
if ("setPositionState" in mediaSession) {
|
||||
this.player.off("timeupdate", onTimeUpdate);
|
||||
}
|
||||
mediaSession.metadata = null;
|
||||
for (const [action, _] of actionHandlers) {
|
||||
try {
|
||||
mediaSession.setActionHandler(action, null);
|
||||
} catch {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
disable() {}
|
||||
|
||||
updateMediaSession(metadata: CustomVideoMetadata | undefined) {
|
||||
if (!metadata) {
|
||||
mediaSession.metadata = null;
|
||||
return;
|
||||
}
|
||||
mediaSession.metadata = new window.MediaMetadata({
|
||||
title: metadata.title,
|
||||
album: metadata.subtitle,
|
||||
artist: metadata.artist,
|
||||
artwork: metadata.imageUri ? [{ src: metadata.imageUri }] : [],
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user