bitmovin-player-react-native 0.1.0 → 0.2.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.
Files changed (44) hide show
  1. package/README.md +163 -1
  2. package/RNBitmovinPlayer.podspec +3 -3
  3. package/android/src/main/java/com/bitmovin/player/reactnative/DrmModule.kt +191 -0
  4. package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +116 -101
  5. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +69 -38
  6. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +10 -26
  7. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +3 -0
  8. package/android/src/main/java/com/bitmovin/player/reactnative/Registry.kt +11 -0
  9. package/android/src/main/java/com/bitmovin/player/reactnative/SourceModule.kt +178 -0
  10. package/android/src/main/java/com/bitmovin/player/reactnative/UuidModule.kt +20 -0
  11. package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +128 -1
  12. package/android/src/main/java/com/bitmovin/player/reactnative/extensions/Events.kt +11 -2
  13. package/ios/DrmModule.m +16 -0
  14. package/ios/DrmModule.swift +442 -0
  15. package/ios/Event+JSON.swift +31 -0
  16. package/ios/PlayerModule.m +21 -25
  17. package/ios/PlayerModule.swift +122 -120
  18. package/ios/RCTConvert+BitmovinPlayer.swift +131 -12
  19. package/ios/RNPlayerView+PlayerListener.swift +12 -0
  20. package/ios/RNPlayerView.swift +5 -3
  21. package/ios/RNPlayerViewManager.m +3 -1
  22. package/ios/RNPlayerViewManager.swift +4 -21
  23. package/ios/Registry.swift +5 -0
  24. package/ios/SourceModule.m +30 -0
  25. package/ios/SourceModule.swift +187 -0
  26. package/ios/UuidModule.m +9 -0
  27. package/ios/UuidModule.swift +23 -0
  28. package/lib/index.d.ts +670 -235
  29. package/lib/index.js +257 -106
  30. package/lib/index.mjs +260 -112
  31. package/package.json +5 -4
  32. package/src/components/PlayerView/events.ts +24 -18
  33. package/src/components/PlayerView/index.tsx +29 -26
  34. package/src/drm/fairplayConfig.ts +90 -0
  35. package/src/drm/index.ts +178 -0
  36. package/src/drm/widevineConfig.ts +37 -0
  37. package/src/events.ts +67 -6
  38. package/src/hooks/useProxy.ts +19 -15
  39. package/src/index.ts +5 -3
  40. package/src/nativeInstance.ts +64 -0
  41. package/src/player.ts +51 -42
  42. package/src/source.ts +88 -8
  43. package/src/subtitleTrack.ts +60 -0
  44. package/src/utils.ts +15 -0
@@ -2,7 +2,7 @@ import BitmovinPlayer
2
2
 
3
3
  @objc(RNPlayerView)
4
4
  class RNPlayerView: UIView {
5
- /// Component events.
5
+ /// React component events. Directly mapped to props in `NativePlayerView`.
6
6
  @objc var onEvent: RCTBubblingEventBlock?
7
7
  @objc var onPlayerActive: RCTBubblingEventBlock?
8
8
  @objc var onPlayerError: RCTBubblingEventBlock?
@@ -23,9 +23,11 @@ class RNPlayerView: UIView {
23
23
  @objc var onSourceUnloaded: RCTBubblingEventBlock?
24
24
  @objc var onSourceError: RCTBubblingEventBlock?
25
25
  @objc var onSourceWarning: RCTBubblingEventBlock?
26
+ @objc var onSubtitleAdded: RCTBubblingEventBlock?
27
+ @objc var onSubtitleRemoved: RCTBubblingEventBlock?
28
+ @objc var onSubtitleChanged: RCTBubblingEventBlock?
26
29
 
27
- /// Bitmovin's player view.
28
- /// Get's initialized when there's a player instance ready to be used.
30
+ /// The `PlayerView` subview.
29
31
  var playerView: PlayerView? {
30
32
  willSet {
31
33
  newValue?.autoresizingMask = [
@@ -22,8 +22,10 @@ RCT_EXPORT_VIEW_PROPERTY(onSourceLoaded, RCTBubblingEventBlock)
22
22
  RCT_EXPORT_VIEW_PROPERTY(onSourceUnloaded, RCTBubblingEventBlock)
23
23
  RCT_EXPORT_VIEW_PROPERTY(onSourceError, RCTBubblingEventBlock)
24
24
  RCT_EXPORT_VIEW_PROPERTY(onSourceWarning, RCTBubblingEventBlock)
25
+ RCT_EXPORT_VIEW_PROPERTY(onSubtitleAdded, RCTBubblingEventBlock)
26
+ RCT_EXPORT_VIEW_PROPERTY(onSubtitleRemoved, RCTBubblingEventBlock)
27
+ RCT_EXPORT_VIEW_PROPERTY(onSubtitleChanged, RCTBubblingEventBlock)
25
28
 
26
29
  RCT_EXTERN_METHOD(attachPlayer:(nonnull NSNumber *)viewId playerId:(NSString *)playerId)
27
- RCT_EXTERN_METHOD(detachPlayer:(nonnull NSNumber *)viewId playerId:(NSString *)playerId)
28
30
 
29
31
  @end
@@ -3,8 +3,8 @@ import Foundation
3
3
 
4
4
  @objc(RNPlayerViewManager)
5
5
  class RNPlayerViewManager: RCTViewManager {
6
- /// Register module to be initialized on the main thread.
7
- override class func requiresMainQueueSetup() -> Bool {
6
+ /// Initialize module on main thread.
7
+ override static func requiresMainQueueSetup() -> Bool {
8
8
  true
9
9
  }
10
10
 
@@ -19,11 +19,11 @@ class RNPlayerViewManager: RCTViewManager {
19
19
  - Parameter viewId: `RNPlayerView` id inside `UIManager`'s registry.
20
20
  - Parameter playerId: `Player` instance id inside `PlayerModule`'s registry.
21
21
  */
22
- @objc func attachPlayer(_ viewId: NSNumber, playerId: String) {
22
+ @objc func attachPlayer(_ viewId: NSNumber, playerId: NativeId) {
23
23
  bridge.uiManager.addUIBlock { [weak self] _, views in
24
24
  guard
25
25
  let view = views?[viewId] as? RNPlayerView,
26
- let player = self?.getPlayerModule()?.player(with: playerId)
26
+ let player = self?.getPlayerModule()?.retrieve(playerId)
27
27
  else {
28
28
  return
29
29
  }
@@ -35,23 +35,6 @@ class RNPlayerViewManager: RCTViewManager {
35
35
  player.add(listener: view)
36
36
  }
37
37
  }
38
-
39
- /**
40
- Remove `RNPlayerView` from its associated `Player` listeners list.
41
- - Parameter viewId: `RNPlayerView` id inside `UIManager`'s registry.
42
- - Parameter playerId: `Player` instance id inside `PlayerModule`'s registry.
43
- */
44
- @objc func detachPlayer(_ viewId: NSNumber, playerId: String) {
45
- bridge.uiManager.addUIBlock { [weak self] _, views in
46
- guard
47
- let view = views?[viewId] as? RNPlayerView,
48
- let player = self?.getPlayerModule()?.player(with: playerId)
49
- else {
50
- return
51
- }
52
- player.remove(listener: view)
53
- }
54
- }
55
38
 
56
39
  /// Fetches the initialized `PlayerModule` instance on RN's bridge object.
57
40
  private func getPlayerModule() -> PlayerModule? {
@@ -0,0 +1,5 @@
1
+ /// Represents the `UUID` string used as index for a certain registry object.
2
+ typealias NativeId = String
3
+
4
+ /// Represents an in memory storage facility that associates an object of type `T` with a certain `NativeId`.
5
+ typealias Registry<T> = [NativeId: T]
@@ -0,0 +1,30 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_REMAP_MODULE(SourceModule, SourceModule, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(initWithConfig:(NSString *)nativeId config:(nullable id)config)
6
+ RCT_EXTERN_METHOD(initWithDrmConfig:(NSString *)nativeId drmNativeId:(NSString *)drmNativeId config:(nullable id)config)
7
+ RCT_EXTERN_METHOD(destroy:(NSString *)nativeId)
8
+ RCT_EXTERN_METHOD(
9
+ isAttachedToPlayer:(NSString *)nativeId
10
+ resolver:(RCTPromiseResolveBlock)resolve
11
+ rejecter:(RCTPromiseRejectBlock)reject)
12
+ RCT_EXTERN_METHOD(
13
+ isActive:(NSString *)nativeId
14
+ resolver:(RCTPromiseResolveBlock)resolve
15
+ rejecter:(RCTPromiseRejectBlock)reject)
16
+ RCT_EXTERN_METHOD(
17
+ duration:(NSString *)nativeId
18
+ resolver:(RCTPromiseResolveBlock)resolve
19
+ rejecter:(RCTPromiseRejectBlock)reject)
20
+ RCT_EXTERN_METHOD(
21
+ loadingState:(NSString *)nativeId
22
+ resolver:(RCTPromiseResolveBlock)resolve
23
+ rejecter:(RCTPromiseRejectBlock)reject)
24
+ RCT_EXTERN_METHOD(
25
+ getMetadata:(NSString *)nativeId
26
+ resolver:(RCTPromiseResolveBlock)resolve
27
+ rejecter:(RCTPromiseRejectBlock)reject)
28
+ RCT_EXTERN_METHOD(setMetadata:(NSString *)nativeId metadata:(nullable id)metadata)
29
+
30
+ @end
@@ -0,0 +1,187 @@
1
+ import BitmovinPlayer
2
+
3
+ @objc(SourceModule)
4
+ class SourceModule: NSObject, RCTBridgeModule {
5
+ /// React bridge reference.
6
+ @objc var bridge: RCTBridge!
7
+
8
+ /// In-memory mapping from `nativeId`s to `Source` instances.
9
+ private var sources: Registry<Source> = [:]
10
+
11
+ /// JS module name.
12
+ static func moduleName() -> String! {
13
+ "SourceModule"
14
+ }
15
+
16
+ /// Module requires main thread initialization.
17
+ static func requiresMainQueueSetup() -> Bool {
18
+ true
19
+ }
20
+
21
+ /// Use `UIManager.addBlock` to enqueue module methods on UI thread.
22
+ var methodQueue: DispatchQueue! {
23
+ bridge.uiManager.methodQueue
24
+ }
25
+
26
+ /**
27
+ Fetches the `Source` instance associated with `nativeId` from internal sources.
28
+ - Parameter nativeId: `Source` instance ID.
29
+ - Returns: The associated `Source` instance or `nil`.
30
+ */
31
+ @objc func retrieve(_ nativeId: NativeId) -> Source? {
32
+ sources[nativeId]
33
+ }
34
+
35
+ /**
36
+ Creates a new `Source` instance inside the internal sources using the provided `config` object.
37
+ - Parameter nativeId: ID to be associated with the `Source` instance.
38
+ - Parameter config: `SourceConfig` object received from JS.
39
+ */
40
+ @objc(initWithConfig:config:)
41
+ func initWithConfig(_ nativeId: NativeId, config: Any?) {
42
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
43
+ guard
44
+ self?.sources[nativeId] == nil,
45
+ let sourceConfig = RCTConvert.sourceConfig(config)
46
+ else {
47
+ return
48
+ }
49
+ self?.sources[nativeId] = SourceFactory.create(from: sourceConfig)
50
+ }
51
+ }
52
+
53
+ /**
54
+ Creates a new `Source` instance inside the internal sources using the provided `config` object and an initialized DRM configuration ID.
55
+ - Parameter nativeId: ID to be associated with the `Source` instance.
56
+ - Parameter drmNativeId: ID of the DRM config object to use.
57
+ - Parameter config: `SourceConfig` object received from JS.
58
+ */
59
+ @objc(initWithDrmConfig:drmNativeId:config:)
60
+ func initWithDrmConfig(_ nativeId: NativeId, drmNativeId: NativeId, config: Any?) {
61
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
62
+ guard
63
+ self?.sources[nativeId] == nil,
64
+ let fairplayConfig = self?.getDrmModule()?.retrieve(drmNativeId),
65
+ let sourceConfig = RCTConvert.sourceConfig(config, drmConfig: fairplayConfig)
66
+ else {
67
+ return
68
+ }
69
+ self?.sources[nativeId] = SourceFactory.create(from: sourceConfig)
70
+ }
71
+ }
72
+
73
+ /// Fetches the initialized `DrmModule` instance on RN's bridge object.
74
+ private func getDrmModule() -> DrmModule? {
75
+ bridge.module(for: DrmModule.self) as? DrmModule
76
+ }
77
+
78
+ /**
79
+ Removes the `Source` instance associated with `nativeId` from `sources`.
80
+ - Parameter nativeId: Instance to be disposed.
81
+ */
82
+ @objc(destroy:)
83
+ func destroy(_ nativeId: NativeId) {
84
+ sources.removeValue(forKey: nativeId)
85
+ }
86
+
87
+ /**
88
+ Whether `nativeId` source is currently attached to a player instance.
89
+ - Parameter nativeId: Source `nativeId`.
90
+ - Parameter resolver: JS promise resolver.
91
+ - Parameter rejecter: JS promise rejecter.
92
+ */
93
+ @objc(isAttachedToPlayer:resolver:rejecter:)
94
+ func isAttachedToPlayer(
95
+ _ nativeId: NativeId,
96
+ resolver resolve: @escaping RCTPromiseResolveBlock,
97
+ rejecter reject: @escaping RCTPromiseRejectBlock
98
+ ) {
99
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
100
+ resolve(self?.sources[nativeId]?.isAttachedToPlayer)
101
+ }
102
+ }
103
+
104
+ /**
105
+ Whether `nativeId` source is currently active in a `Player`.
106
+ - Parameter nativeId: Source `nativeId`.
107
+ - Parameter resolver: JS promise resolver.
108
+ - Parameter rejecter: JS promise rejecter.
109
+ */
110
+ @objc(isActive:resolver:rejecter:)
111
+ func isActive(
112
+ _ nativeId: NativeId,
113
+ resolver resolve: @escaping RCTPromiseResolveBlock,
114
+ rejecter reject: @escaping RCTPromiseRejectBlock
115
+ ) {
116
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
117
+ resolve(self?.sources[nativeId]?.isActive)
118
+ }
119
+ }
120
+
121
+ /**
122
+ The duration of `nativeId` source in seconds.
123
+ - Parameter nativeId: Source `nativeId`.
124
+ - Parameter resolver: JS promise resolver.
125
+ - Parameter rejecter: JS promise rejecter.
126
+ */
127
+ @objc(duration:resolver:rejecter:)
128
+ func duration(
129
+ _ nativeId: NativeId,
130
+ resolver resolve: @escaping RCTPromiseResolveBlock,
131
+ rejecter reject: @escaping RCTPromiseRejectBlock
132
+ ) {
133
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
134
+ resolve(self?.sources[nativeId]?.duration)
135
+ }
136
+ }
137
+
138
+ /**
139
+ The current loading state of `nativeId` source.
140
+ - Parameter nativeId: Source `nativeId`.
141
+ - Parameter resolver: JS promise resolver.
142
+ - Parameter rejecter: JS promise rejecter.
143
+ */
144
+ @objc(loadingState:resolver:rejecter:)
145
+ func loadingState(
146
+ _ nativeId: NativeId,
147
+ resolver resolve: @escaping RCTPromiseResolveBlock,
148
+ rejecter reject: @escaping RCTPromiseRejectBlock
149
+ ) {
150
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
151
+ resolve(self?.sources[nativeId]?.loadingState)
152
+ }
153
+ }
154
+
155
+ /**
156
+ Metadata for the currently loaded `nativeId` source.
157
+ - Parameter nativeId: Source `nativeId`.
158
+ - Parameter resolver: JS promise resolver.
159
+ - Parameter rejecter: JS promise rejecter.
160
+ */
161
+ @objc(getMetadata:resolver:rejecter:)
162
+ func getMetadata(
163
+ _ nativeId: NativeId,
164
+ resolver resolve: @escaping RCTPromiseResolveBlock,
165
+ rejecter reject: @escaping RCTPromiseRejectBlock
166
+ ) {
167
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
168
+ resolve(self?.sources[nativeId]?.metadata)
169
+ }
170
+ }
171
+
172
+ /**
173
+ Set the metadata for a loaded `nativeId` source.
174
+ - Parameter nativeId: Source `nativeId`.
175
+ - Parameter resolver: JS promise resolver.
176
+ - Parameter rejecter: JS promise rejecter.
177
+ */
178
+ @objc(setMetadata:metadata:)
179
+ func setMetadata(_ nativeId: NativeId, metadata: Any?) {
180
+ bridge.uiManager.addUIBlock { [weak self] _, _ in
181
+ guard let metadata = metadata as? [String: AnyObject] else {
182
+ return
183
+ }
184
+ self?.sources[nativeId]?.metadata = metadata
185
+ }
186
+ }
187
+ }
@@ -0,0 +1,9 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_REMAP_MODULE(UuidModule, UuidModule, NSObject)
4
+
5
+ // UUID generation is sync and runs on the JS thread so in order to avoid performance
6
+ // issues, it should be as fast as possible.
7
+ RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(generate)
8
+
9
+ @end
@@ -0,0 +1,23 @@
1
+ /**
2
+ Native module for easy and fast unique ID generation on JS side. Used to generate native instance IDs.
3
+ */
4
+ @objc(UuidModule)
5
+ class UuidModule: NSObject, RCTBridgeModule {
6
+ /// Initialize this module on main thread.
7
+ static func requiresMainQueueSetup() -> Bool {
8
+ true
9
+ }
10
+
11
+ /// Exported JS module name.
12
+ static func moduleName() -> String! {
13
+ "UuidModule"
14
+ }
15
+
16
+ /**
17
+ Synchronously generate a random UUIDv4.
18
+ - Returns: Random UUID RFC 4122 version 4.
19
+ */
20
+ @objc func generate() -> String {
21
+ UUID().uuidString
22
+ }
23
+ }