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
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import BitmovinPlayer
|
|
2
|
+
|
|
3
|
+
extension Source {
|
|
4
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
5
|
+
var json: [AnyHashable: Any] = [
|
|
6
|
+
"duration": duration,
|
|
7
|
+
"isActive": isActive,
|
|
8
|
+
"loadingState": loadingState,
|
|
9
|
+
"isAttachedToPlayer": isAttachedToPlayer
|
|
10
|
+
]
|
|
11
|
+
if let metadata = metadata {
|
|
12
|
+
json["metadata"] = metadata
|
|
13
|
+
}
|
|
14
|
+
return json
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extension SeekEvent {
|
|
19
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
20
|
+
[
|
|
21
|
+
"name": name,
|
|
22
|
+
"timestamp": timestamp,
|
|
23
|
+
"from": [
|
|
24
|
+
"time": from.time,
|
|
25
|
+
"source": from.source.toJSON()
|
|
26
|
+
],
|
|
27
|
+
"to": [
|
|
28
|
+
"time": to.time,
|
|
29
|
+
"source": to.source.toJSON()
|
|
30
|
+
]
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
extension TimeChangedEvent {
|
|
36
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
37
|
+
["name": name, "timestamp": timestamp, "currentTime": currentTime]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
extension Event {
|
|
42
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
43
|
+
["name": name, "timestamp": timestamp]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
extension NSError {
|
|
48
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
49
|
+
[
|
|
50
|
+
"code": code,
|
|
51
|
+
"domain": domain,
|
|
52
|
+
"description": description,
|
|
53
|
+
"localizedDescription": localizedDescription
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
extension DeficiencyData {
|
|
59
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
60
|
+
var json: [AnyHashable: Any] = ["code": code, "message": message]
|
|
61
|
+
if let underlyingError = underlyingError {
|
|
62
|
+
json["underlyingError"] = underlyingError.toJSON()
|
|
63
|
+
}
|
|
64
|
+
return json
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protocol ErrorEventType: Event {
|
|
69
|
+
associatedtype Code
|
|
70
|
+
var code: Code { get }
|
|
71
|
+
var data: DeficiencyData? { get }
|
|
72
|
+
var message: String { get }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
extension ErrorEventType {
|
|
76
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
77
|
+
var json: [AnyHashable: Any] = [
|
|
78
|
+
"name": name,
|
|
79
|
+
"timestamp": timestamp,
|
|
80
|
+
"code": code,
|
|
81
|
+
"message": message
|
|
82
|
+
]
|
|
83
|
+
if let data = data {
|
|
84
|
+
json["data"] = data.toJSON()
|
|
85
|
+
}
|
|
86
|
+
return json
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
extension PlayerErrorEvent: ErrorEventType {
|
|
91
|
+
typealias Code = PlayerError.Code
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
extension PlayerWarningEvent: ErrorEventType {
|
|
95
|
+
typealias Code = PlayerWarning.Code
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
extension SourceErrorEvent: ErrorEventType {
|
|
99
|
+
typealias Code = SourceError.Code
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
extension SourceWarningEvent: ErrorEventType {
|
|
103
|
+
typealias Code = SourceWarning.Code
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protocol SourceEventType: Event {
|
|
107
|
+
var source: Source { get }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
extension SourceEventType {
|
|
111
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
112
|
+
["name": name, "timestamp": timestamp, "source": source.toJSON()]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
extension SourceLoadEvent: SourceEventType {}
|
|
117
|
+
extension SourceLoadedEvent: SourceEventType {}
|
|
118
|
+
extension SourceUnloadedEvent: SourceEventType {}
|
|
119
|
+
|
|
120
|
+
protocol TimedEventType: Event {
|
|
121
|
+
var time: TimeInterval { get }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
extension TimedEventType {
|
|
125
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
126
|
+
["name": name, "timestamp": timestamp, "time": time]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
extension PlayEvent: TimedEventType {}
|
|
131
|
+
extension PausedEvent: TimedEventType {}
|
|
132
|
+
extension PlayingEvent: TimedEventType {}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_REMAP_MODULE(PlayerModule, PlayerModule, NSObject)
|
|
4
|
+
|
|
5
|
+
// UUID generation is sync and runs on the JS thread so it should be as
|
|
6
|
+
// fast as possible to avoid perf issues.
|
|
7
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(generateUUIDv4)
|
|
8
|
+
|
|
9
|
+
RCT_EXTERN_METHOD(initWithConfig:(NSString *)playerId config:(nullable id)config)
|
|
10
|
+
RCT_EXTERN_METHOD(loadSource:(NSString *)playerId config:(id)config)
|
|
11
|
+
RCT_EXTERN_METHOD(unload:(NSString *)playerId)
|
|
12
|
+
RCT_EXTERN_METHOD(play:(NSString *)playerId)
|
|
13
|
+
RCT_EXTERN_METHOD(pause:(NSString *)playerId)
|
|
14
|
+
RCT_EXTERN_METHOD(seek:(NSString *)playerId time:(nonnull NSNumber *)time)
|
|
15
|
+
RCT_EXTERN_METHOD(mute:(NSString *)playerId)
|
|
16
|
+
RCT_EXTERN_METHOD(unmute:(NSString *)playerId)
|
|
17
|
+
RCT_EXTERN_METHOD(destroy:(NSString *)playerId)
|
|
18
|
+
RCT_EXTERN_METHOD(setVolume:(NSString *)playerId volume:(nonnull NSNumber *)volume)
|
|
19
|
+
RCT_EXTERN_METHOD(
|
|
20
|
+
source:(NSString *)playerId
|
|
21
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
22
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
RCT_EXTERN_METHOD(
|
|
24
|
+
getVolume:(NSString *)playerId
|
|
25
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
26
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
27
|
+
RCT_EXTERN_METHOD(
|
|
28
|
+
currentTime:(NSString *)playerId
|
|
29
|
+
mode:(NSString *)mode
|
|
30
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
31
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
32
|
+
RCT_EXTERN_METHOD(
|
|
33
|
+
duration:(NSString *)playerId
|
|
34
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
36
|
+
RCT_EXTERN_METHOD(
|
|
37
|
+
isMuted:(NSString *)playerId
|
|
38
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
39
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
40
|
+
RCT_EXTERN_METHOD(
|
|
41
|
+
isPlaying:(NSString *)playerId
|
|
42
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
43
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
44
|
+
RCT_EXTERN_METHOD(
|
|
45
|
+
isPaused:(NSString *)playerId
|
|
46
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
47
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
48
|
+
RCT_EXTERN_METHOD(
|
|
49
|
+
isLive:(NSString *)playerId
|
|
50
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
51
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
52
|
+
RCT_EXTERN_METHOD(
|
|
53
|
+
isAirPlayActive:(NSString *)playerId
|
|
54
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
55
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
56
|
+
RCT_EXTERN_METHOD(
|
|
57
|
+
isAirPlayAvailable:(NSString *)playerId
|
|
58
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
59
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
60
|
+
|
|
61
|
+
@end
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import BitmovinPlayer
|
|
2
|
+
|
|
3
|
+
@objc(PlayerModule)
|
|
4
|
+
class PlayerModule: NSObject, RCTBridgeModule {
|
|
5
|
+
/// Accessible react bridge reference.
|
|
6
|
+
@objc var bridge: RCTBridge!
|
|
7
|
+
|
|
8
|
+
/// In-memory dictionary mapping id <-> `Player`.
|
|
9
|
+
private var registry: [String: Player] = [:]
|
|
10
|
+
|
|
11
|
+
/// Exported module name to JS.
|
|
12
|
+
static func moduleName() -> String! {
|
|
13
|
+
"PlayerModule"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Requires module initialization from main thread.
|
|
17
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
18
|
+
true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Dispatch methods on `UIManager` queue so all of them stay in sync with `RNPlayerViewManager`.
|
|
22
|
+
var methodQueue: DispatchQueue! {
|
|
23
|
+
bridge.uiManager.methodQueue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
Resolve the current `Player` instance associated with `id`. Intented to
|
|
28
|
+
be used by other RN bridge modules such as `RNPlayerViewManager`.
|
|
29
|
+
- Parameter id: Target player id.
|
|
30
|
+
- Returns: The player instance found if there's any.
|
|
31
|
+
*/
|
|
32
|
+
@objc func player(with id: String) -> Player? {
|
|
33
|
+
registry[id]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
Synchronously generate a random UUID for `Player`s native id when no `nativeId` is provided
|
|
38
|
+
by the user.
|
|
39
|
+
- Returns: Random UUID RFC 4122 version 4.
|
|
40
|
+
*/
|
|
41
|
+
@objc func generateUUIDv4() -> String {
|
|
42
|
+
UUID().uuidString
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
Create a new `Player` instance for the given `config` if no one exists already.
|
|
47
|
+
- Parameter config: Player configuration options sent from JS.
|
|
48
|
+
*/
|
|
49
|
+
@objc(initWithConfig:config:)
|
|
50
|
+
func initWithConfig(_ playerId: String, config: Any?) {
|
|
51
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
52
|
+
guard
|
|
53
|
+
self?.registry[playerId] == nil,
|
|
54
|
+
let playerConfig = RCTConvert.playerConfig(config)
|
|
55
|
+
else {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
self?.registry[playerId] = PlayerFactory.create(playerConfig: playerConfig)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
Load the source of the given `playerId` with `config` options from JS.
|
|
64
|
+
- Parameter playerId: Target player.
|
|
65
|
+
- Parameter config: Source configuration options from JS.
|
|
66
|
+
*/
|
|
67
|
+
@objc(loadSource:config:)
|
|
68
|
+
func loadSource(_ playerId: String, config: Any) {
|
|
69
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
70
|
+
guard
|
|
71
|
+
let player = self?.registry[playerId],
|
|
72
|
+
let sourceConfig = RCTConvert.sourceConfig(config)
|
|
73
|
+
else {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
player.load(sourceConfig: sourceConfig)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
Call `.unload()` on `playerId`'s player.
|
|
82
|
+
- Parameter playerId: Target player Id.
|
|
83
|
+
*/
|
|
84
|
+
@objc(unload:)
|
|
85
|
+
func unload(_ playerId: String) {
|
|
86
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
87
|
+
self?.registry[playerId]?.unload()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
Call `.play()` on `playerId`'s player.
|
|
93
|
+
- Parameter playerId: Target player Id.
|
|
94
|
+
*/
|
|
95
|
+
@objc(play:)
|
|
96
|
+
func play(_ playerId: String) {
|
|
97
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
98
|
+
self?.registry[playerId]?.play()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
Call `.pause()` on `playerId`'s player.
|
|
104
|
+
- Parameter playerId: Target player Id.
|
|
105
|
+
*/
|
|
106
|
+
@objc(pause:)
|
|
107
|
+
func pause(_ playerId: String) {
|
|
108
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
109
|
+
self?.registry[playerId]?.pause()
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
Call `.seek(time:)` on `playerId`'s player.
|
|
115
|
+
- Parameter playerId: Target player Id.
|
|
116
|
+
- Parameter time: Time to seek in seconds.
|
|
117
|
+
*/
|
|
118
|
+
@objc(seek:time:)
|
|
119
|
+
func seek(_ playerId: String, time: NSNumber) {
|
|
120
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
121
|
+
self?.registry[playerId]?.seek(time: time.doubleValue)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
Call `.mute()` on `playerId`'s player.
|
|
127
|
+
- Parameter playerId: Target player Id.
|
|
128
|
+
*/
|
|
129
|
+
@objc(mute:)
|
|
130
|
+
func mute(_ playerId: String) {
|
|
131
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
132
|
+
self?.registry[playerId]?.mute()
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
Call `.unmute()` on `playerId`'s player.
|
|
138
|
+
- Parameter playerId: Target player Id.
|
|
139
|
+
*/
|
|
140
|
+
@objc(unmute:)
|
|
141
|
+
func unmute(_ playerId: String) {
|
|
142
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
143
|
+
self?.registry[playerId]?.unmute()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
Call `.destroy()` on `playerId`'s player.
|
|
149
|
+
- Parameter playerId: Target player Id.
|
|
150
|
+
*/
|
|
151
|
+
@objc(destroy:)
|
|
152
|
+
func destroy(_ playerId: String) {
|
|
153
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
154
|
+
self?.registry[playerId]?.destroy()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
Call `.setVolume(volume:)` on `playerId`'s player.
|
|
160
|
+
- Parameter playerId: Target player Id.
|
|
161
|
+
- Parameter volume: Integer representing the volume level (between 0 to 100).
|
|
162
|
+
*/
|
|
163
|
+
@objc(setVolume:volume:)
|
|
164
|
+
func setVolume(_ playerId: String, volume: NSNumber) {
|
|
165
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
166
|
+
self?.registry[playerId]?.volume = volume.intValue
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
Resolve the source of `playerId`'s player.
|
|
172
|
+
- Parameter playerId: Target player Id.
|
|
173
|
+
- Parameter resolver: JS promise resolver.
|
|
174
|
+
- Parameter rejecter: JS promise rejecter.
|
|
175
|
+
*/
|
|
176
|
+
@objc(source:resolver:rejecter:)
|
|
177
|
+
func source(
|
|
178
|
+
_ playerId: String,
|
|
179
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
180
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
181
|
+
) {
|
|
182
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
183
|
+
resolve(self?.registry[playerId]?.source?.toJSON())
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
Resolve `playerId`'s current volume.
|
|
189
|
+
- Parameter playerId: Target player Id.
|
|
190
|
+
- Parameter resolver: JS promise resolver.
|
|
191
|
+
- Parameter rejecter: JS promise rejecter.
|
|
192
|
+
*/
|
|
193
|
+
@objc(getVolume:resolver:rejecter:)
|
|
194
|
+
func getVolume(
|
|
195
|
+
_ playerId: String,
|
|
196
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
197
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
198
|
+
) {
|
|
199
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
200
|
+
resolve(self?.registry[playerId]?.volume)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
Resolve `playerId`'s current playback time.
|
|
206
|
+
- Parameter playerId: Target player Id.
|
|
207
|
+
- Parameter mode: Time mode: either relative or absolute. Can be empty.
|
|
208
|
+
- Parameter resolver: JS promise resolver.
|
|
209
|
+
- Parameter rejecter: JS promise rejecter.
|
|
210
|
+
*/
|
|
211
|
+
@objc(currentTime:mode:resolver:rejecter:)
|
|
212
|
+
func currentTime(
|
|
213
|
+
_ playerId: String,
|
|
214
|
+
mode: String?,
|
|
215
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
216
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
217
|
+
) {
|
|
218
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
219
|
+
let player = self?.registry[playerId]
|
|
220
|
+
if let mode = mode {
|
|
221
|
+
resolve(player?.currentTime(RCTConvert.timeMode(mode)))
|
|
222
|
+
} else {
|
|
223
|
+
resolve(player?.currentTime)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
Resolve `playerId`'s active source duration.
|
|
230
|
+
- Parameter playerId: Target player Id.
|
|
231
|
+
- Parameter resolver: JS promise resolver.
|
|
232
|
+
- Parameter rejecter: JS promise rejecter.
|
|
233
|
+
*/
|
|
234
|
+
@objc(duration:resolver:rejecter:)
|
|
235
|
+
func duration(
|
|
236
|
+
_ playerId: String,
|
|
237
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
238
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
239
|
+
) {
|
|
240
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
241
|
+
resolve(self?.registry[playerId]?.duration)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
Resolve `playerId`'s current muted state.
|
|
247
|
+
- Parameter playerId: Target player Id.
|
|
248
|
+
- Parameter resolver: JS promise resolver.
|
|
249
|
+
- Parameter rejecter: JS promise rejecter.
|
|
250
|
+
*/
|
|
251
|
+
@objc(isMuted:resolver:rejecter:)
|
|
252
|
+
func isMuted(
|
|
253
|
+
_ playerId: String,
|
|
254
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
255
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
256
|
+
) {
|
|
257
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
258
|
+
resolve(self?.registry[playerId]?.isMuted)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
Resolve `playerId`'s current playing state.
|
|
264
|
+
- Parameter playerId: Target player Id.
|
|
265
|
+
- Parameter resolver: JS promise resolver.
|
|
266
|
+
- Parameter rejecter: JS promise rejecter.
|
|
267
|
+
*/
|
|
268
|
+
@objc(isPlaying:resolver:rejecter:)
|
|
269
|
+
func isPlaying(
|
|
270
|
+
_ playerId: String,
|
|
271
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
272
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
273
|
+
) {
|
|
274
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
275
|
+
resolve(self?.registry[playerId]?.isPlaying)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
Resolve `playerId`'s current paused state.
|
|
281
|
+
- Parameter playerId: Target player Id.
|
|
282
|
+
- Parameter resolver: JS promise resolver.
|
|
283
|
+
- Parameter rejecter: JS promise rejecter.
|
|
284
|
+
*/
|
|
285
|
+
@objc(isPaused:resolver:rejecter:)
|
|
286
|
+
func isPaused(
|
|
287
|
+
_ playerId: String,
|
|
288
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
289
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
290
|
+
) {
|
|
291
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
292
|
+
resolve(self?.registry[playerId]?.isPaused)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
Resolve `playerId`'s live streaming state.
|
|
298
|
+
`true` if source is a live streaming.
|
|
299
|
+
- Parameter playerId: Target player Id.
|
|
300
|
+
- Parameter resolver: JS promise resolver.
|
|
301
|
+
- Parameter rejecter: JS promise rejecter.
|
|
302
|
+
*/
|
|
303
|
+
@objc(isLive:resolver:rejecter:)
|
|
304
|
+
func isLive(
|
|
305
|
+
_ playerId: String,
|
|
306
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
307
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
308
|
+
) {
|
|
309
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
310
|
+
resolve(self?.registry[playerId]?.isLive)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
Resolve `playerId`'s air play activation state.
|
|
316
|
+
- Parameter playerId: Target player Id.
|
|
317
|
+
- Parameter resolver: JS promise resolver.
|
|
318
|
+
- Parameter rejecter: JS promise rejecter.
|
|
319
|
+
*/
|
|
320
|
+
@objc(isAirPlayActive:resolver:rejecter:)
|
|
321
|
+
func isAirPlayActive(
|
|
322
|
+
_ playerId: String,
|
|
323
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
324
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
325
|
+
) {
|
|
326
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
327
|
+
resolve(self?.registry[playerId]?.isAirPlayActive)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
Resolve `playerId`'s air play availability state.
|
|
333
|
+
- Parameter playerId: Target player Id.
|
|
334
|
+
- Parameter resolver: JS promise resolver.
|
|
335
|
+
- Parameter rejecter: JS promise rejecter.
|
|
336
|
+
*/
|
|
337
|
+
@objc(isAirPlayAvailable:resolver:rejecter:)
|
|
338
|
+
func isAirPlayAvailable(
|
|
339
|
+
_ playerId: String,
|
|
340
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
341
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
342
|
+
) {
|
|
343
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
344
|
+
resolve(self?.registry[playerId]?.isAirPlayAvailable)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import BitmovinPlayer
|
|
3
|
+
|
|
4
|
+
extension RCTConvert {
|
|
5
|
+
/**
|
|
6
|
+
Utility method to convert a JS object into `PlayerConfig`.
|
|
7
|
+
- Parameter json: JS object
|
|
8
|
+
- Returns: Generated `Playerconfig`
|
|
9
|
+
*/
|
|
10
|
+
static func playerConfig(_ json: Any?) -> PlayerConfig? {
|
|
11
|
+
let playerConfig = PlayerConfig()
|
|
12
|
+
guard let json = json as? [String: Any?] else {
|
|
13
|
+
return playerConfig
|
|
14
|
+
}
|
|
15
|
+
if let licenseKey = json["licenseKey"] as? String {
|
|
16
|
+
playerConfig.key = licenseKey
|
|
17
|
+
}
|
|
18
|
+
return playerConfig
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Utility method to convert a JS object into `SourceConfig`.
|
|
23
|
+
- Parameter json: JS object
|
|
24
|
+
- Returns: Generated `SourceConfig`
|
|
25
|
+
*/
|
|
26
|
+
static func sourceConfig(_ json: Any?) -> SourceConfig? {
|
|
27
|
+
guard let json = json as? [String: Any?] else {
|
|
28
|
+
return nil
|
|
29
|
+
}
|
|
30
|
+
let sourceConfig = SourceConfig(
|
|
31
|
+
url: RCTConvert.nsurl(json["url"]),
|
|
32
|
+
type: RCTConvert.sourceType(json["type"])
|
|
33
|
+
)
|
|
34
|
+
if let title = json["title"] as? String {
|
|
35
|
+
sourceConfig.title = title
|
|
36
|
+
}
|
|
37
|
+
if let poster = json["poster"] as? String {
|
|
38
|
+
sourceConfig.posterSource = RCTConvert.nsurl(poster)
|
|
39
|
+
}
|
|
40
|
+
if let isPosterPersistent = json["isPosterPersistent"] as? Bool {
|
|
41
|
+
sourceConfig.isPosterPersistent = isPosterPersistent
|
|
42
|
+
}
|
|
43
|
+
return sourceConfig
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
Utility method to convert a JS object into `SourceType`.
|
|
48
|
+
- Parameter json: JS object
|
|
49
|
+
- Returns: Generated `SourceType`
|
|
50
|
+
*/
|
|
51
|
+
static func sourceType(_ json: Any?) -> SourceType {
|
|
52
|
+
guard let json = json as? String else {
|
|
53
|
+
return .none
|
|
54
|
+
}
|
|
55
|
+
switch json {
|
|
56
|
+
case "none": return .none
|
|
57
|
+
case "hls": return .hls
|
|
58
|
+
case "dash": return .dash
|
|
59
|
+
case "progressive": return .progressive
|
|
60
|
+
default: return .none
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
Utility method to convert a JS object into `TimeMode`.
|
|
66
|
+
- Parameter json: JS object
|
|
67
|
+
- Returns: Generated `TimeMode`
|
|
68
|
+
*/
|
|
69
|
+
static func timeMode(_ json: Any?) -> TimeMode {
|
|
70
|
+
guard let json = json as? String else {
|
|
71
|
+
return .absoluteTime
|
|
72
|
+
}
|
|
73
|
+
switch json {
|
|
74
|
+
case "absolute": return .absoluteTime
|
|
75
|
+
case "relative": return .relativeTime
|
|
76
|
+
default: return .absoluteTime
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|