bitmovin-player-react-native 0.2.0 → 0.3.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/README.md +69 -14
- package/RNBitmovinPlayer.podspec +2 -2
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +19 -3
- package/ios/RCTConvert+BitmovinPlayer.swift +17 -0
- package/lib/index.d.ts +83 -3
- package/lib/index.js +52 -19
- package/lib/index.mjs +48 -18
- package/package.json +14 -10
- package/src/player.ts +81 -0
package/README.md
CHANGED
|
@@ -3,23 +3,42 @@
|
|
|
3
3
|
Official React Native bindings for Bitmovin's mobile Player SDKs.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/bitmovin-player-react-native)
|
|
6
|
-

|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://community.bitmovin.com/?utm_source=github&utm_medium=bitmovin-player-react-native&utm_campaign=dev-community)
|
|
9
9
|
|
|
10
|
-
>
|
|
11
|
-
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
|
|
16
|
-
- [
|
|
17
|
-
|
|
18
|
-
- [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- [
|
|
10
|
+
> The library is under active development.
|
|
11
|
+
|
|
12
|
+
- [Bitmovin Player React Native](#bitmovin-player-react-native)
|
|
13
|
+
- [Platform Support](#platform-support)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Add package dependency](#add-package-dependency)
|
|
16
|
+
- [Setup iOS Player SDK](#setup-ios-player-sdk)
|
|
17
|
+
- [Setup Android Player SDK](#setup-android-player-sdk)
|
|
18
|
+
- [Getting Started](#getting-started)
|
|
19
|
+
- [Setting up a license key](#setting-up-a-license-key)
|
|
20
|
+
- [Configuring through code](#configuring-through-code)
|
|
21
|
+
- [Setting up a playback configurations](#setting-up-a-playback-configurations)
|
|
22
|
+
- [Configuring `Info.plist`](#configuring-infoplist)
|
|
23
|
+
- [Configuring `AndroidManifest.xml`](#configuring-androidmanifestxml)
|
|
24
|
+
- [Accessing native `Player` instances](#accessing-native-player-instances)
|
|
25
|
+
- [Listening to events](#listening-to-events)
|
|
26
|
+
- [Enabling DRM protection](#enabling-drm-protection)
|
|
27
|
+
- [Prepare hooks](#prepare-hooks)
|
|
28
|
+
- [Adding external subtitle tracks](#adding-external-subtitle-tracks)
|
|
29
|
+
- [Contributing](#contributing)
|
|
30
|
+
|
|
31
|
+
## Platform Support
|
|
32
|
+
|
|
33
|
+
This library requires at least React Native 0.64+ and React 17+ to work properly. The currently supported platforms are:
|
|
34
|
+
|
|
35
|
+
- iOS 12.0+
|
|
36
|
+
- tvOS 12.0+
|
|
37
|
+
- Android API 16+
|
|
38
|
+
- Android TV API 17+
|
|
39
|
+
- Fire TV (just make sure the Android API level is at least 17+)
|
|
40
|
+
|
|
41
|
+
Please note that browsers and other browser-like environments such as webOS and Tizen are not supported.
|
|
23
42
|
|
|
24
43
|
## Installation
|
|
25
44
|
|
|
@@ -200,6 +219,42 @@ const player = new Player({
|
|
|
200
219
|
});
|
|
201
220
|
```
|
|
202
221
|
|
|
222
|
+
### Setting up a playback configurations
|
|
223
|
+
|
|
224
|
+
If needed, the default player behavior can be configured through the `playbackConfig` key when initialized.
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Simply pass the `playbackConfig` property to `PlayerConfig` when instantiating a player.
|
|
228
|
+
|
|
229
|
+
// With hooks
|
|
230
|
+
import { usePlayer } from 'bitmovin-player-react-native';
|
|
231
|
+
const player = usePlayer({
|
|
232
|
+
playbackConfig: {
|
|
233
|
+
// Specifies whether the playback starts immediately after loading a source or not. Default is false.
|
|
234
|
+
isAutoplayEnabled: true,
|
|
235
|
+
// Specifies if playback starts muted. Default is false.
|
|
236
|
+
isMuted: true,
|
|
237
|
+
// Specifies if time shift for live streams should be enabled. Default is true.
|
|
238
|
+
isTimeShiftEnabled: true,
|
|
239
|
+
// Whether background playback is enabled or not. Default is false.
|
|
240
|
+
// Only available for iOS.
|
|
241
|
+
isBackgroundPlaybackEnabled: true,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Without hooks
|
|
246
|
+
import { Player } from 'bitmovin-player-react-native';
|
|
247
|
+
const player = new Player({
|
|
248
|
+
// Make sure to use React.createRef if instantiating inside a component.
|
|
249
|
+
playbackConfig: {
|
|
250
|
+
isAutoplayEnabled: true,
|
|
251
|
+
isMuted: true,
|
|
252
|
+
isTimeShiftEnabled: true,
|
|
253
|
+
isBackgroundPlaybackEnabled: true,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
203
258
|
#### Configuring `Info.plist`
|
|
204
259
|
|
|
205
260
|
Add the following lines to the `<dict>` section of your `ios/Info.plist`:
|
package/RNBitmovinPlayer.podspec
CHANGED
|
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package["license"]
|
|
11
11
|
s.authors = package["author"]
|
|
12
12
|
|
|
13
|
-
s.platforms = { :ios => "12.4" }
|
|
13
|
+
s.platforms = { :ios => "12.4", :tvos => "12.4" }
|
|
14
14
|
s.source = {
|
|
15
15
|
:git => "https://github.com/bitmovin/bitmovin-player-react-native.git",
|
|
16
16
|
:tag => "v#{s.version}"
|
|
@@ -19,5 +19,5 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
20
20
|
|
|
21
21
|
s.dependency "React-Core"
|
|
22
|
-
s.dependency "BitmovinPlayer", "3.
|
|
22
|
+
s.dependency "BitmovinPlayer", "3.28.0"
|
|
23
23
|
end
|
package/android/build.gradle
CHANGED
|
@@ -50,6 +50,6 @@ android {
|
|
|
50
50
|
|
|
51
51
|
dependencies {
|
|
52
52
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
|
53
|
-
implementation 'com.bitmovin.player:player:3.
|
|
53
|
+
implementation 'com.bitmovin.player:player:3.24.2'
|
|
54
54
|
implementation 'com.facebook.react:react-native:+'
|
|
55
55
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.bitmovin.player.reactnative.converter
|
|
2
2
|
|
|
3
|
+
import com.bitmovin.player.api.PlaybackConfig
|
|
3
4
|
import com.bitmovin.player.api.PlayerConfig
|
|
4
5
|
import com.bitmovin.player.api.drm.WidevineConfig
|
|
5
6
|
import com.bitmovin.player.api.event.PlayerEvent
|
|
@@ -25,10 +26,25 @@ class JsonConverter {
|
|
|
25
26
|
*/
|
|
26
27
|
@JvmStatic
|
|
27
28
|
fun toPlayerConfig(json: ReadableMap?): PlayerConfig {
|
|
28
|
-
if (json
|
|
29
|
-
|
|
29
|
+
if (json == null) return PlayerConfig()
|
|
30
|
+
val playerConfig = if (json.hasKey("licenseKey")) {
|
|
31
|
+
PlayerConfig(key = json.getString("licenseKey"))
|
|
32
|
+
} else {
|
|
33
|
+
PlayerConfig()
|
|
34
|
+
}
|
|
35
|
+
if (json.hasKey("playbackConfig")) {
|
|
36
|
+
var playbackConfigJson = json.getMap("playbackConfig")
|
|
37
|
+
if (playbackConfigJson?.hasKey("isAutoplayEnabled") == true) {
|
|
38
|
+
playerConfig.playbackConfig.isAutoplayEnabled = playbackConfigJson.getBoolean("isAutoplayEnabled")
|
|
39
|
+
}
|
|
40
|
+
if(playbackConfigJson?.hasKey("isMuted") == true) {
|
|
41
|
+
playerConfig.playbackConfig.isMuted = playbackConfigJson.getBoolean("isMuted")
|
|
42
|
+
}
|
|
43
|
+
if(playbackConfigJson?.hasKey("isTimeShiftEnabled") == true) {
|
|
44
|
+
playerConfig.playbackConfig.isTimeShiftEnabled = playbackConfigJson.getBoolean("isTimeShiftEnabled")
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
|
-
return
|
|
47
|
+
return playerConfig
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
/**
|
|
@@ -15,6 +15,23 @@ extension RCTConvert {
|
|
|
15
15
|
if let licenseKey = json["licenseKey"] as? String {
|
|
16
16
|
playerConfig.key = licenseKey
|
|
17
17
|
}
|
|
18
|
+
if let playbackConfig = json["playbackConfig"] as? [String: Any?] {
|
|
19
|
+
if let isAutoplayEnabled = playbackConfig["isAutoplayEnabled"] as? Bool {
|
|
20
|
+
playerConfig.playbackConfig.isAutoplayEnabled = isAutoplayEnabled
|
|
21
|
+
}
|
|
22
|
+
if let isMuted = playbackConfig["isMuted"] as? Bool {
|
|
23
|
+
playerConfig.playbackConfig.isMuted = isMuted
|
|
24
|
+
}
|
|
25
|
+
if let isTimeShiftEnabled = playbackConfig["isTimeShiftEnabled"] as? Bool {
|
|
26
|
+
playerConfig.playbackConfig.isTimeShiftEnabled = isTimeShiftEnabled
|
|
27
|
+
}
|
|
28
|
+
if let isBackgroundPlaybackEnabled = playbackConfig["isBackgroundPlaybackEnabled"] as? Bool {
|
|
29
|
+
playerConfig.playbackConfig.isBackgroundPlaybackEnabled = isBackgroundPlaybackEnabled
|
|
30
|
+
}
|
|
31
|
+
if let isPictureInPictureEnabled = playbackConfig["isPictureInPictureEnabled"] as? Bool {
|
|
32
|
+
playerConfig.playbackConfig.isPictureInPictureEnabled = isPictureInPictureEnabled
|
|
33
|
+
}
|
|
34
|
+
}
|
|
18
35
|
return playerConfig
|
|
19
36
|
}
|
|
20
37
|
|
package/lib/index.d.ts
CHANGED
|
@@ -570,7 +570,7 @@ declare class Drm extends NativeInstance<DrmConfig> {
|
|
|
570
570
|
* @param message - Base64 encoded message data.
|
|
571
571
|
* @param assetId - Optional asset ID. Only sent by iOS.
|
|
572
572
|
*/
|
|
573
|
-
onPrepareMessage: (message: string, assetId?: string
|
|
573
|
+
onPrepareMessage: (message: string, assetId?: string) => void;
|
|
574
574
|
/**
|
|
575
575
|
* iOS only.
|
|
576
576
|
*
|
|
@@ -763,6 +763,86 @@ interface PlayerConfig extends NativeInstanceConfig {
|
|
|
763
763
|
* ```
|
|
764
764
|
*/
|
|
765
765
|
licenseKey?: string;
|
|
766
|
+
/**
|
|
767
|
+
* Configures playback behaviour. A default PlaybackConfig is set initially.
|
|
768
|
+
*/
|
|
769
|
+
playbackConfig?: PlaybackConfig;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Configures the playback behaviour of the player.
|
|
773
|
+
*/
|
|
774
|
+
interface PlaybackConfig {
|
|
775
|
+
/**
|
|
776
|
+
* Whether the player starts playing automatically after loading a source or not. Default is `false`.
|
|
777
|
+
* @example
|
|
778
|
+
* ```
|
|
779
|
+
* const player = new Player({
|
|
780
|
+
* playbackConfig: {
|
|
781
|
+
* isAutoplayEnabled: true,
|
|
782
|
+
* },
|
|
783
|
+
* });
|
|
784
|
+
* ```
|
|
785
|
+
*/
|
|
786
|
+
isAutoplayEnabled?: boolean;
|
|
787
|
+
/**
|
|
788
|
+
* Whether the sound is muted on startup or not. Default value is `false`.
|
|
789
|
+
* @example
|
|
790
|
+
* ```
|
|
791
|
+
* const player = new Player({
|
|
792
|
+
* playbackConfig: {
|
|
793
|
+
* isMuted: true,
|
|
794
|
+
* },
|
|
795
|
+
* });
|
|
796
|
+
* ```
|
|
797
|
+
*/
|
|
798
|
+
isMuted?: boolean;
|
|
799
|
+
/**
|
|
800
|
+
* Whether time shift / DVR for live streams is enabled or not. Default is `true`.
|
|
801
|
+
* @example
|
|
802
|
+
* ```
|
|
803
|
+
* const player = new Player({
|
|
804
|
+
* playbackConfig: {
|
|
805
|
+
* isTimeShiftEnabled: false,
|
|
806
|
+
* },
|
|
807
|
+
* });
|
|
808
|
+
* ```
|
|
809
|
+
*/
|
|
810
|
+
isTimeShiftEnabled?: boolean;
|
|
811
|
+
/**
|
|
812
|
+
* Whether background playback is enabled or not.
|
|
813
|
+
* Default is `false`.
|
|
814
|
+
*
|
|
815
|
+
* When set to `true`, playback is not automatically paused
|
|
816
|
+
* anymore when the app moves to the background.
|
|
817
|
+
* When set to `true`, also make sure to properly configure your app to allow
|
|
818
|
+
* background playback.
|
|
819
|
+
*
|
|
820
|
+
* On tvOS, background playback is only supported for audio-only content.
|
|
821
|
+
*
|
|
822
|
+
* Default is `false`.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```
|
|
826
|
+
* const player = new Player({
|
|
827
|
+
* {
|
|
828
|
+
* isBackgroundPlaybackEnabled: true,
|
|
829
|
+
* }
|
|
830
|
+
* })
|
|
831
|
+
* ```
|
|
832
|
+
*/
|
|
833
|
+
isBackgroundPlaybackEnabled?: boolean;
|
|
834
|
+
/**
|
|
835
|
+
* Whether the picture-in-picture mode option is enabled for iOS or not. Default is `false`.
|
|
836
|
+
* @example
|
|
837
|
+
* ```
|
|
838
|
+
* const player = new Player({
|
|
839
|
+
* playbackConfig: {
|
|
840
|
+
* isPictureInPictureEnabled: true,
|
|
841
|
+
* },
|
|
842
|
+
* });
|
|
843
|
+
* ```
|
|
844
|
+
*/
|
|
845
|
+
isPictureInPictureEnabled?: boolean;
|
|
766
846
|
}
|
|
767
847
|
/**
|
|
768
848
|
* Loads, controls and renders audio and video content represented through `Source`s. A player
|
|
@@ -850,7 +930,7 @@ declare class Player extends NativeInstance<PlayerConfig> {
|
|
|
850
930
|
*
|
|
851
931
|
* @param mode - The time mode to specify: an absolute UNIX timestamp ('absolute') or relative time ('relative').
|
|
852
932
|
*/
|
|
853
|
-
getCurrentTime: (mode?:
|
|
933
|
+
getCurrentTime: (mode?: 'relative' | 'absolute') => Promise<number>;
|
|
854
934
|
/**
|
|
855
935
|
* @returns The total duration in seconds of the current video or INFINITY if it’s a live stream.
|
|
856
936
|
*/
|
|
@@ -918,4 +998,4 @@ declare function PlayerView(props: PlayerViewProps): JSX.Element;
|
|
|
918
998
|
*/
|
|
919
999
|
declare function usePlayer(config?: PlayerConfig): Player;
|
|
920
1000
|
|
|
921
|
-
export { BasePlayerViewProps, DestroyEvent, Drm, DrmConfig, ErrorEvent, Event, EventSource, FairplayConfig, LoadingState, MutedEvent, PausedEvent, PlayEvent, PlaybackFinishedEvent, Player, PlayerActiveEvent, PlayerConfig, PlayerErrorEvent, PlayerView, PlayerViewProps, PlayerWarningEvent, PlayingEvent, ReadyEvent, SeekEvent, SeekedEvent, SideLoadedSubtitleTrack, Source, SourceConfig, SourceErrorEvent, SourceLoadEvent, SourceLoadedEvent, SourceType, SourceUnloadedEvent, SourceWarningEvent, SubtitleAddedEvent, SubtitleChangedEvent, SubtitleFormat, SubtitleRemovedEvent, SubtitleTrack, TimeChangedEvent, UnmutedEvent, WidevineConfig, usePlayer };
|
|
1001
|
+
export { BasePlayerViewProps, DestroyEvent, Drm, DrmConfig, ErrorEvent, Event, EventSource, FairplayConfig, LoadingState, MutedEvent, PausedEvent, PlayEvent, PlaybackConfig, PlaybackFinishedEvent, Player, PlayerActiveEvent, PlayerConfig, PlayerErrorEvent, PlayerView, PlayerViewProps, PlayerWarningEvent, PlayingEvent, ReadyEvent, SeekEvent, SeekedEvent, SideLoadedSubtitleTrack, Source, SourceConfig, SourceErrorEvent, SourceLoadEvent, SourceLoadedEvent, SourceType, SourceUnloadedEvent, SourceWarningEvent, SubtitleAddedEvent, SubtitleChangedEvent, SubtitleFormat, SubtitleRemovedEvent, SubtitleTrack, TimeChangedEvent, UnmutedEvent, WidevineConfig, usePlayer };
|
package/lib/index.js
CHANGED
|
@@ -18,7 +18,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
}
|
|
19
19
|
return to;
|
|
20
20
|
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
22
25
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
26
|
var __publicField = (obj, key, value) => {
|
|
24
27
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -55,12 +58,15 @@ function unwrapNativeEvent(event) {
|
|
|
55
58
|
return (0, import_lodash.default)(event.nativeEvent, ["target"]);
|
|
56
59
|
}
|
|
57
60
|
function useProxy(viewRef) {
|
|
58
|
-
return (0, import_react.useCallback)(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
return (0, import_react.useCallback)(
|
|
62
|
+
(callback) => (event) => {
|
|
63
|
+
const node = event.target._nativeTag;
|
|
64
|
+
if (node === (0, import_react_native2.findNodeHandle)(viewRef.current)) {
|
|
65
|
+
callback?.(unwrapNativeEvent(event));
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
[viewRef]
|
|
69
|
+
);
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
// src/components/PlayerView/index.tsx
|
|
@@ -71,10 +77,14 @@ var styles = import_react_native3.StyleSheet.create({
|
|
|
71
77
|
});
|
|
72
78
|
function dispatch(command, node, playerId) {
|
|
73
79
|
const commandId = import_react_native3.Platform.OS === "android" ? import_react_native3.UIManager.NativePlayerView.Commands[command].toString() : import_react_native3.UIManager.getViewManagerConfig("NativePlayerView").Commands[command];
|
|
74
|
-
import_react_native3.UIManager.dispatchViewManagerCommand(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
import_react_native3.UIManager.dispatchViewManagerCommand(
|
|
81
|
+
node,
|
|
82
|
+
commandId,
|
|
83
|
+
import_react_native3.Platform.select({
|
|
84
|
+
ios: [playerId],
|
|
85
|
+
android: [node, playerId]
|
|
86
|
+
})
|
|
87
|
+
);
|
|
78
88
|
}
|
|
79
89
|
function PlayerView(props) {
|
|
80
90
|
const nativeView = (0, import_react2.useRef)(null);
|
|
@@ -152,18 +162,27 @@ var Drm = class extends NativeInstance {
|
|
|
152
162
|
});
|
|
153
163
|
__publicField(this, "onPrepareCertificate", (certificate) => {
|
|
154
164
|
if (this.config?.fairplay?.prepareCertificate) {
|
|
155
|
-
DrmModule.setPreparedCertificate(
|
|
165
|
+
DrmModule.setPreparedCertificate(
|
|
166
|
+
this.nativeId,
|
|
167
|
+
this.config?.fairplay?.prepareCertificate?.(certificate)
|
|
168
|
+
);
|
|
156
169
|
}
|
|
157
170
|
});
|
|
158
171
|
__publicField(this, "onPrepareMessage", (message, assetId) => {
|
|
159
172
|
const config = import_react_native5.Platform.OS === "ios" ? this.config?.fairplay : this.config?.widevine;
|
|
160
173
|
if (config && config.prepareMessage) {
|
|
161
|
-
DrmModule.setPreparedMessage(
|
|
174
|
+
DrmModule.setPreparedMessage(
|
|
175
|
+
this.nativeId,
|
|
176
|
+
import_react_native5.Platform.OS === "ios" ? config.prepareMessage?.(message, assetId) : config.prepareMessage?.(message)
|
|
177
|
+
);
|
|
162
178
|
}
|
|
163
179
|
});
|
|
164
180
|
__publicField(this, "onPrepareSyncMessage", (syncMessage, assetId) => {
|
|
165
181
|
if (this.config?.fairplay?.prepareSyncMessage) {
|
|
166
|
-
DrmModule.setPreparedSyncMessage(
|
|
182
|
+
DrmModule.setPreparedSyncMessage(
|
|
183
|
+
this.nativeId,
|
|
184
|
+
this.config?.fairplay?.prepareSyncMessage?.(syncMessage, assetId)
|
|
185
|
+
);
|
|
167
186
|
}
|
|
168
187
|
});
|
|
169
188
|
__publicField(this, "onPrepareLicense", (license) => {
|
|
@@ -174,12 +193,18 @@ var Drm = class extends NativeInstance {
|
|
|
174
193
|
});
|
|
175
194
|
__publicField(this, "onPrepareLicenseServerUrl", (licenseServerUrl) => {
|
|
176
195
|
if (this.config?.fairplay?.prepareLicenseServerUrl) {
|
|
177
|
-
DrmModule.setPreparedLicenseServerUrl(
|
|
196
|
+
DrmModule.setPreparedLicenseServerUrl(
|
|
197
|
+
this.nativeId,
|
|
198
|
+
this.config?.fairplay?.prepareLicenseServerUrl?.(licenseServerUrl)
|
|
199
|
+
);
|
|
178
200
|
}
|
|
179
201
|
});
|
|
180
202
|
__publicField(this, "onPrepareContentId", (contentId) => {
|
|
181
203
|
if (this.config?.fairplay?.prepareContentId) {
|
|
182
|
-
DrmModule.setPreparedContentId(
|
|
204
|
+
DrmModule.setPreparedContentId(
|
|
205
|
+
this.nativeId,
|
|
206
|
+
this.config?.fairplay?.prepareContentId?.(contentId)
|
|
207
|
+
);
|
|
183
208
|
}
|
|
184
209
|
});
|
|
185
210
|
}
|
|
@@ -218,7 +243,11 @@ var Source = class extends NativeInstance {
|
|
|
218
243
|
if (this.config?.drmConfig) {
|
|
219
244
|
this.drm = new Drm(this.config.drmConfig);
|
|
220
245
|
this.drm.initialize();
|
|
221
|
-
SourceModule.initWithDrmConfig(
|
|
246
|
+
SourceModule.initWithDrmConfig(
|
|
247
|
+
this.nativeId,
|
|
248
|
+
this.drm.nativeId,
|
|
249
|
+
this.config
|
|
250
|
+
);
|
|
222
251
|
} else {
|
|
223
252
|
SourceModule.initWithConfig(this.nativeId, this.config);
|
|
224
253
|
}
|
|
@@ -326,14 +355,18 @@ var Player = class extends NativeInstance {
|
|
|
326
355
|
});
|
|
327
356
|
__publicField(this, "isAirPlayActive", async () => {
|
|
328
357
|
if (import_react_native7.Platform.OS === "android") {
|
|
329
|
-
console.warn(
|
|
358
|
+
console.warn(
|
|
359
|
+
`[Player ${this.nativeId}] Method isAirPlayActive is not available for Android. Only iOS devices.`
|
|
360
|
+
);
|
|
330
361
|
return false;
|
|
331
362
|
}
|
|
332
363
|
return PlayerModule.isAirPlayActive(this.nativeId);
|
|
333
364
|
});
|
|
334
365
|
__publicField(this, "isAirPlayAvailable", async () => {
|
|
335
366
|
if (import_react_native7.Platform.OS === "android") {
|
|
336
|
-
console.warn(
|
|
367
|
+
console.warn(
|
|
368
|
+
`[Player ${this.nativeId}] Method isAirPlayAvailable is not available for Android. Only iOS devices.`
|
|
369
|
+
);
|
|
337
370
|
return false;
|
|
338
371
|
}
|
|
339
372
|
return PlayerModule.isAirPlayAvailable(this.nativeId);
|
package/lib/index.mjs
CHANGED
|
@@ -26,12 +26,15 @@ function unwrapNativeEvent(event) {
|
|
|
26
26
|
return omit(event.nativeEvent, ["target"]);
|
|
27
27
|
}
|
|
28
28
|
function useProxy(viewRef) {
|
|
29
|
-
return useCallback(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
return useCallback(
|
|
30
|
+
(callback) => (event) => {
|
|
31
|
+
const node = event.target._nativeTag;
|
|
32
|
+
if (node === findNodeHandle(viewRef.current)) {
|
|
33
|
+
callback?.(unwrapNativeEvent(event));
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
[viewRef]
|
|
37
|
+
);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
// src/components/PlayerView/index.tsx
|
|
@@ -42,10 +45,14 @@ var styles = StyleSheet.create({
|
|
|
42
45
|
});
|
|
43
46
|
function dispatch(command, node, playerId) {
|
|
44
47
|
const commandId = Platform.OS === "android" ? UIManager.NativePlayerView.Commands[command].toString() : UIManager.getViewManagerConfig("NativePlayerView").Commands[command];
|
|
45
|
-
UIManager.dispatchViewManagerCommand(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
UIManager.dispatchViewManagerCommand(
|
|
49
|
+
node,
|
|
50
|
+
commandId,
|
|
51
|
+
Platform.select({
|
|
52
|
+
ios: [playerId],
|
|
53
|
+
android: [node, playerId]
|
|
54
|
+
})
|
|
55
|
+
);
|
|
49
56
|
}
|
|
50
57
|
function PlayerView(props) {
|
|
51
58
|
const nativeView = useRef(null);
|
|
@@ -123,18 +130,27 @@ var Drm = class extends NativeInstance {
|
|
|
123
130
|
});
|
|
124
131
|
__publicField(this, "onPrepareCertificate", (certificate) => {
|
|
125
132
|
if (this.config?.fairplay?.prepareCertificate) {
|
|
126
|
-
DrmModule.setPreparedCertificate(
|
|
133
|
+
DrmModule.setPreparedCertificate(
|
|
134
|
+
this.nativeId,
|
|
135
|
+
this.config?.fairplay?.prepareCertificate?.(certificate)
|
|
136
|
+
);
|
|
127
137
|
}
|
|
128
138
|
});
|
|
129
139
|
__publicField(this, "onPrepareMessage", (message, assetId) => {
|
|
130
140
|
const config = Platform2.OS === "ios" ? this.config?.fairplay : this.config?.widevine;
|
|
131
141
|
if (config && config.prepareMessage) {
|
|
132
|
-
DrmModule.setPreparedMessage(
|
|
142
|
+
DrmModule.setPreparedMessage(
|
|
143
|
+
this.nativeId,
|
|
144
|
+
Platform2.OS === "ios" ? config.prepareMessage?.(message, assetId) : config.prepareMessage?.(message)
|
|
145
|
+
);
|
|
133
146
|
}
|
|
134
147
|
});
|
|
135
148
|
__publicField(this, "onPrepareSyncMessage", (syncMessage, assetId) => {
|
|
136
149
|
if (this.config?.fairplay?.prepareSyncMessage) {
|
|
137
|
-
DrmModule.setPreparedSyncMessage(
|
|
150
|
+
DrmModule.setPreparedSyncMessage(
|
|
151
|
+
this.nativeId,
|
|
152
|
+
this.config?.fairplay?.prepareSyncMessage?.(syncMessage, assetId)
|
|
153
|
+
);
|
|
138
154
|
}
|
|
139
155
|
});
|
|
140
156
|
__publicField(this, "onPrepareLicense", (license) => {
|
|
@@ -145,12 +161,18 @@ var Drm = class extends NativeInstance {
|
|
|
145
161
|
});
|
|
146
162
|
__publicField(this, "onPrepareLicenseServerUrl", (licenseServerUrl) => {
|
|
147
163
|
if (this.config?.fairplay?.prepareLicenseServerUrl) {
|
|
148
|
-
DrmModule.setPreparedLicenseServerUrl(
|
|
164
|
+
DrmModule.setPreparedLicenseServerUrl(
|
|
165
|
+
this.nativeId,
|
|
166
|
+
this.config?.fairplay?.prepareLicenseServerUrl?.(licenseServerUrl)
|
|
167
|
+
);
|
|
149
168
|
}
|
|
150
169
|
});
|
|
151
170
|
__publicField(this, "onPrepareContentId", (contentId) => {
|
|
152
171
|
if (this.config?.fairplay?.prepareContentId) {
|
|
153
|
-
DrmModule.setPreparedContentId(
|
|
172
|
+
DrmModule.setPreparedContentId(
|
|
173
|
+
this.nativeId,
|
|
174
|
+
this.config?.fairplay?.prepareContentId?.(contentId)
|
|
175
|
+
);
|
|
154
176
|
}
|
|
155
177
|
});
|
|
156
178
|
}
|
|
@@ -189,7 +211,11 @@ var Source = class extends NativeInstance {
|
|
|
189
211
|
if (this.config?.drmConfig) {
|
|
190
212
|
this.drm = new Drm(this.config.drmConfig);
|
|
191
213
|
this.drm.initialize();
|
|
192
|
-
SourceModule.initWithDrmConfig(
|
|
214
|
+
SourceModule.initWithDrmConfig(
|
|
215
|
+
this.nativeId,
|
|
216
|
+
this.drm.nativeId,
|
|
217
|
+
this.config
|
|
218
|
+
);
|
|
193
219
|
} else {
|
|
194
220
|
SourceModule.initWithConfig(this.nativeId, this.config);
|
|
195
221
|
}
|
|
@@ -297,14 +323,18 @@ var Player = class extends NativeInstance {
|
|
|
297
323
|
});
|
|
298
324
|
__publicField(this, "isAirPlayActive", async () => {
|
|
299
325
|
if (Platform3.OS === "android") {
|
|
300
|
-
console.warn(
|
|
326
|
+
console.warn(
|
|
327
|
+
`[Player ${this.nativeId}] Method isAirPlayActive is not available for Android. Only iOS devices.`
|
|
328
|
+
);
|
|
301
329
|
return false;
|
|
302
330
|
}
|
|
303
331
|
return PlayerModule.isAirPlayActive(this.nativeId);
|
|
304
332
|
});
|
|
305
333
|
__publicField(this, "isAirPlayAvailable", async () => {
|
|
306
334
|
if (Platform3.OS === "android") {
|
|
307
|
-
console.warn(
|
|
335
|
+
console.warn(
|
|
336
|
+
`[Player ${this.nativeId}] Method isAirPlayAvailable is not available for Android. Only iOS devices.`
|
|
337
|
+
);
|
|
308
338
|
return false;
|
|
309
339
|
}
|
|
310
340
|
return PlayerModule.isAirPlayAvailable(this.nativeId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bitmovin-player-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Official React Native bindings for Bitmovin's mobile Player SDKs.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"example": "yarn --cwd example",
|
|
31
31
|
"pods": "cd example && pod-install --quiet",
|
|
32
32
|
"bootstrap": "yarn && yarn example && yarn pods",
|
|
33
|
-
"
|
|
33
|
+
"prepare": "husky install"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"react-native",
|
|
@@ -45,24 +45,28 @@
|
|
|
45
45
|
"homepage": "https://github.com/bitmovin/bitmovin-player-react-native",
|
|
46
46
|
"repository": "https://github.com/bitmovin/bitmovin-player-react-native",
|
|
47
47
|
"devDependencies": {
|
|
48
|
+
"@babel/core": "7.19.3",
|
|
49
|
+
"@babel/runtime": "7.19.0",
|
|
48
50
|
"@commitlint/config-conventional": "11.0.0",
|
|
49
|
-
"@react-native-community/eslint-config": "3.0
|
|
51
|
+
"@react-native-community/eslint-config": "3.1.0",
|
|
50
52
|
"@types/jest": "26.0.24",
|
|
51
53
|
"@types/lodash.omit": "4.5.0",
|
|
52
54
|
"@types/react": "18.0.15",
|
|
53
55
|
"@types/react-native": "0.69.2",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
+
"babel-plugin-module-resolver": "4.1.0",
|
|
57
|
+
"commitlint": "17.1.2",
|
|
58
|
+
"eslint": "8.24.0",
|
|
56
59
|
"eslint-config-prettier": "8.5.0",
|
|
57
|
-
"eslint-plugin-prettier": "4.
|
|
60
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
58
61
|
"husky": "8.0.1",
|
|
59
62
|
"jest": "26.6.3",
|
|
60
63
|
"lint-staged": "13.0.3",
|
|
61
|
-
"
|
|
64
|
+
"metro-config": "0.72.3",
|
|
65
|
+
"metro-react-native-babel-preset": "0.72.3",
|
|
66
|
+
"pod-install": "0.1.38",
|
|
62
67
|
"prettier": "2.7.1",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"typescript": "4.5.5"
|
|
68
|
+
"tsup": "6.2.3",
|
|
69
|
+
"typescript": "4.8.4"
|
|
66
70
|
},
|
|
67
71
|
"dependencies": {
|
|
68
72
|
"lodash.omit": "4.5.0"
|
package/src/player.ts
CHANGED
|
@@ -28,6 +28,87 @@ export interface PlayerConfig extends NativeInstanceConfig {
|
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
licenseKey?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Configures playback behaviour. A default PlaybackConfig is set initially.
|
|
33
|
+
*/
|
|
34
|
+
playbackConfig?: PlaybackConfig;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Configures the playback behaviour of the player.
|
|
39
|
+
*/
|
|
40
|
+
export interface PlaybackConfig {
|
|
41
|
+
/**
|
|
42
|
+
* Whether the player starts playing automatically after loading a source or not. Default is `false`.
|
|
43
|
+
* @example
|
|
44
|
+
* ```
|
|
45
|
+
* const player = new Player({
|
|
46
|
+
* playbackConfig: {
|
|
47
|
+
* isAutoplayEnabled: true,
|
|
48
|
+
* },
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
isAutoplayEnabled?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the sound is muted on startup or not. Default value is `false`.
|
|
55
|
+
* @example
|
|
56
|
+
* ```
|
|
57
|
+
* const player = new Player({
|
|
58
|
+
* playbackConfig: {
|
|
59
|
+
* isMuted: true,
|
|
60
|
+
* },
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
isMuted?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Whether time shift / DVR for live streams is enabled or not. Default is `true`.
|
|
67
|
+
* @example
|
|
68
|
+
* ```
|
|
69
|
+
* const player = new Player({
|
|
70
|
+
* playbackConfig: {
|
|
71
|
+
* isTimeShiftEnabled: false,
|
|
72
|
+
* },
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
isTimeShiftEnabled?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Whether background playback is enabled or not.
|
|
79
|
+
* Default is `false`.
|
|
80
|
+
*
|
|
81
|
+
* When set to `true`, playback is not automatically paused
|
|
82
|
+
* anymore when the app moves to the background.
|
|
83
|
+
* When set to `true`, also make sure to properly configure your app to allow
|
|
84
|
+
* background playback.
|
|
85
|
+
*
|
|
86
|
+
* On tvOS, background playback is only supported for audio-only content.
|
|
87
|
+
*
|
|
88
|
+
* Default is `false`.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```
|
|
92
|
+
* const player = new Player({
|
|
93
|
+
* {
|
|
94
|
+
* isBackgroundPlaybackEnabled: true,
|
|
95
|
+
* }
|
|
96
|
+
* })
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
isBackgroundPlaybackEnabled?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Whether the picture-in-picture mode option is enabled for iOS or not. Default is `false`.
|
|
102
|
+
* @example
|
|
103
|
+
* ```
|
|
104
|
+
* const player = new Player({
|
|
105
|
+
* playbackConfig: {
|
|
106
|
+
* isPictureInPictureEnabled: true,
|
|
107
|
+
* },
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
isPictureInPictureEnabled?: boolean;
|
|
31
112
|
}
|
|
32
113
|
|
|
33
114
|
/**
|