bitmovin-player-react-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +274 -0
- package/RNBitmovinPlayer.podspec +23 -0
- package/android/build.gradle +55 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +279 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +264 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +139 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +33 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +162 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/Events.kt +15 -0
- package/ios/Event+JSON.swift +132 -0
- package/ios/PlayerModule.m +61 -0
- package/ios/PlayerModule.swift +347 -0
- package/ios/RCTConvert+BitmovinPlayer.swift +79 -0
- package/ios/RNBitmovinPlayer.h +7 -0
- package/ios/RNBitmovinPlayer.xcodeproj/project.pbxproj +303 -0
- package/ios/RNPlayerView+PlayerListener.swift +83 -0
- package/ios/RNPlayerView.swift +50 -0
- package/ios/RNPlayerViewManager.m +29 -0
- package/ios/RNPlayerViewManager.swift +60 -0
- package/lib/index.d.ts +486 -0
- package/lib/index.js +218 -0
- package/lib/index.mjs +191 -0
- package/package.json +82 -0
- package/src/components/PlayerView/events.ts +69 -0
- package/src/components/PlayerView/index.tsx +106 -0
- package/src/components/PlayerView/native.ts +17 -0
- package/src/components/index.ts +1 -0
- package/src/events.ts +184 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/usePlayer.ts +10 -0
- package/src/hooks/useProxy.ts +36 -0
- package/src/index.ts +5 -0
- package/src/player.ts +229 -0
- package/src/source.ts +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Bitmovin Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Bitmovin Player React Native
|
|
2
|
+
|
|
3
|
+
Official React Native bindings for Bitmovin's mobile Player SDKs.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/bitmovin-player-react-native)
|
|
6
|
+

|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://community.bitmovin.com/?utm_source=github&utm_medium=bitmovin-player-react-native&utm_campaign=dev-community)
|
|
9
|
+
|
|
10
|
+
> :warning: **Beta Version**: The library is under active development. The current Beta release supports basic playback of unprotected video assets.
|
|
11
|
+
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Add package dependency](#add-package-dependency)
|
|
14
|
+
- [Setup iOS Player SDK](#setup-ios-player-sdk)
|
|
15
|
+
- [Setup Android Player SDK](#setup-android-player-sdk)
|
|
16
|
+
- [Getting Started](#getting-started)
|
|
17
|
+
- [Setting up a license key](#setting-up-a-license-key)
|
|
18
|
+
- [Accessing native `Player` instances](#accessing-native-player-instances)
|
|
19
|
+
- [Listening to events](#listening-to-events)
|
|
20
|
+
- [Contributing](#contributing)
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Since Bitmovin's native SDKs are distributed through custom [Cocoapods](https://github.com/bitmovin/cocoapod-specs) and [Maven](https://artifacts.bitmovin.com/ui/native/public-releases) repositories, the installation cannot be managed by React Native's Autolink and requires some extra steps. Please refer to the installation instructions for each platform below. For more information on integrating the native SDKs, refer to the [Getting Started guides](https://bitmovin.com/docs/getting-started).
|
|
25
|
+
|
|
26
|
+
### Add package dependency
|
|
27
|
+
|
|
28
|
+
This library is available as an [NPM package](https://www.npmjs.com/package/bitmovin-player-react-native) and may be added as a dependency to your project using any node-based package manager, e.g.
|
|
29
|
+
|
|
30
|
+
> npm
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npm install bitmovin-player-react-native --save
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> yarn
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
yarn add bitmovin-player-react-native
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Setup iOS Player SDK
|
|
43
|
+
|
|
44
|
+
If you ran `pod install` after installing the node package and received an error similar to the one below, it is because Bitmovin's custom cocoapods repository has not been added to the `Podfile` and the [`iOS Player SDK`](https://github.com/bitmovin/bitmovin-player-ios-samples) could not be resolved:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
[!] Unable to find a specification for `BitmovinPlayer (= 3.xx.x)` depended upon by `RNBitmovinPlayer`
|
|
48
|
+
|
|
49
|
+
You have either:
|
|
50
|
+
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
|
|
51
|
+
* mistyped the name or version.
|
|
52
|
+
* not added the source repo that hosts the Podspec to your Podfile.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
To fix above error, open your `ios/Podfile` and set up Bitmovin's pods source url:
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
59
|
+
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
60
|
+
|
|
61
|
+
# Bitmovin pods source url
|
|
62
|
+
source 'https://github.com/bitmovin/cocoapod-specs.git'
|
|
63
|
+
|
|
64
|
+
# iOS version should be 12 or greater.
|
|
65
|
+
# If you are running RN 0.69 you should be fine already.
|
|
66
|
+
platform :ios, '12.4'
|
|
67
|
+
install! 'cocoapods', :deterministic_uuids => false
|
|
68
|
+
|
|
69
|
+
target 'MyApp' do
|
|
70
|
+
config = use_native_modules!
|
|
71
|
+
|
|
72
|
+
# Rest of Podfile...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Now run `pod install` again (try with `--repo-update` if the error persists) - the error should now be resolved.
|
|
76
|
+
|
|
77
|
+
### Setup Android Player SDK
|
|
78
|
+
|
|
79
|
+
The Android setup also needs an extra step in order to correctly resolve the [Android Player SDK](https://github.com/bitmovin/bitmovin-player-android-samples) native dependency.
|
|
80
|
+
|
|
81
|
+
Just make sure to add Bitmovin's artifacts repository to the `allprojects.repositories` section of your `android/build.gradle`:
|
|
82
|
+
|
|
83
|
+
```groovy
|
|
84
|
+
allprojects {
|
|
85
|
+
repositories {
|
|
86
|
+
maven { url("$rootDir/../node_modules/react-native/android") }
|
|
87
|
+
maven { url("$rootDir/../node_modules/jsc-android/dist") }
|
|
88
|
+
mavenCentral {
|
|
89
|
+
content {
|
|
90
|
+
excludeGroup "com.facebook.react"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
google()
|
|
94
|
+
maven { url 'https://www.jitpack.io' }
|
|
95
|
+
// Add Bitmovin's artifacts repository url
|
|
96
|
+
maven { url 'https://artifacts.bitmovin.com/artifactory/public-releases' }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Getting Started
|
|
102
|
+
|
|
103
|
+
The following is the simplest working component one can create using this library:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import React, { useEffect, useCallback } from 'react';
|
|
107
|
+
import { View, Platform, StyleSheet } from 'react-native';
|
|
108
|
+
import {
|
|
109
|
+
usePlayer,
|
|
110
|
+
SourceType,
|
|
111
|
+
PlayerView,
|
|
112
|
+
} from 'bitmovin-player-react-native';
|
|
113
|
+
|
|
114
|
+
export default function PlayerSample() {
|
|
115
|
+
// The `usePlayer` hook creates or references a certain native `Player`
|
|
116
|
+
// instance from within any component.
|
|
117
|
+
const player = usePlayer({
|
|
118
|
+
// The only required parameter is the license key but it can be omitted from code upon correct
|
|
119
|
+
// Info.plist/AndroidManifest.xml configuration.
|
|
120
|
+
//
|
|
121
|
+
// Head to `Setting up a license key` for more information.
|
|
122
|
+
licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
// Load a streamable video source during component's initialization.
|
|
127
|
+
player.load({
|
|
128
|
+
// Select url and type dependeding on the running platform.
|
|
129
|
+
url:
|
|
130
|
+
Platform.OS === 'ios'
|
|
131
|
+
? // HLS for iOS
|
|
132
|
+
'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
|
|
133
|
+
: // Dash for Android
|
|
134
|
+
'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
|
|
135
|
+
type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
|
|
136
|
+
// Optionally set a title that will appear at player's top-left corner.
|
|
137
|
+
title: 'Art of Motion',
|
|
138
|
+
// Optionally load a poster image over the player.
|
|
139
|
+
poster:
|
|
140
|
+
'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/poster.jpg',
|
|
141
|
+
// Optionally set whether poster image will persist over player.
|
|
142
|
+
// Useful for audio-only streams. Default to false.
|
|
143
|
+
isPosterPersistent: false,
|
|
144
|
+
});
|
|
145
|
+
}, [player]);
|
|
146
|
+
|
|
147
|
+
// onReady is called when the player has downloaded initial
|
|
148
|
+
// video and audio and is ready to start playback.
|
|
149
|
+
const onReady = useCallback(
|
|
150
|
+
(event) => {
|
|
151
|
+
// Start playback
|
|
152
|
+
player.play();
|
|
153
|
+
// Print event timestamp
|
|
154
|
+
console.log(event.timestamp);
|
|
155
|
+
},
|
|
156
|
+
[player]
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Make sure to pass the `player` prop in `PlayerView`.
|
|
160
|
+
return (
|
|
161
|
+
<View style={styles.flex1}>
|
|
162
|
+
<PlayerView style={styles.flex1} player={player} onReady={onReady} />
|
|
163
|
+
</View>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const styles = StyleSheet.create({
|
|
168
|
+
flex1: {
|
|
169
|
+
flex: 1,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
If you're interested in a complete running example, head to [`example/`](https://github.com/bitmovin/bitmovin-player-react-native/tree/main/example).
|
|
175
|
+
|
|
176
|
+
### Setting up a license key
|
|
177
|
+
|
|
178
|
+
First of all, create a license key on the [Dashboard](https://bitmovin.com/dashboard) and then make sure to associate your iOS app bundle id with it (see more [here](https://bitmovin.com/docs/player/getting-started/ios#step-3-configure-your-player-license)).
|
|
179
|
+
|
|
180
|
+
Then your license key can be either set from code or by configuring `Info.plist` and `AndroidManifest.xml`.
|
|
181
|
+
|
|
182
|
+
#### Configuring through code
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Simply pass the `licenseKey` property to `PlayerConfig` when instantiating a player.
|
|
186
|
+
|
|
187
|
+
// With hooks
|
|
188
|
+
import { usePlayer } from 'bitmovin-player-react-native';
|
|
189
|
+
const player = usePlayer({
|
|
190
|
+
licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Without hooks
|
|
194
|
+
import { Player } from 'bitmovin-player-react-native';
|
|
195
|
+
const player = new Player({
|
|
196
|
+
// Make sure to use React.createRef if instantiating inside a component.
|
|
197
|
+
licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Configuring `Info.plist`
|
|
202
|
+
|
|
203
|
+
Add the following lines to the `<dict>` section of your `ios/Info.plist`:
|
|
204
|
+
|
|
205
|
+
```xml
|
|
206
|
+
<key>BitmovinPlayerLicenseKey</key>
|
|
207
|
+
<string>ENTER-YOUR-LICENSE-KEY</string>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### Configuring `AndroidManifest.xml`
|
|
211
|
+
|
|
212
|
+
Add the following line to the `<application>` section of your `android/app/src/main/AndroidManifest.xml`:
|
|
213
|
+
|
|
214
|
+
```xml
|
|
215
|
+
<meta-data android:name="BITMOVIN_PLAYER_LICENSE_KEY" android:value="ENTER-YOUR-LICENSE-KEY" />
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Accessing native `Player` instances
|
|
219
|
+
|
|
220
|
+
When you instantiate a player with `usePlayer` or `new Player()` from javascript, you're actually either creating a new `Player` instance in the native side (see [SDKs docs](https://bitmovin.com/docs/player/sdks) for more info) or referencing an existing one.
|
|
221
|
+
|
|
222
|
+
So it means that a player with the same `nativeId` in two different parts of the code is referencing the same in-memory instance internally.
|
|
223
|
+
|
|
224
|
+
**Example**
|
|
225
|
+
|
|
226
|
+
Both components in the example below are referencing the same native `Player` indexed as `my-player`. And even though each `<PlayerView />` creates a different `View` internally, the `Player` instance (which is a separate thing) remains the same. It just gets attached to a different view.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Using `usePlayer`
|
|
230
|
+
export const CompA = () => {
|
|
231
|
+
// Same `player` as in `CompB`.
|
|
232
|
+
const player = usePlayer({
|
|
233
|
+
nativeId: 'my-player',
|
|
234
|
+
});
|
|
235
|
+
return <PlayerView player={player} />;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Using `new Player()`
|
|
239
|
+
export const CompB = () => {
|
|
240
|
+
// Same `player` as in `CompA`.
|
|
241
|
+
const player = useRef(
|
|
242
|
+
new Player({
|
|
243
|
+
nativeId: 'my-player',
|
|
244
|
+
})
|
|
245
|
+
);
|
|
246
|
+
return <PlayerView player={player.current} />;
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Listening to events
|
|
251
|
+
|
|
252
|
+
Both player and source events can be registered from `PlayerView`, but not all of them. For a complete list of the events currently available, checkout [`EventProps`](https://github.com/bitmovin/bitmovin-player-react-native/blob/main/src/components/PlayerView/events.ts#L29) and [`events.ts`](https://github.com/bitmovin/bitmovin-player-react-native/blob/main/src/events.ts).
|
|
253
|
+
|
|
254
|
+
To register an event callback, just pass its name prefixed with `on` as a `PlayerView` prop:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
return (
|
|
258
|
+
<PlayerView
|
|
259
|
+
onReady={onReady}
|
|
260
|
+
onMuted={onMuted}
|
|
261
|
+
onPaused={onPaused}
|
|
262
|
+
onPlayerActive={onPlayerActive}
|
|
263
|
+
onSourceLoaded={onSourceLoaded}
|
|
264
|
+
onPlayerError={onPlayerError}
|
|
265
|
+
onSourceError={onSourceError}
|
|
266
|
+
onPlaybackFinished={onPlaybackFinished}
|
|
267
|
+
{...}
|
|
268
|
+
/>
|
|
269
|
+
);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Contributing
|
|
273
|
+
|
|
274
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "RNBitmovinPlayer"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => "12.0" }
|
|
14
|
+
s.source = {
|
|
15
|
+
:git => "https://github.com/bitmovin/player-react-native-bridge.git",
|
|
16
|
+
:tag => "#{s.version}"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
20
|
+
|
|
21
|
+
s.dependency "React-Core"
|
|
22
|
+
s.dependency "BitmovinPlayer", "3.23.0"
|
|
23
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext {
|
|
3
|
+
kotlinVersion = '1.7.0'
|
|
4
|
+
androidToolsVersion = '7.0.4'
|
|
5
|
+
}
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:$androidToolsVersion"
|
|
12
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
apply plugin: 'com.android.library'
|
|
17
|
+
apply plugin: 'kotlin-android'
|
|
18
|
+
|
|
19
|
+
repositories {
|
|
20
|
+
mavenLocal()
|
|
21
|
+
maven {
|
|
22
|
+
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
|
23
|
+
url "$rootDir/../node_modules/react-native/android"
|
|
24
|
+
}
|
|
25
|
+
google()
|
|
26
|
+
mavenCentral()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
android {
|
|
30
|
+
compileSdk 31
|
|
31
|
+
defaultConfig {
|
|
32
|
+
minSdkVersion 21
|
|
33
|
+
targetSdkVersion 31
|
|
34
|
+
versionCode 1
|
|
35
|
+
versionName '1.0'
|
|
36
|
+
}
|
|
37
|
+
buildTypes {
|
|
38
|
+
release {
|
|
39
|
+
minifyEnabled false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
lintOptions {
|
|
43
|
+
disable 'GradleCompatible'
|
|
44
|
+
}
|
|
45
|
+
compileOptions {
|
|
46
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
47
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
|
53
|
+
implementation 'com.bitmovin.player:player:3.20.0'
|
|
54
|
+
implementation 'com.facebook.react:react-native:+'
|
|
55
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
package com.bitmovin.player.reactnative
|
|
2
|
+
|
|
3
|
+
import com.bitmovin.player.api.Player
|
|
4
|
+
import com.bitmovin.player.reactnative.converter.JsonConverter
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.facebook.react.bridge.ReactMethod
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
10
|
+
import com.facebook.react.module.annotations.ReactModule;
|
|
11
|
+
import com.facebook.react.uimanager.UIManagerModule
|
|
12
|
+
import java.util.UUID
|
|
13
|
+
|
|
14
|
+
@ReactModule(name = PlayerModule.name)
|
|
15
|
+
class PlayerModule(private val context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
|
16
|
+
/**
|
|
17
|
+
* In-memory mapping of `id` <-> `Player`.
|
|
18
|
+
*/
|
|
19
|
+
private var registry: MutableMap<String, Player> = mutableMapOf()
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Exported module name to JS.
|
|
23
|
+
*/
|
|
24
|
+
companion object {
|
|
25
|
+
const val name = "PlayerModule"
|
|
26
|
+
}
|
|
27
|
+
override fun getName() = PlayerModule.name
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Fetch the `Player` instance with id equal to `playerId` inside this module's `registry`.
|
|
31
|
+
* @param playerId Target player to look inside registry.
|
|
32
|
+
*/
|
|
33
|
+
fun getPlayer(playerId: String?): Player? {
|
|
34
|
+
if (playerId == null) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
return registry[playerId]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Synchronously generate a random UUID for `Player`s native id when no `nativeId` is provided
|
|
42
|
+
* by the user.
|
|
43
|
+
* @return Random UUID RFC 4122 version 4.
|
|
44
|
+
*/
|
|
45
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
46
|
+
fun generateUUIDv4(): String = UUID.randomUUID().toString()
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Create a new `Player` instance for the given `config` if no one exists already.
|
|
50
|
+
* @param config Player configuration options sent from JS.
|
|
51
|
+
*/
|
|
52
|
+
@ReactMethod
|
|
53
|
+
fun initWithConfig(playerId: String, config: ReadableMap?) {
|
|
54
|
+
uiManager()?.addUIBlock {
|
|
55
|
+
if (!registry.containsKey(playerId)) {
|
|
56
|
+
JsonConverter.toPlayerConfig(config)?.let {
|
|
57
|
+
registry[playerId] = Player.create(context, it)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Load the source of the given `playerId` with `config` options from JS.
|
|
65
|
+
* @param playerId Target player.
|
|
66
|
+
* @param config Source configuration options from JS.
|
|
67
|
+
*/
|
|
68
|
+
@ReactMethod
|
|
69
|
+
fun loadSource(playerId: String, config: ReadableMap?) {
|
|
70
|
+
uiManager()?.addUIBlock {
|
|
71
|
+
JsonConverter.toSourceConfig(config)?.let {
|
|
72
|
+
registry[playerId]?.load(it)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Call `.unload()` on `playerId`'s player.
|
|
79
|
+
* @param playerId Target player Id.
|
|
80
|
+
*/
|
|
81
|
+
@ReactMethod
|
|
82
|
+
fun unload(playerId: String) {
|
|
83
|
+
uiManager()?.addUIBlock {
|
|
84
|
+
registry[playerId]?.unload()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Call `.play()` on `playerId`'s player.
|
|
90
|
+
* @param playerId Target player Id.
|
|
91
|
+
*/
|
|
92
|
+
@ReactMethod
|
|
93
|
+
fun play(playerId: String) {
|
|
94
|
+
uiManager()?.addUIBlock {
|
|
95
|
+
registry[playerId]?.play()
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Call `.pause()` on `playerId`'s player.
|
|
101
|
+
* @param playerId Target player Id.
|
|
102
|
+
*/
|
|
103
|
+
@ReactMethod
|
|
104
|
+
fun pause(playerId: String) {
|
|
105
|
+
uiManager()?.addUIBlock {
|
|
106
|
+
registry[playerId]?.pause()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Call `.seek(time:)` on `playerId`'s player.
|
|
112
|
+
* @param playerId Target player Id.
|
|
113
|
+
* @param time Seek time in seconds.
|
|
114
|
+
*/
|
|
115
|
+
@ReactMethod
|
|
116
|
+
fun seek(playerId: String, time: Double) {
|
|
117
|
+
uiManager()?.addUIBlock {
|
|
118
|
+
registry[playerId]?.seek(time)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Call `.mute()` on `playerId`'s player.
|
|
124
|
+
* @param playerId Target player Id.
|
|
125
|
+
*/
|
|
126
|
+
@ReactMethod
|
|
127
|
+
fun mute(playerId: String) {
|
|
128
|
+
uiManager()?.addUIBlock {
|
|
129
|
+
registry[playerId]?.mute()
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Call `.unmute()` on `playerId`'s player.
|
|
135
|
+
* @param playerId Target player Id.
|
|
136
|
+
*/
|
|
137
|
+
@ReactMethod
|
|
138
|
+
fun unmute(playerId: String) {
|
|
139
|
+
uiManager()?.addUIBlock {
|
|
140
|
+
registry[playerId]?.unmute()
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Call `.destroy()` on `playerId`'s player.
|
|
146
|
+
* @param playerId Target player Id.
|
|
147
|
+
*/
|
|
148
|
+
@ReactMethod
|
|
149
|
+
fun destroy(playerId: String) {
|
|
150
|
+
uiManager()?.addUIBlock {
|
|
151
|
+
registry[playerId]?.destroy()
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Call `.setVolume(volume:)` on `playerId`'s player.
|
|
157
|
+
* @param playerId Target player Id.
|
|
158
|
+
* @param volume Volume level integer between 0 to 100.
|
|
159
|
+
*/
|
|
160
|
+
@ReactMethod
|
|
161
|
+
fun setVolume(playerId: String, volume: Int) {
|
|
162
|
+
uiManager()?.addUIBlock {
|
|
163
|
+
registry[playerId]?.volume = volume
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Resolve `playerId`'s current volume.
|
|
169
|
+
* @param playerId Target player Id.
|
|
170
|
+
* @param promise JS promise object.
|
|
171
|
+
*/
|
|
172
|
+
@ReactMethod
|
|
173
|
+
fun getVolume(playerId: String, promise: Promise) {
|
|
174
|
+
uiManager()?.addUIBlock {
|
|
175
|
+
promise.resolve(registry[playerId]?.volume)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Resolve the source of `playerId`'s player.
|
|
181
|
+
* @param playerId Target player Id.
|
|
182
|
+
* @param promise JS promise object.
|
|
183
|
+
*/
|
|
184
|
+
@ReactMethod
|
|
185
|
+
fun source(playerId: String, promise: Promise) {
|
|
186
|
+
uiManager()?.addUIBlock {
|
|
187
|
+
promise.resolve(JsonConverter.fromSource(registry[playerId]?.source))
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Resolve `playerId`'s current playback time.
|
|
193
|
+
* @param playerId Target player Id.
|
|
194
|
+
* @param promise JS promise object.
|
|
195
|
+
*/
|
|
196
|
+
@ReactMethod
|
|
197
|
+
fun currentTime(playerId: String, mode: String?, promise: Promise) {
|
|
198
|
+
uiManager()?.addUIBlock {
|
|
199
|
+
var timeOffset: Double = 0.0
|
|
200
|
+
if (mode != null) {
|
|
201
|
+
timeOffset = if (mode == "relative") {
|
|
202
|
+
registry[playerId]?.playbackTimeOffsetToRelativeTime ?: 0.0
|
|
203
|
+
} else {
|
|
204
|
+
registry[playerId]?.playbackTimeOffsetToAbsoluteTime ?: 0.0
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
val currentTime = registry[playerId]?.currentTime
|
|
208
|
+
if (currentTime != null) {
|
|
209
|
+
promise.resolve(currentTime + timeOffset)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Resolve `playerId`'s current source duration.
|
|
216
|
+
* @param playerId Target player Id.
|
|
217
|
+
* @param promise JS promise object.
|
|
218
|
+
*/
|
|
219
|
+
@ReactMethod
|
|
220
|
+
fun duration(playerId: String, promise: Promise) {
|
|
221
|
+
uiManager()?.addUIBlock {
|
|
222
|
+
promise.resolve(registry[playerId]?.duration)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Resolve `playerId`'s current muted state.
|
|
228
|
+
* @param playerId Target player Id.
|
|
229
|
+
* @param promise JS promise object.
|
|
230
|
+
*/
|
|
231
|
+
@ReactMethod
|
|
232
|
+
fun isMuted(playerId: String, promise: Promise) {
|
|
233
|
+
uiManager()?.addUIBlock {
|
|
234
|
+
promise.resolve(registry[playerId]?.isMuted)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Resolve `playerId`'s current playing state.
|
|
240
|
+
* @param playerId Target player Id.
|
|
241
|
+
* @param promise JS promise object.
|
|
242
|
+
*/
|
|
243
|
+
@ReactMethod
|
|
244
|
+
fun isPlaying(playerId: String, promise: Promise) {
|
|
245
|
+
uiManager()?.addUIBlock {
|
|
246
|
+
promise.resolve(registry[playerId]?.isPlaying)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Resolve `playerId`'s current paused state.
|
|
252
|
+
* @param playerId Target player Id.
|
|
253
|
+
* @param promise JS promise object.
|
|
254
|
+
*/
|
|
255
|
+
@ReactMethod
|
|
256
|
+
fun isPaused(playerId: String, promise: Promise) {
|
|
257
|
+
uiManager()?.addUIBlock {
|
|
258
|
+
promise.resolve(registry[playerId]?.isPaused)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Resolve `playerId`'s current live state.
|
|
264
|
+
* @param playerId Target player Id.
|
|
265
|
+
* @param promise JS promise object.
|
|
266
|
+
*/
|
|
267
|
+
@ReactMethod
|
|
268
|
+
fun isLive(playerId: String, promise: Promise) {
|
|
269
|
+
uiManager()?.addUIBlock {
|
|
270
|
+
promise.resolve(registry[playerId]?.isLive)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Helper function that returns the initialized `UIManager` instance.
|
|
276
|
+
*/
|
|
277
|
+
private fun uiManager(): UIManagerModule? =
|
|
278
|
+
context.getNativeModule(UIManagerModule::class.java)
|
|
279
|
+
}
|