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/lib/index.mjs
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => {
|
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
return value;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/player.ts
|
|
9
|
+
import { NativeModules, Platform } from "react-native";
|
|
10
|
+
var PlayerModule = NativeModules.PlayerModule;
|
|
11
|
+
var Player = class {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
__publicField(this, "nativeId");
|
|
14
|
+
__publicField(this, "config");
|
|
15
|
+
__publicField(this, "load", (source) => {
|
|
16
|
+
PlayerModule.loadSource(this.nativeId, source);
|
|
17
|
+
});
|
|
18
|
+
__publicField(this, "unload", () => {
|
|
19
|
+
PlayerModule.unload(this.nativeId);
|
|
20
|
+
});
|
|
21
|
+
__publicField(this, "play", () => {
|
|
22
|
+
PlayerModule.play(this.nativeId);
|
|
23
|
+
});
|
|
24
|
+
__publicField(this, "pause", () => {
|
|
25
|
+
PlayerModule.pause(this.nativeId);
|
|
26
|
+
});
|
|
27
|
+
__publicField(this, "seek", (time) => {
|
|
28
|
+
PlayerModule.seek(this.nativeId, time);
|
|
29
|
+
});
|
|
30
|
+
__publicField(this, "mute", () => {
|
|
31
|
+
PlayerModule.mute(this.nativeId);
|
|
32
|
+
});
|
|
33
|
+
__publicField(this, "unmute", () => {
|
|
34
|
+
PlayerModule.unmute(this.nativeId);
|
|
35
|
+
});
|
|
36
|
+
__publicField(this, "destroy", () => {
|
|
37
|
+
PlayerModule.destroy(this.nativeId);
|
|
38
|
+
});
|
|
39
|
+
__publicField(this, "setVolume", (volume) => {
|
|
40
|
+
PlayerModule.setVolume(this.nativeId, volume);
|
|
41
|
+
});
|
|
42
|
+
__publicField(this, "getSource", async () => {
|
|
43
|
+
return PlayerModule.source(this.nativeId);
|
|
44
|
+
});
|
|
45
|
+
__publicField(this, "getVolume", async () => {
|
|
46
|
+
return PlayerModule.getVolume(this.nativeId);
|
|
47
|
+
});
|
|
48
|
+
__publicField(this, "getCurrentTime", async (mode) => {
|
|
49
|
+
return PlayerModule.currentTime(this.nativeId, mode);
|
|
50
|
+
});
|
|
51
|
+
__publicField(this, "getDuration", async () => {
|
|
52
|
+
return PlayerModule.duration(this.nativeId);
|
|
53
|
+
});
|
|
54
|
+
__publicField(this, "isMuted", async () => {
|
|
55
|
+
return PlayerModule.isMuted(this.nativeId);
|
|
56
|
+
});
|
|
57
|
+
__publicField(this, "isPlaying", async () => {
|
|
58
|
+
return PlayerModule.isPlaying(this.nativeId);
|
|
59
|
+
});
|
|
60
|
+
__publicField(this, "isPaused", async () => {
|
|
61
|
+
return PlayerModule.isPaused(this.nativeId);
|
|
62
|
+
});
|
|
63
|
+
__publicField(this, "isLive", async () => {
|
|
64
|
+
return PlayerModule.isLive(this.nativeId);
|
|
65
|
+
});
|
|
66
|
+
__publicField(this, "isAirPlayActive", async () => {
|
|
67
|
+
if (Platform.OS === "android") {
|
|
68
|
+
console.warn(`[Player ${this.nativeId}] Method isAirPlayActive is not available for Android. Only iOS devices.`);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return PlayerModule.isAirPlayActive(this.nativeId);
|
|
72
|
+
});
|
|
73
|
+
__publicField(this, "isAirPlayAvailable", async () => {
|
|
74
|
+
if (Platform.OS === "android") {
|
|
75
|
+
console.warn(`[Player ${this.nativeId}] Method isAirPlayAvailable is not available for Android. Only iOS devices.`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return PlayerModule.isAirPlayAvailable(this.nativeId);
|
|
79
|
+
});
|
|
80
|
+
this.config = config ?? null;
|
|
81
|
+
this.nativeId = config?.nativeId ?? PlayerModule.generateUUIDv4();
|
|
82
|
+
PlayerModule.initWithConfig(this.nativeId, this.config);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// src/source.ts
|
|
87
|
+
var SourceType = /* @__PURE__ */ ((SourceType2) => {
|
|
88
|
+
SourceType2["NONE"] = "none";
|
|
89
|
+
SourceType2["HLS"] = "hls";
|
|
90
|
+
SourceType2["DASH"] = "dash";
|
|
91
|
+
SourceType2["PROGRESSIVE"] = "progressive";
|
|
92
|
+
return SourceType2;
|
|
93
|
+
})(SourceType || {});
|
|
94
|
+
var LoadingState = /* @__PURE__ */ ((LoadingState2) => {
|
|
95
|
+
LoadingState2[LoadingState2["UNLOADED"] = 0] = "UNLOADED";
|
|
96
|
+
LoadingState2[LoadingState2["LOADING"] = 1] = "LOADING";
|
|
97
|
+
LoadingState2[LoadingState2["LOADED"] = 2] = "LOADED";
|
|
98
|
+
return LoadingState2;
|
|
99
|
+
})(LoadingState || {});
|
|
100
|
+
|
|
101
|
+
// src/hooks/usePlayer.ts
|
|
102
|
+
import { useRef } from "react";
|
|
103
|
+
function usePlayer(config) {
|
|
104
|
+
return useRef(new Player(config)).current;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/components/PlayerView/index.tsx
|
|
108
|
+
import React, { useRef as useRef3, useEffect } from "react";
|
|
109
|
+
import {
|
|
110
|
+
Platform as Platform2,
|
|
111
|
+
UIManager,
|
|
112
|
+
StyleSheet,
|
|
113
|
+
findNodeHandle as findNodeHandle2
|
|
114
|
+
} from "react-native";
|
|
115
|
+
|
|
116
|
+
// src/components/PlayerView/native.ts
|
|
117
|
+
import { requireNativeComponent } from "react-native";
|
|
118
|
+
var NativePlayerView = requireNativeComponent("NativePlayerView");
|
|
119
|
+
|
|
120
|
+
// src/hooks/useProxy.ts
|
|
121
|
+
import omit from "lodash.omit";
|
|
122
|
+
import { useCallback, useRef as useRef2 } from "react";
|
|
123
|
+
import { findNodeHandle } from "react-native";
|
|
124
|
+
function unwrapNativeEvent(event) {
|
|
125
|
+
return omit(event.nativeEvent, ["target"]);
|
|
126
|
+
}
|
|
127
|
+
function useProxy(viewRef, proxy) {
|
|
128
|
+
const proxyRef = useRef2(proxy);
|
|
129
|
+
return useCallback((event) => {
|
|
130
|
+
const node = event.target._nativeTag;
|
|
131
|
+
if (node === findNodeHandle(viewRef.current)) {
|
|
132
|
+
proxyRef.current?.(unwrapNativeEvent(event));
|
|
133
|
+
}
|
|
134
|
+
}, [viewRef]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/components/PlayerView/index.tsx
|
|
138
|
+
var styles = StyleSheet.create({
|
|
139
|
+
baseStyle: {
|
|
140
|
+
alignSelf: "stretch"
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
function dispatch(command, node, playerId) {
|
|
144
|
+
const commandId = Platform2.OS === "android" ? UIManager.NativePlayerView.Commands[command].toString() : UIManager.getViewManagerConfig("NativePlayerView").Commands[command];
|
|
145
|
+
UIManager.dispatchViewManagerCommand(node, commandId, Platform2.select({
|
|
146
|
+
ios: [playerId],
|
|
147
|
+
android: [node, playerId]
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
function PlayerView(props) {
|
|
151
|
+
const nativeView = useRef3(null);
|
|
152
|
+
const style = StyleSheet.flatten([styles.baseStyle, props.style]);
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
const node = findNodeHandle2(nativeView.current);
|
|
155
|
+
dispatch("attachPlayer", node, props.player.nativeId);
|
|
156
|
+
return () => {
|
|
157
|
+
dispatch("detachPlayer", node, props.player.nativeId);
|
|
158
|
+
};
|
|
159
|
+
}, [props.player.nativeId]);
|
|
160
|
+
return /* @__PURE__ */ React.createElement(NativePlayerView, {
|
|
161
|
+
ref: nativeView,
|
|
162
|
+
style,
|
|
163
|
+
onEvent: useProxy(nativeView, props.onEvent),
|
|
164
|
+
onPlayerActive: useProxy(nativeView, props.onPlayerActive),
|
|
165
|
+
onPlayerError: useProxy(nativeView, props.onPlayerError),
|
|
166
|
+
onPlayerWarning: useProxy(nativeView, props.onPlayerWarning),
|
|
167
|
+
onDestroy: useProxy(nativeView, props.onDestroy),
|
|
168
|
+
onMuted: useProxy(nativeView, props.onMuted),
|
|
169
|
+
onUnmuted: useProxy(nativeView, props.onUnmuted),
|
|
170
|
+
onReady: useProxy(nativeView, props.onReady),
|
|
171
|
+
onPaused: useProxy(nativeView, props.onPaused),
|
|
172
|
+
onPlay: useProxy(nativeView, props.onPlay),
|
|
173
|
+
onPlaying: useProxy(nativeView, props.onPlaying),
|
|
174
|
+
onPlaybackFinished: useProxy(nativeView, props.onPlaybackFinished),
|
|
175
|
+
onSeek: useProxy(nativeView, props.onSeek),
|
|
176
|
+
onSeeked: useProxy(nativeView, props.onSeeked),
|
|
177
|
+
onTimeChanged: useProxy(nativeView, props.onTimeChanged),
|
|
178
|
+
onSourceLoad: useProxy(nativeView, props.onSourceLoad),
|
|
179
|
+
onSourceLoaded: useProxy(nativeView, props.onSourceLoaded),
|
|
180
|
+
onSourceUnloaded: useProxy(nativeView, props.onSourceUnloaded),
|
|
181
|
+
onSourceError: useProxy(nativeView, props.onSourceError),
|
|
182
|
+
onSourceWarning: useProxy(nativeView, props.onSourceWarning)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
export {
|
|
186
|
+
LoadingState,
|
|
187
|
+
Player,
|
|
188
|
+
PlayerView,
|
|
189
|
+
SourceType,
|
|
190
|
+
usePlayer
|
|
191
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bitmovin-player-react-native",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official React Native bindings for Bitmovin's mobile Player SDKs.",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"module": "lib/index.mjs",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"source": "src/index.ts",
|
|
9
|
+
"react-native": "src/index.ts",
|
|
10
|
+
"author": "Bitmovin GmbH",
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"lib",
|
|
14
|
+
"android",
|
|
15
|
+
"ios",
|
|
16
|
+
"cpp",
|
|
17
|
+
"RNBitmovinPlayer.podspec",
|
|
18
|
+
"!android/build",
|
|
19
|
+
"!ios/build",
|
|
20
|
+
"!**/__tests__",
|
|
21
|
+
"!**/__fixtures__",
|
|
22
|
+
"!**/__mocks__"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"typescript": "tsc --noEmit",
|
|
27
|
+
"lint": "eslint \"**/*.{ts,tsx}\"",
|
|
28
|
+
"format": "prettier --write .",
|
|
29
|
+
"build": "tsup ./src/index.ts --dts --target es2020 --format cjs,esm -d lib",
|
|
30
|
+
"example": "yarn --cwd example",
|
|
31
|
+
"pods": "cd example && pod-install --quiet",
|
|
32
|
+
"bootstrap": "yarn && yarn example && yarn pods"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"react-native",
|
|
36
|
+
"ios",
|
|
37
|
+
"android",
|
|
38
|
+
"bitmovin",
|
|
39
|
+
"player",
|
|
40
|
+
"video",
|
|
41
|
+
"streaming"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"homepage": "https://github.com/bitmovin/bitmovin-player-react-native",
|
|
45
|
+
"repository": "https://github.com/bitmovin/bitmovin-player-react-native",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@commitlint/config-conventional": "11.0.0",
|
|
48
|
+
"@react-native-community/eslint-config": "3.0.2",
|
|
49
|
+
"@types/jest": "26.0.24",
|
|
50
|
+
"@types/lodash.omit": "4.5.0",
|
|
51
|
+
"@types/react": "17.0.39",
|
|
52
|
+
"@types/react-native": "0.67.7",
|
|
53
|
+
"commitlint": "11.0.0",
|
|
54
|
+
"eslint": "8.18.0",
|
|
55
|
+
"eslint-config-prettier": "8.5.0",
|
|
56
|
+
"eslint-plugin-prettier": "4.0.0",
|
|
57
|
+
"husky": "8.0.1",
|
|
58
|
+
"jest": "26.6.3",
|
|
59
|
+
"lint-staged": "13.0.3",
|
|
60
|
+
"pod-install": "0.1.37",
|
|
61
|
+
"prettier": "2.7.1",
|
|
62
|
+
"react": "17.0.2",
|
|
63
|
+
"tsup": "5.12.9",
|
|
64
|
+
"typescript": "4.5.5"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"lodash.omit": "4.5.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": ">=17",
|
|
71
|
+
"react-native": ">=0.64"
|
|
72
|
+
},
|
|
73
|
+
"commitlint": {
|
|
74
|
+
"extends": [
|
|
75
|
+
"@commitlint/config-conventional"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"lint-staged": {
|
|
79
|
+
"*.(ts|tsx)": "eslint",
|
|
80
|
+
"*.(ts|tsx|js|jsx|md|json|yml|yaml)": "prettier --write"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { NativeSyntheticEvent } from 'react-native';
|
|
2
|
+
import {
|
|
3
|
+
Event,
|
|
4
|
+
PlayerActiveEvent,
|
|
5
|
+
PlayerErrorEvent,
|
|
6
|
+
PlayerWarningEvent,
|
|
7
|
+
DestroyEvent,
|
|
8
|
+
MutedEvent,
|
|
9
|
+
UnmutedEvent,
|
|
10
|
+
ReadyEvent,
|
|
11
|
+
PausedEvent,
|
|
12
|
+
PlayEvent,
|
|
13
|
+
PlayingEvent,
|
|
14
|
+
PlaybackFinishedEvent,
|
|
15
|
+
SeekEvent,
|
|
16
|
+
SeekedEvent,
|
|
17
|
+
TimeChangedEvent,
|
|
18
|
+
SourceLoadEvent,
|
|
19
|
+
SourceLoadedEvent,
|
|
20
|
+
SourceUnloadedEvent,
|
|
21
|
+
SourceErrorEvent,
|
|
22
|
+
SourceWarningEvent,
|
|
23
|
+
} from '../../events';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Type that defines all event props supported by `PlayerView` and `NativePlayerView`.
|
|
27
|
+
* Used to generate the specific events interface for each component.
|
|
28
|
+
*/
|
|
29
|
+
interface EventProps {
|
|
30
|
+
onEvent: Event;
|
|
31
|
+
onPlayerActive: PlayerActiveEvent;
|
|
32
|
+
onPlayerError: PlayerErrorEvent;
|
|
33
|
+
onPlayerWarning: PlayerWarningEvent;
|
|
34
|
+
onDestroy: DestroyEvent;
|
|
35
|
+
onMuted: MutedEvent;
|
|
36
|
+
onUnmuted: UnmutedEvent;
|
|
37
|
+
onReady: ReadyEvent;
|
|
38
|
+
onPaused: PausedEvent;
|
|
39
|
+
onPlay: PlayEvent;
|
|
40
|
+
onPlaying: PlayingEvent;
|
|
41
|
+
onPlaybackFinished: PlaybackFinishedEvent;
|
|
42
|
+
onSeek: SeekEvent;
|
|
43
|
+
onSeeked: SeekedEvent;
|
|
44
|
+
onTimeChanged: TimeChangedEvent;
|
|
45
|
+
onSourceLoad: SourceLoadEvent;
|
|
46
|
+
onSourceLoaded: SourceLoadedEvent;
|
|
47
|
+
onSourceUnloaded: SourceUnloadedEvent;
|
|
48
|
+
onSourceError: SourceErrorEvent;
|
|
49
|
+
onSourceWarning: SourceWarningEvent;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Event props for `PlayerView`.
|
|
54
|
+
*
|
|
55
|
+
* Note the events of `PlayerView` are simply a proxy over
|
|
56
|
+
* the events from `NativePlayerView` just removing RN's bubbling data.
|
|
57
|
+
*/
|
|
58
|
+
export type PlayerViewEvents = {
|
|
59
|
+
[Prop in keyof EventProps]?: (event: EventProps[Prop]) => void;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Event props for `NativePlayerView`.
|
|
64
|
+
*/
|
|
65
|
+
export type NativePlayerViewEvents = {
|
|
66
|
+
[Prop in keyof EventProps]?: (
|
|
67
|
+
nativeEvent: NativeSyntheticEvent<EventProps[Prop]>
|
|
68
|
+
) => void;
|
|
69
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React, { useRef, useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
UIManager,
|
|
5
|
+
ViewStyle,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
findNodeHandle,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { PlayerViewEvents } from './events';
|
|
10
|
+
import { NativePlayerView } from './native';
|
|
11
|
+
import { Player } from '../../player';
|
|
12
|
+
import { useProxy } from '../../hooks/useProxy';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base `PlayerView` component props. Used to stablish common
|
|
16
|
+
* props between `NativePlayerView` and `PlayerView`.
|
|
17
|
+
* @see NativePlayerView
|
|
18
|
+
*/
|
|
19
|
+
export interface BasePlayerViewProps {
|
|
20
|
+
style?: ViewStyle;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `PlayerView` component props.
|
|
25
|
+
* @see PlayerView
|
|
26
|
+
*/
|
|
27
|
+
export interface PlayerViewProps extends BasePlayerViewProps, PlayerViewEvents {
|
|
28
|
+
/**
|
|
29
|
+
* `Player` instance (generally returned from `usePlayer` hook) that will control
|
|
30
|
+
* and render audio/video inside the `PlayerView`.
|
|
31
|
+
*/
|
|
32
|
+
player: Player;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Base style that initializes the native view frame when no width/height prop has been set.
|
|
37
|
+
*/
|
|
38
|
+
const styles = StyleSheet.create({
|
|
39
|
+
baseStyle: {
|
|
40
|
+
alignSelf: 'stretch',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Dispatches any given `NativePlayerView` commands on React's `UIManager`.
|
|
46
|
+
*/
|
|
47
|
+
function dispatch(command: string, node: number | null, playerId: string) {
|
|
48
|
+
const commandId =
|
|
49
|
+
Platform.OS === 'android'
|
|
50
|
+
? (UIManager as any).NativePlayerView.Commands[command].toString()
|
|
51
|
+
: UIManager.getViewManagerConfig('NativePlayerView').Commands[command];
|
|
52
|
+
UIManager.dispatchViewManagerCommand(
|
|
53
|
+
node,
|
|
54
|
+
commandId,
|
|
55
|
+
Platform.select({
|
|
56
|
+
ios: [playerId],
|
|
57
|
+
android: [node, playerId],
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Component that provides the Bitmovin Player UI and default UI handling to an attached `Player` instance.
|
|
64
|
+
* This component needs a `Player` instance to work properly so make sure one is passed to it as a prop.
|
|
65
|
+
*/
|
|
66
|
+
export function PlayerView(props: PlayerViewProps) {
|
|
67
|
+
// Native view reference.
|
|
68
|
+
const nativeView = useRef(null);
|
|
69
|
+
// Style resulting from merging `baseStyle` and `props.style`.
|
|
70
|
+
const style = StyleSheet.flatten([styles.baseStyle, props.style]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
// Attach `props.player` to native `PlayerView`.
|
|
73
|
+
const node = findNodeHandle(nativeView.current);
|
|
74
|
+
dispatch('attachPlayer', node, props.player.nativeId);
|
|
75
|
+
return () => {
|
|
76
|
+
// Detach `props.player` from native `PlayerView`.
|
|
77
|
+
dispatch('detachPlayer', node, props.player.nativeId);
|
|
78
|
+
};
|
|
79
|
+
}, [props.player.nativeId]);
|
|
80
|
+
return (
|
|
81
|
+
<NativePlayerView
|
|
82
|
+
ref={nativeView}
|
|
83
|
+
style={style}
|
|
84
|
+
onEvent={useProxy(nativeView, props.onEvent)}
|
|
85
|
+
onPlayerActive={useProxy(nativeView, props.onPlayerActive)}
|
|
86
|
+
onPlayerError={useProxy(nativeView, props.onPlayerError)}
|
|
87
|
+
onPlayerWarning={useProxy(nativeView, props.onPlayerWarning)}
|
|
88
|
+
onDestroy={useProxy(nativeView, props.onDestroy)}
|
|
89
|
+
onMuted={useProxy(nativeView, props.onMuted)}
|
|
90
|
+
onUnmuted={useProxy(nativeView, props.onUnmuted)}
|
|
91
|
+
onReady={useProxy(nativeView, props.onReady)}
|
|
92
|
+
onPaused={useProxy(nativeView, props.onPaused)}
|
|
93
|
+
onPlay={useProxy(nativeView, props.onPlay)}
|
|
94
|
+
onPlaying={useProxy(nativeView, props.onPlaying)}
|
|
95
|
+
onPlaybackFinished={useProxy(nativeView, props.onPlaybackFinished)}
|
|
96
|
+
onSeek={useProxy(nativeView, props.onSeek)}
|
|
97
|
+
onSeeked={useProxy(nativeView, props.onSeeked)}
|
|
98
|
+
onTimeChanged={useProxy(nativeView, props.onTimeChanged)}
|
|
99
|
+
onSourceLoad={useProxy(nativeView, props.onSourceLoad)}
|
|
100
|
+
onSourceLoaded={useProxy(nativeView, props.onSourceLoaded)}
|
|
101
|
+
onSourceUnloaded={useProxy(nativeView, props.onSourceUnloaded)}
|
|
102
|
+
onSourceError={useProxy(nativeView, props.onSourceError)}
|
|
103
|
+
onSourceWarning={useProxy(nativeView, props.onSourceWarning)}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { requireNativeComponent } from 'react-native';
|
|
2
|
+
import { NativePlayerViewEvents } from './events';
|
|
3
|
+
import { BasePlayerViewProps } from './index';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Props type for `NativePlayerView` native component.
|
|
7
|
+
* Mostly maps the event props defined in native code.
|
|
8
|
+
*/
|
|
9
|
+
export interface NativePlayerViewProps
|
|
10
|
+
extends BasePlayerViewProps,
|
|
11
|
+
NativePlayerViewEvents {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Native host component bridging Bitmovin's `PlayerView`.
|
|
15
|
+
*/
|
|
16
|
+
export const NativePlayerView =
|
|
17
|
+
requireNativeComponent<NativePlayerViewProps>('NativePlayerView');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PlayerView';
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Source } from './source';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base event type for all events.
|
|
5
|
+
*/
|
|
6
|
+
export interface Event {
|
|
7
|
+
/**
|
|
8
|
+
* This event name as it is on the native side.
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
/**
|
|
12
|
+
* The UNIX timestamp in which this event happened.
|
|
13
|
+
*/
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Base event type for error and warning events.
|
|
19
|
+
*/
|
|
20
|
+
export interface ErrorEvent extends Event {
|
|
21
|
+
/**
|
|
22
|
+
* Error/Warning's code number.
|
|
23
|
+
*/
|
|
24
|
+
code?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Error/Warning's localized message.
|
|
27
|
+
*/
|
|
28
|
+
message: string;
|
|
29
|
+
/**
|
|
30
|
+
* Underlying data emitted with the Error/Warning.
|
|
31
|
+
*/
|
|
32
|
+
data?: Record<string, any>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Emitted when a source is loaded into the player.
|
|
37
|
+
* Seeking and time shifting are allowed as soon as this event is seen.
|
|
38
|
+
*/
|
|
39
|
+
export interface PlayerActiveEvent extends Event {}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Emitted when a player error happens.
|
|
43
|
+
*/
|
|
44
|
+
export interface PlayerErrorEvent extends ErrorEvent {}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Emitted when a player warning happens.
|
|
48
|
+
*/
|
|
49
|
+
export interface PlayerWarningEvent extends ErrorEvent {}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Emitted when the player is destroyed.
|
|
53
|
+
*/
|
|
54
|
+
export interface DestroyEvent extends Event {}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Emitted when the player is muted.
|
|
58
|
+
*/
|
|
59
|
+
export interface MutedEvent extends Event {}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Emitted when the player is unmuted.
|
|
63
|
+
*/
|
|
64
|
+
export interface UnmutedEvent extends Event {}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Emitted when the player is ready for immediate playback, because initial audio/video
|
|
68
|
+
* has been downloaded.
|
|
69
|
+
*/
|
|
70
|
+
export interface ReadyEvent extends Event {}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Emitted when the player is paused.
|
|
74
|
+
*/
|
|
75
|
+
export interface PausedEvent extends Event {
|
|
76
|
+
/**
|
|
77
|
+
* The player's playback time from when this event happened.
|
|
78
|
+
*/
|
|
79
|
+
time: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Emitted when the player received an intention to start/resume playback.
|
|
84
|
+
*/
|
|
85
|
+
export interface PlayEvent extends Event {
|
|
86
|
+
/**
|
|
87
|
+
* The player's playback time from when this event happened.
|
|
88
|
+
*/
|
|
89
|
+
time: number;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Emitted when playback has started.
|
|
94
|
+
*/
|
|
95
|
+
export interface PlayingEvent extends Event {
|
|
96
|
+
/**
|
|
97
|
+
* The player's playback time from when this event happened.
|
|
98
|
+
*/
|
|
99
|
+
time: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Emitted when the playback of the current media has finished.
|
|
104
|
+
*/
|
|
105
|
+
export interface PlaybackFinishedEvent extends Event {}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Emitted when the player is about to seek to a new position.
|
|
109
|
+
* Only applies to VoD streams.
|
|
110
|
+
*/
|
|
111
|
+
export interface SeekEvent extends Event {
|
|
112
|
+
/**
|
|
113
|
+
* Removed source metadata.
|
|
114
|
+
*/
|
|
115
|
+
from: {
|
|
116
|
+
time: number;
|
|
117
|
+
source: Source;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Added source metadata.
|
|
121
|
+
*/
|
|
122
|
+
to: {
|
|
123
|
+
time: number;
|
|
124
|
+
source: Source;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Emitted when seeking has finished and data to continue playback is available.
|
|
130
|
+
* Only applies to VoD streams.
|
|
131
|
+
*/
|
|
132
|
+
export interface SeekedEvent extends Event {}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Emitted when the current playback time has changed.
|
|
136
|
+
*/
|
|
137
|
+
export interface TimeChangedEvent extends Event {
|
|
138
|
+
/**
|
|
139
|
+
* The player's playback time from when this event happened.
|
|
140
|
+
*/
|
|
141
|
+
currentTime: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Emitted when a new source loading has started.
|
|
146
|
+
* It doesn't mean that the loading of the new manifest has finished.
|
|
147
|
+
*/
|
|
148
|
+
export interface SourceLoadEvent extends Event {
|
|
149
|
+
/**
|
|
150
|
+
* Source that is about to load.
|
|
151
|
+
*/
|
|
152
|
+
source: Source;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Emitted when a new source is loaded.
|
|
157
|
+
* It doesn't mean that the loading of the new manifest has finished.
|
|
158
|
+
*/
|
|
159
|
+
export interface SourceLoadedEvent extends Event {
|
|
160
|
+
/**
|
|
161
|
+
* Source that was loaded into player.
|
|
162
|
+
*/
|
|
163
|
+
source: Source;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Emitted when the current source has been unloaded.
|
|
168
|
+
*/
|
|
169
|
+
export interface SourceUnloadedEvent extends Event {
|
|
170
|
+
/**
|
|
171
|
+
* Source that was unloaded from player.
|
|
172
|
+
*/
|
|
173
|
+
source: Source;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Emitted when a source error happens.
|
|
178
|
+
*/
|
|
179
|
+
export interface SourceErrorEvent extends ErrorEvent {}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Emitted when a source warning happens.
|
|
183
|
+
*/
|
|
184
|
+
export interface SourceWarningEvent extends ErrorEvent {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './usePlayer';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { Player, PlayerConfig } from '../player';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* React hook that creates and returns a reference to a `Player` instance
|
|
6
|
+
* that can be used inside any component.
|
|
7
|
+
*/
|
|
8
|
+
export function usePlayer(config?: PlayerConfig): Player {
|
|
9
|
+
return useRef(new Player(config)).current;
|
|
10
|
+
}
|