bitmovin-player-react-native 0.9.2 → 0.10.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/RNBitmovinPlayer.podspec +1 -1
- package/android/build.gradle +1 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/AnalyticsModule.kt +43 -11
- package/android/src/main/java/com/bitmovin/player/reactnative/OfflineModule.kt +279 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +37 -1
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +1 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +123 -35
- package/android/src/main/java/com/bitmovin/player/reactnative/offline/OfflineContentManagerBridge.kt +216 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/offline/OfflineDownloadRequest.kt +7 -0
- package/ios/DrmModule.swift +5 -5
- package/ios/OfflineContentManagerBridge.swift +141 -0
- package/ios/OfflineModule.m +19 -0
- package/ios/OfflineModule.swift +465 -0
- package/ios/PlayerModule.m +2 -0
- package/ios/PlayerModule.swift +40 -7
- package/ios/RCTConvert+BitmovinPlayer.swift +135 -1
- package/ios/RNBitmovinPlayer.h +1 -0
- package/lib/index.d.mts +382 -2
- package/lib/index.d.ts +382 -2
- package/lib/index.js +233 -0
- package/lib/index.mjs +231 -0
- package/package.json +1 -1
- package/src/adaptationConfig.ts +10 -0
- package/src/index.ts +2 -0
- package/src/offline/index.ts +7 -0
- package/src/offline/offlineContentConfig.ts +18 -0
- package/src/offline/offlineContentManager.ts +216 -0
- package/src/offline/offlineContentManagerListener.ts +187 -0
- package/src/offline/offlineContentOptions.ts +29 -0
- package/src/offline/offlineDownloadRequest.ts +20 -0
- package/src/offline/offlineSourceOptions.ts +11 -0
- package/src/offline/offlineState.ts +22 -0
- package/src/player.ts +30 -0
- package/src/source.ts +38 -0
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
|
|
2
|
+
import Foundation
|
|
3
|
+
import BitmovinPlayer
|
|
4
|
+
|
|
5
|
+
@objc(OfflineModule)
|
|
6
|
+
class OfflineModule: RCTEventEmitter {
|
|
7
|
+
/// JS module name.
|
|
8
|
+
override static func moduleName() -> String! {
|
|
9
|
+
"BitmovinOfflineModule"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/// Module requires main thread initialization.
|
|
13
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
14
|
+
true
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override func supportedEvents() -> [String]! {
|
|
18
|
+
return ["BitmovinOfflineEvent"]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Since most `OfflineModule` operations are UI related and need to be executed on the main thread, they are scheduled with `UIManager.addBlock`.
|
|
22
|
+
override var methodQueue: DispatchQueue! {
|
|
23
|
+
bridge.uiManager.methodQueue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#if os(iOS)
|
|
27
|
+
private var offlineContentManagerBridges: Registry<OfflineContentManagerBridge> = [:]
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
Retrieves the `OfflineContentManager` instance associated with `nativeId` from the internal offline managers.
|
|
31
|
+
- Parameter nativeId `OfflineContentManager` instance ID.
|
|
32
|
+
- Returns: The associated `OfflineContentManager` instance or `nil`.
|
|
33
|
+
*/
|
|
34
|
+
func retrieve(_ nativeId: NativeId) -> OfflineContentManagerBridge? {
|
|
35
|
+
offlineContentManagerBridges[nativeId]
|
|
36
|
+
}
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
Creates a new `OfflineContentManager` instance inside the internal offline managers using the provided config object.
|
|
41
|
+
- @param config Config object received from JS. Should contain `sourceConfig` and `identifier`.
|
|
42
|
+
*/
|
|
43
|
+
@objc(initWithConfig:config:drmNativeId:resolver:rejecter:)
|
|
44
|
+
func initWithConfig(
|
|
45
|
+
_ nativeId: NativeId,
|
|
46
|
+
config: Any?,
|
|
47
|
+
drmNativeId: NativeId?,
|
|
48
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
49
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
50
|
+
) {
|
|
51
|
+
#if os(iOS)
|
|
52
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
53
|
+
guard
|
|
54
|
+
let self = self,
|
|
55
|
+
self.offlineContentManagerBridges[nativeId] == nil,
|
|
56
|
+
let config = config as? [String: Any?],
|
|
57
|
+
let identifier = config["identifier"] as? String
|
|
58
|
+
else {
|
|
59
|
+
reject("BitmovinOfflineModule", "Could not create an offline content manager", nil)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let fairplayConfig = drmNativeId.flatMap { self.bridge[DrmModule.self]?.retrieve($0) }
|
|
64
|
+
guard let sourceConfig = RCTConvert.sourceConfig(config["sourceConfig"], drmConfig: fairplayConfig) else {
|
|
65
|
+
reject("BitmovinOfflineModule", "Invalid source config", nil)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
do {
|
|
70
|
+
let offlineContentManager = try OfflineManager.sharedInstance()
|
|
71
|
+
.offlineContentManager(for: sourceConfig, id: identifier)
|
|
72
|
+
let offlineContentManagerBridge = OfflineContentManagerBridge(
|
|
73
|
+
forManager: offlineContentManager,
|
|
74
|
+
eventEmitter: self,
|
|
75
|
+
nativeId: nativeId,
|
|
76
|
+
identifier: identifier
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self.offlineContentManagerBridges[nativeId] = offlineContentManagerBridge
|
|
80
|
+
resolve(nil)
|
|
81
|
+
} catch let error as NSError {
|
|
82
|
+
reject("BitmovinOfflineModule", "Could not create an offline content manager", error)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
#endif
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@objc(getState:resolver:rejecter:)
|
|
89
|
+
func getState(
|
|
90
|
+
_ nativeId: NativeId,
|
|
91
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
92
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
93
|
+
) {
|
|
94
|
+
#if os(iOS)
|
|
95
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
96
|
+
guard
|
|
97
|
+
let self = self,
|
|
98
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
99
|
+
else {
|
|
100
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resolve(RCTConvert.toJson(offlineState: offlineContentManagerBridge.offlineContentManager.offlineState))
|
|
105
|
+
}
|
|
106
|
+
#endif
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
Starts the `OfflineContentManager`'s asynchronous process of fetching the `OfflineContentOptions`.
|
|
111
|
+
When the options are loaded a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onOptionsAvailable`.
|
|
112
|
+
- Parameter nativeId: Target offline module Id.
|
|
113
|
+
- Parameter resolver: JS promise resolver.
|
|
114
|
+
- Parameter rejecter: JS promise rejecter.
|
|
115
|
+
*/
|
|
116
|
+
@objc(getOptions:resolver:rejecter:)
|
|
117
|
+
func getOptions(
|
|
118
|
+
_ nativeId: NativeId,
|
|
119
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
120
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
121
|
+
#if os(iOS)
|
|
122
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
123
|
+
guard
|
|
124
|
+
let self = self,
|
|
125
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
126
|
+
else {
|
|
127
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
offlineContentManagerBridge.fetchAvailableTracks()
|
|
132
|
+
resolve(nil)
|
|
133
|
+
}
|
|
134
|
+
#endif
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
Enqueues downloads according to the `OfflineDownloadRequest`.
|
|
139
|
+
* The promise will reject in the event of null or invalid request parameters.
|
|
140
|
+
- Parameter nativeId: Target offline module Id
|
|
141
|
+
- Parameter request: The download request js object containing the requested bitrate and track option ids to download.
|
|
142
|
+
- Parameter resolver: JS promise resolver.
|
|
143
|
+
- Parameter rejecter: JS promise rejecter.
|
|
144
|
+
*/
|
|
145
|
+
@objc(download:request:resolver:rejecter:)
|
|
146
|
+
func download(
|
|
147
|
+
_ nativeId: NativeId,
|
|
148
|
+
request: Any?,
|
|
149
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
150
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
151
|
+
) {
|
|
152
|
+
#if os(iOS)
|
|
153
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
154
|
+
guard
|
|
155
|
+
let self = self,
|
|
156
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
157
|
+
else {
|
|
158
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
switch offlineContentManagerBridge.offlineContentManager.offlineState {
|
|
163
|
+
case .downloaded:
|
|
164
|
+
reject("BitmovinOfflineModule", "Download already completed", nil)
|
|
165
|
+
return
|
|
166
|
+
case .downloading:
|
|
167
|
+
reject("BitmovinOfflineModule", "Download already in progress", nil)
|
|
168
|
+
return
|
|
169
|
+
case .suspended:
|
|
170
|
+
reject("BitmovinOfflineModule", "Download is suspended", nil)
|
|
171
|
+
return
|
|
172
|
+
@unknown default:
|
|
173
|
+
break
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
guard let request = request as? [String: Any?] else {
|
|
177
|
+
reject("BitmovinOfflineModule", "Invalid download request", nil)
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
guard
|
|
182
|
+
let currentTrackSelection = offlineContentManagerBridge.currentTrackSelection
|
|
183
|
+
else {
|
|
184
|
+
reject("BitmovinOfflineModule", "Invalid download options", nil)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if let audioOptionIds = request["audioOptionIds"] as? [String],
|
|
189
|
+
!audioOptionIds.isEmpty {
|
|
190
|
+
currentTrackSelection.audioTracks.forEach {
|
|
191
|
+
if audioOptionIds.contains($0.label) {
|
|
192
|
+
$0.action = .download
|
|
193
|
+
} else {
|
|
194
|
+
$0.action = .none
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if let textOptionIds = request["textOptionIds"] as? [String],
|
|
200
|
+
!textOptionIds.isEmpty {
|
|
201
|
+
currentTrackSelection.textTracks.forEach {
|
|
202
|
+
if textOptionIds.contains($0.label) {
|
|
203
|
+
$0.action = .download
|
|
204
|
+
} else {
|
|
205
|
+
$0.action = .none
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let config = DownloadConfig()
|
|
211
|
+
|
|
212
|
+
if let minimumBitrate = request["minimumBitrate"] as? NSNumber {
|
|
213
|
+
config.minimumBitrate = minimumBitrate
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
offlineContentManagerBridge.offlineContentManager.download(tracks: currentTrackSelection, downloadConfig: config)
|
|
217
|
+
resolve(nil)
|
|
218
|
+
}
|
|
219
|
+
#endif
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
Resumes all suspended actions.
|
|
224
|
+
- Parameter nativeId: Target offline module Id
|
|
225
|
+
- Parameter resolver: JS promise resolver.
|
|
226
|
+
- Parameter rejecter: JS promise rejecter.
|
|
227
|
+
*/
|
|
228
|
+
@objc(resume:resolver:rejecter:)
|
|
229
|
+
func resume(
|
|
230
|
+
_ nativeId: NativeId,
|
|
231
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
232
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
233
|
+
#if os(iOS)
|
|
234
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
235
|
+
guard
|
|
236
|
+
let self = self,
|
|
237
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
238
|
+
else {
|
|
239
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
offlineContentManagerBridge.offlineContentManager.resumeDownload()
|
|
244
|
+
resolve(nil)
|
|
245
|
+
}
|
|
246
|
+
#endif
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
Suspends all active actions.
|
|
251
|
+
- Parameter nativeId: Target offline module Id
|
|
252
|
+
- Parameter resolver: JS promise resolver.
|
|
253
|
+
- Parameter rejecter: JS promise rejecter.
|
|
254
|
+
*/
|
|
255
|
+
@objc(suspend:resolver:rejecter:)
|
|
256
|
+
func suspend(
|
|
257
|
+
_ nativeId: NativeId,
|
|
258
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
259
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
260
|
+
) {
|
|
261
|
+
#if os(iOS)
|
|
262
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
263
|
+
guard
|
|
264
|
+
let self = self,
|
|
265
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
266
|
+
else {
|
|
267
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
268
|
+
return
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
offlineContentManagerBridge.offlineContentManager.suspendDownload()
|
|
272
|
+
resolve(nil)
|
|
273
|
+
}
|
|
274
|
+
#endif
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
Cancels all active downloads and removes the data.
|
|
279
|
+
- Parameter nativeId: Target offline module Id
|
|
280
|
+
- Parameter resolver: JS promise resolver.
|
|
281
|
+
- Parameter rejecter: JS promise rejecter.
|
|
282
|
+
*/
|
|
283
|
+
@objc(cancelDownload:resolver:rejecter:)
|
|
284
|
+
func cancelDownload(
|
|
285
|
+
_ nativeId: NativeId,
|
|
286
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
287
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
288
|
+
) {
|
|
289
|
+
#if os(iOS)
|
|
290
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
291
|
+
guard
|
|
292
|
+
let self = self,
|
|
293
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
294
|
+
else {
|
|
295
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
296
|
+
return
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
offlineContentManagerBridge.offlineContentManager.cancelDownload()
|
|
300
|
+
resolve(nil)
|
|
301
|
+
}
|
|
302
|
+
#endif
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
Resolve `nativeId`'s current `usedStorage`.
|
|
307
|
+
- Parameter nativeId: Target offline module Id
|
|
308
|
+
- Parameter resolver: JS promise resolver.
|
|
309
|
+
- Parameter rejecter: JS promise rejecter.
|
|
310
|
+
*/
|
|
311
|
+
@objc(usedStorage:resolver:rejecter:)
|
|
312
|
+
func usedStorage(
|
|
313
|
+
_ nativeId: NativeId,
|
|
314
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
315
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
316
|
+
) {
|
|
317
|
+
#if os(iOS)
|
|
318
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
319
|
+
guard
|
|
320
|
+
let self = self,
|
|
321
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
322
|
+
else {
|
|
323
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
resolve(offlineContentManagerBridge.offlineContentManager.usedStorage)
|
|
328
|
+
}
|
|
329
|
+
#endif
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
Deletes everything related to the related content ID.
|
|
334
|
+
- Parameter nativeId: Target offline module Id
|
|
335
|
+
- Parameter resolver: JS promise resolver.
|
|
336
|
+
- Parameter rejecter: JS promise rejecter.
|
|
337
|
+
*/
|
|
338
|
+
@objc(deleteAll:resolver:rejecter:)
|
|
339
|
+
func deleteAll(
|
|
340
|
+
_ nativeId: NativeId,
|
|
341
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
342
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
343
|
+
) {
|
|
344
|
+
#if os(iOS)
|
|
345
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
346
|
+
guard
|
|
347
|
+
let self = self,
|
|
348
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
349
|
+
else {
|
|
350
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
offlineContentManagerBridge.offlineContentManager.deleteOfflineData()
|
|
355
|
+
resolve(nil)
|
|
356
|
+
}
|
|
357
|
+
#endif
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
Downloads the offline license.
|
|
362
|
+
When finished successfully a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onDrmLicenseUpdated`.
|
|
363
|
+
Errors are transmitted by a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onError`.
|
|
364
|
+
- Parameter nativeId: Target offline module Id
|
|
365
|
+
- Parameter resolver: JS promise resolver.
|
|
366
|
+
- Parameter rejecter: JS promise rejecter.
|
|
367
|
+
*/
|
|
368
|
+
@objc(donwloadLicense:resolver:rejecter:)
|
|
369
|
+
func downloadLicense(
|
|
370
|
+
_ nativeId: NativeId,
|
|
371
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
372
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
373
|
+
) {
|
|
374
|
+
#if os(iOS)
|
|
375
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
376
|
+
guard
|
|
377
|
+
let self = self,
|
|
378
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
379
|
+
else {
|
|
380
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
offlineContentManagerBridge.offlineContentManager.syncOfflineDrmLicenseInformation()
|
|
385
|
+
resolve(nil)
|
|
386
|
+
}
|
|
387
|
+
#endif
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
Renews the already downloaded DRM license.
|
|
392
|
+
When finished successfully a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onDrmLicenseUpdated`.
|
|
393
|
+
Errors are transmitted by a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onError`.
|
|
394
|
+
- Parameter nativeId: Target offline module Id
|
|
395
|
+
- Parameter resolver: JS promise resolver.
|
|
396
|
+
- Parameter rejecter: JS promise rejecter.
|
|
397
|
+
*/
|
|
398
|
+
@objc(renewOfflineLicense:resolver:rejecter:)
|
|
399
|
+
func renewOfflineLicense(
|
|
400
|
+
_ nativeId: NativeId,
|
|
401
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
402
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
403
|
+
) {
|
|
404
|
+
#if os(iOS)
|
|
405
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
406
|
+
guard
|
|
407
|
+
let self = self,
|
|
408
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
409
|
+
else {
|
|
410
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
411
|
+
return
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
offlineContentManagerBridge.offlineContentManager.renewOfflineLicense()
|
|
415
|
+
resolve(nil)
|
|
416
|
+
}
|
|
417
|
+
#endif
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
Removes the `OfflineContentManagerListener` for the `nativeId`'s offline content manager.
|
|
422
|
+
IMPORTANT: Call this when the component, in which it was created, is destroyed.
|
|
423
|
+
The `OfflineManager` should not be used after calling this method.
|
|
424
|
+
- Parameter nativeId: Target offline module Id
|
|
425
|
+
- Parameter resolver: JS promise resolver.
|
|
426
|
+
- Parameter rejecter: JS promise rejecter.
|
|
427
|
+
*/
|
|
428
|
+
@objc(release:resolver:rejecter:)
|
|
429
|
+
func release(
|
|
430
|
+
_ nativeId: NativeId,
|
|
431
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
432
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
433
|
+
) {
|
|
434
|
+
#if os(iOS)
|
|
435
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
436
|
+
guard
|
|
437
|
+
let self = self,
|
|
438
|
+
let offlineContentManagerBridge = self.offlineContentManagerBridges[nativeId]
|
|
439
|
+
else {
|
|
440
|
+
reject("BitmovinOfflineModule", "Could not find the offline module instance", nil)
|
|
441
|
+
return
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
offlineContentManagerBridge.release()
|
|
445
|
+
self.offlineContentManagerBridges[nativeId] = nil
|
|
446
|
+
resolve(nil)
|
|
447
|
+
}
|
|
448
|
+
#endif
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
This method is no-op on iOS.
|
|
453
|
+
- Parameter nativeId: Target offline module Id
|
|
454
|
+
- Parameter resolver: JS promise resolver.
|
|
455
|
+
- Parameter rejecter: JS promise rejecter.
|
|
456
|
+
*/
|
|
457
|
+
@objc(releaseLicense:resolver:rejecter:)
|
|
458
|
+
func releaseLicense(
|
|
459
|
+
_ nativeId: NativeId,
|
|
460
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
461
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
462
|
+
) {
|
|
463
|
+
resolve(nil)
|
|
464
|
+
}
|
|
465
|
+
}
|
package/ios/PlayerModule.m
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
RCT_EXTERN_METHOD(initWithConfig:(NSString *)nativeId config:(nullable id)config)
|
|
6
6
|
RCT_EXTERN_METHOD(loadSource:(NSString *)nativeId sourceNativeId:(NSString *)sourceNativeId)
|
|
7
|
+
RCT_EXTERN_METHOD(loadOfflineContent:(NSString *)nativeId offlineContentManagerBridgeId:(NSString *)offlineContentManagerBridgeId options:(nullable id)options)
|
|
7
8
|
RCT_EXTERN_METHOD(unload:(NSString *)nativeId)
|
|
8
9
|
RCT_EXTERN_METHOD(play:(NSString *)nativeId)
|
|
9
10
|
RCT_EXTERN_METHOD(pause:(NSString *)nativeId)
|
|
@@ -82,5 +83,6 @@ RCT_EXTERN_METHOD(
|
|
|
82
83
|
getMaxTimeShift:(NSString *)nativeId
|
|
83
84
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
84
85
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
86
|
+
RCT_EXTERN_METHOD(setMaxSelectableBitrate:(NSString *)nativeId maxSelectableBitrate:(nonnull NSNumber *)maxSelectableBitrate)
|
|
85
87
|
|
|
86
88
|
@end
|
package/ios/PlayerModule.swift
CHANGED
|
@@ -59,7 +59,7 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
59
59
|
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
60
60
|
guard
|
|
61
61
|
let player = self?.players[nativeId],
|
|
62
|
-
let source = self?.
|
|
62
|
+
let source = self?.bridge[SourceModule.self]?.retrieve(sourceNativeId)
|
|
63
63
|
else {
|
|
64
64
|
return
|
|
65
65
|
}
|
|
@@ -67,9 +67,29 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
/**
|
|
71
|
+
Loads the given offline source configuration into `nativeId`'s `Player` object.
|
|
72
|
+
- Parameter nativeId: Target player.
|
|
73
|
+
- Parameter offlineContentManagerBridgeId: The `nativeId` of the `OfflineModule` object.
|
|
74
|
+
*/
|
|
75
|
+
@objc(loadOfflineContent:offlineContentManagerBridgeId:options:)
|
|
76
|
+
func loadOfflineContent(_ nativeId: NativeId, offlineContentManagerBridgeId: NativeId, options: Any?) {
|
|
77
|
+
#if os(iOS)
|
|
78
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
79
|
+
guard
|
|
80
|
+
let player = self?.players[nativeId],
|
|
81
|
+
let offlineContentManagerBridge = self?.bridge[OfflineModule.self]?.retrieve(offlineContentManagerBridgeId)
|
|
82
|
+
else {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
let optionsDictionary = options as? [String: Any?] ?? [:]
|
|
86
|
+
let restrictedToAssetCache = optionsDictionary["restrictedToAssetCache"] as? Bool ?? true
|
|
87
|
+
let offlineSourceConfig = offlineContentManagerBridge.offlineContentManager.createOfflineSourceConfig(restrictedToAssetCache: restrictedToAssetCache)
|
|
88
|
+
|
|
89
|
+
guard let offlineSourceConfig = offlineSourceConfig else { return }
|
|
90
|
+
player.load(sourceConfig: offlineSourceConfig)
|
|
91
|
+
}
|
|
92
|
+
#endif
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
/**
|
|
@@ -116,7 +136,7 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
116
136
|
self?.players[nativeId]?.seek(time: time.doubleValue)
|
|
117
137
|
}
|
|
118
138
|
}
|
|
119
|
-
|
|
139
|
+
|
|
120
140
|
/**
|
|
121
141
|
Sets `timeShift` on `nativeId`'s player.
|
|
122
142
|
- Parameter nativeId: Target player Id.
|
|
@@ -462,7 +482,7 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
462
482
|
resolve(self?.players[nativeId]?.isAd)
|
|
463
483
|
}
|
|
464
484
|
}
|
|
465
|
-
|
|
485
|
+
|
|
466
486
|
/**
|
|
467
487
|
The current time shift of the live stream in seconds. This value is always 0 if the active `source` is not a
|
|
468
488
|
live stream or there are no sources loaded.
|
|
@@ -480,7 +500,7 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
480
500
|
resolve(self?.players[nativeId]?.timeShift)
|
|
481
501
|
}
|
|
482
502
|
}
|
|
483
|
-
|
|
503
|
+
|
|
484
504
|
/**
|
|
485
505
|
Returns the limit in seconds for time shift. Is either negative or 0. Is applicable for live streams only.
|
|
486
506
|
- Parameter nativeId: Target player id.
|
|
@@ -497,4 +517,17 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
497
517
|
resolve(self?.players[nativeId]?.maxTimeShift)
|
|
498
518
|
}
|
|
499
519
|
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
Sets the max selectable bitrate for the player.
|
|
523
|
+
- Parameter nativeId: Target player id.
|
|
524
|
+
- Parameter maxBitrate: The desired max bitrate limit.
|
|
525
|
+
*/
|
|
526
|
+
@objc(setMaxSelectableBitrate:maxSelectableBitrate:)
|
|
527
|
+
func setMaxSelectableBitrate(_ nativeId: NativeId, maxSelectableBitrate: NSNumber) {
|
|
528
|
+
let maxSelectableBitrateValue = maxSelectableBitrate.uintValue
|
|
529
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
530
|
+
self?.players[nativeId]?.maxSelectableBitrate = maxSelectableBitrateValue != -1 ? maxSelectableBitrateValue : 0
|
|
531
|
+
}
|
|
532
|
+
}
|
|
500
533
|
}
|