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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/RNBitmovinPlayer.podspec +23 -0
  4. package/android/build.gradle +55 -0
  5. package/android/src/main/AndroidManifest.xml +4 -0
  6. package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +279 -0
  7. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +264 -0
  8. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +139 -0
  9. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +33 -0
  10. package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +162 -0
  11. package/android/src/main/java/com/bitmovin/player/reactnative/extensions/Events.kt +15 -0
  12. package/ios/Event+JSON.swift +132 -0
  13. package/ios/PlayerModule.m +61 -0
  14. package/ios/PlayerModule.swift +347 -0
  15. package/ios/RCTConvert+BitmovinPlayer.swift +79 -0
  16. package/ios/RNBitmovinPlayer.h +7 -0
  17. package/ios/RNBitmovinPlayer.xcodeproj/project.pbxproj +303 -0
  18. package/ios/RNPlayerView+PlayerListener.swift +83 -0
  19. package/ios/RNPlayerView.swift +50 -0
  20. package/ios/RNPlayerViewManager.m +29 -0
  21. package/ios/RNPlayerViewManager.swift +60 -0
  22. package/lib/index.d.ts +486 -0
  23. package/lib/index.js +218 -0
  24. package/lib/index.mjs +191 -0
  25. package/package.json +82 -0
  26. package/src/components/PlayerView/events.ts +69 -0
  27. package/src/components/PlayerView/index.tsx +106 -0
  28. package/src/components/PlayerView/native.ts +17 -0
  29. package/src/components/index.ts +1 -0
  30. package/src/events.ts +184 -0
  31. package/src/hooks/index.ts +1 -0
  32. package/src/hooks/usePlayer.ts +10 -0
  33. package/src/hooks/useProxy.ts +36 -0
  34. package/src/index.ts +5 -0
  35. package/src/player.ts +229 -0
  36. package/src/source.ts +95 -0
@@ -0,0 +1,264 @@
1
+ package com.bitmovin.player.reactnative
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.view.ViewGroup
5
+ import android.widget.LinearLayout
6
+ import com.bitmovin.player.PlayerView
7
+ import com.bitmovin.player.api.Player
8
+ import com.bitmovin.player.api.event.Event
9
+ import com.bitmovin.player.api.event.PlayerEvent
10
+ import com.bitmovin.player.api.event.SourceEvent
11
+ import com.bitmovin.player.api.event.on
12
+ import com.bitmovin.player.reactnative.converter.JsonConverter
13
+ import com.facebook.react.bridge.ReactApplicationContext
14
+ import com.facebook.react.bridge.ReactContext
15
+ import com.facebook.react.uimanager.events.RCTEventEmitter
16
+
17
+ /**
18
+ * Native view wrapper for component instances. It both serves as the main view
19
+ * handled by RN (the actual player view is handled by the RNPlayerViewManager) and
20
+ * exposes player events as bubbling events.
21
+ */
22
+ @SuppressLint("ViewConstructor")
23
+ class RNPlayerView(context: ReactApplicationContext) : LinearLayout(context) {
24
+ /**
25
+ * Reference to the shared player view set as child.
26
+ */
27
+ var playerView: PlayerView? = null
28
+
29
+ /**
30
+ * Handy property accessor for `playerView`'s player instance.
31
+ */
32
+ var player: Player?
33
+ get() = playerView?.player
34
+ set(value) {
35
+ playerView?.player = value
36
+ }
37
+
38
+ /**
39
+ * Set the given `playerView` as child and start bubbling events.
40
+ * @param playerView Shared player view instance.
41
+ */
42
+ fun addPlayerView(playerView: PlayerView) {
43
+ this.playerView = playerView
44
+ if (playerView.parent != this) {
45
+ (playerView.parent as ViewGroup?)?.removeView(playerView)
46
+ addView(playerView)
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Try to measure and update this view layout as much as possible to
52
+ * avoid layout problems related to React or old layout values present
53
+ * in `playerView` due to being previously attached to a different parent.
54
+ */
55
+ override fun requestLayout() {
56
+ super.requestLayout()
57
+ post {
58
+ measure(
59
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
60
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY))
61
+ layout(left, top, right, bottom)
62
+ }
63
+ }
64
+
65
+ /**
66
+ * `onEvent` event callback.
67
+ */
68
+ private val onEvent: (PlayerEvent) -> Unit = {
69
+ emitEvent("event", it)
70
+ }
71
+
72
+ /**
73
+ * `onPlayerError` event callback.
74
+ */
75
+ private val onPlayerError: (PlayerEvent.Error) -> Unit = {
76
+ emitEvent("playerError", it)
77
+ }
78
+
79
+ /**
80
+ * `onPlayerWarning` event callback.
81
+ */
82
+ private val onPlayerWarning: (PlayerEvent.Warning) -> Unit = {
83
+ emitEvent("playerWarning", it)
84
+ }
85
+
86
+ /**
87
+ * `onDestroy` event callback.
88
+ */
89
+ private val onDestroy: (PlayerEvent.Destroy) -> Unit = {
90
+ emitEvent("destroy", it)
91
+ }
92
+
93
+ /**
94
+ * `onMuted` event callback.
95
+ */
96
+ private val onMuted: (PlayerEvent.Muted) -> Unit = {
97
+ emitEvent("muted", it)
98
+ }
99
+
100
+ /**
101
+ * `onUnmuted` event callback.
102
+ */
103
+ private val onUnmuted: (PlayerEvent.Unmuted) -> Unit = {
104
+ emitEvent("unmuted", it)
105
+ }
106
+
107
+ /**
108
+ * `onReady` event callback.
109
+ */
110
+ private val onReady: (PlayerEvent.Ready) -> Unit = {
111
+ emitEvent("ready", it)
112
+ }
113
+
114
+ /**
115
+ * `onPaused` event callback.
116
+ */
117
+ private val onPaused: (PlayerEvent.Paused) -> Unit = {
118
+ emitEvent("paused", it)
119
+ }
120
+
121
+ /**
122
+ * `onPlay` event callback.
123
+ */
124
+ private val onPlay: (PlayerEvent.Play) -> Unit = {
125
+ emitEvent("play", it)
126
+ }
127
+
128
+ /**
129
+ * `onPlaying` event callback.
130
+ */
131
+ private val onPlaying: (PlayerEvent.Playing) -> Unit = {
132
+ emitEvent("playing", it)
133
+ }
134
+
135
+ /**
136
+ * `onPlaybackFinished` event callback.
137
+ */
138
+ private val onPlaybackFinished: (PlayerEvent.PlaybackFinished) -> Unit = {
139
+ emitEvent("playbackFinished", it)
140
+ }
141
+
142
+ /**
143
+ * `onSeek` event callback.
144
+ */
145
+ private val onSeek: (PlayerEvent.Seek) -> Unit = {
146
+ emitEvent("seek", it)
147
+ }
148
+
149
+ /**
150
+ * `onSeeked` event callback.
151
+ */
152
+ private val onSeeked: (PlayerEvent.Seeked) -> Unit = {
153
+ emitEvent("seeked", it)
154
+ }
155
+
156
+ /**
157
+ * `onTimeChanged` event callback.
158
+ */
159
+ private val onTimeChanged: (PlayerEvent.TimeChanged) -> Unit = {
160
+ emitEvent("timeChanged", it)
161
+ }
162
+
163
+ /**
164
+ * `onSourceLoad` event callback.
165
+ */
166
+ private val onSourceLoad: (SourceEvent.Load) -> Unit = {
167
+ emitEvent("sourceLoad", it)
168
+ }
169
+
170
+ /**
171
+ * `onSourceLoaded` event callback.
172
+ */
173
+ private val onSourceLoaded: (SourceEvent.Loaded) -> Unit = {
174
+ emitEvent("sourceLoaded", it)
175
+ }
176
+
177
+ /**
178
+ * `onSourceUnloaded` event callback.
179
+ */
180
+ private val onSourceUnloaded: (SourceEvent.Unloaded) -> Unit = {
181
+ emitEvent("sourceUnloaded", it)
182
+ }
183
+
184
+ /**
185
+ * `onSourceError` event callback.
186
+ */
187
+ private val onSourceError: (SourceEvent.Error) -> Unit = {
188
+ emitEvent("sourceError", it)
189
+ }
190
+
191
+ /**
192
+ * `onSourceWarning` event callback.
193
+ */
194
+ private val onSourceWarning: (SourceEvent.Warning) -> Unit = {
195
+ emitEvent("sourceWarning", it)
196
+ }
197
+
198
+ /**
199
+ * Start listening and emitting player events as bubbling events to the js side.
200
+ */
201
+ fun startBubblingEvents() {
202
+ player?.on(onEvent)
203
+ player?.on(onPlayerError)
204
+ player?.on(onPlayerWarning)
205
+ player?.on(onDestroy)
206
+ player?.on(onMuted)
207
+ player?.on(onUnmuted)
208
+ player?.on(onReady)
209
+ player?.on(onPaused)
210
+ player?.on(onPlay)
211
+ player?.on(onPlaying)
212
+ player?.on(onPlaybackFinished)
213
+ player?.on(onSeek)
214
+ player?.on(onSeeked)
215
+ player?.on(onTimeChanged)
216
+ player?.on(onSourceLoad)
217
+ player?.on(onSourceLoaded)
218
+ player?.on(onSourceUnloaded)
219
+ player?.on(onSourceError)
220
+ player?.on(onSourceWarning)
221
+ }
222
+
223
+ /**
224
+ * Stop listening for player events and cease to emit bubbling events.
225
+ */
226
+ fun stopBubblingEvents() {
227
+ player?.off(onEvent)
228
+ player?.off(onPlayerError)
229
+ player?.off(onPlayerWarning)
230
+ player?.off(onDestroy)
231
+ player?.off(onMuted)
232
+ player?.off(onUnmuted)
233
+ player?.off(onReady)
234
+ player?.off(onPaused)
235
+ player?.off(onPlay)
236
+ player?.off(onPlaying)
237
+ player?.off(onPlaybackFinished)
238
+ player?.off(onSeek)
239
+ player?.off(onSeeked)
240
+ player?.off(onTimeChanged)
241
+ player?.off(onSourceLoad)
242
+ player?.off(onSourceLoaded)
243
+ player?.off(onSourceUnloaded)
244
+ player?.off(onSourceError)
245
+ player?.off(onSourceWarning)
246
+ }
247
+
248
+ /**
249
+ * Emits a bubbling event with payload to js.
250
+ * @param event Native event name.
251
+ * @param json Optional js object to be sent as payload.
252
+ */
253
+ private inline fun <reified E : Event> emitEvent(name: String, event: E) {
254
+ val payload = if (event is PlayerEvent) {
255
+ JsonConverter.fromPlayerEvent(event)
256
+ } else {
257
+ JsonConverter.fromSourceEvent(event as SourceEvent)
258
+ }
259
+ val reactContext = context as ReactContext
260
+ reactContext
261
+ .getJSModule(RCTEventEmitter::class.java)
262
+ .receiveEvent(id, name, payload)
263
+ }
264
+ }
@@ -0,0 +1,139 @@
1
+ package com.bitmovin.player.reactnative
2
+
3
+ import android.view.ViewGroup.LayoutParams
4
+ import com.bitmovin.player.PlayerView
5
+ import com.facebook.react.bridge.*
6
+ import com.facebook.react.uimanager.SimpleViewManager
7
+ import com.facebook.react.uimanager.ThemedReactContext
8
+ import com.facebook.react.uimanager.UIManagerModule
9
+
10
+ class RNPlayerViewManager(private val context: ReactApplicationContext) : SimpleViewManager<RNPlayerView>() {
11
+ /**
12
+ * Native component functions.
13
+ */
14
+ enum class Commands {
15
+ ATTACH_PLAYER,
16
+ DETACH_PLAYER,
17
+ }
18
+
19
+ /**
20
+ * Exported module name to JS.
21
+ */
22
+ override fun getName() = "NativePlayerView"
23
+
24
+ /**
25
+ * The component's native view factory. RN calls this method multiple times
26
+ * for each component instance.
27
+ */
28
+ override fun createViewInstance(reactContext: ThemedReactContext) = RNPlayerView(context)
29
+
30
+ /**
31
+ * A mapping between a event native identifier and its bubbled version that will
32
+ * be accessed from React.
33
+ */
34
+ private val bubblingEventsMapping: Map<String, String> = mapOf(
35
+ "event" to "onEvent",
36
+ "playerError" to "onPlayerError",
37
+ "playerWarning" to "onPlayerWarning",
38
+ "destroy" to "onDestroy",
39
+ "muted" to "onMuted",
40
+ "unmuted" to "onUnmuted",
41
+ "ready" to "onReady",
42
+ "paused" to "onPaused",
43
+ "play" to "onPlay",
44
+ "playing" to "onPlaying",
45
+ "playbackFinished" to "onPlaybackFinished",
46
+ "seek" to "onSeek",
47
+ "seeked" to "onSeeked",
48
+ "timeChanged" to "onTimeChanged",
49
+ "sourceLoad" to "onSourceLoad",
50
+ "sourceLoaded" to "onSourceLoaded",
51
+ "sourceUnloaded" to "onSourceUnloaded",
52
+ "sourceError" to "onSourceError",
53
+ "sourceWarning" to "onSourceWarning",
54
+ )
55
+
56
+ /**
57
+ * Component's event registry. Bubbling events are directly mapped to react props. No
58
+ * need to use proxy functions or `NativeEventEmitter`.
59
+ * @return map between event names (sent from native code) to js props.
60
+ */
61
+ override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> =
62
+ bubblingEventsMapping.entries.associate {
63
+ it.key to mapOf(
64
+ "phasedRegistrationNames" to mapOf("bubbled" to it.value)
65
+ )
66
+ }.toMutableMap()
67
+
68
+ /**
69
+ * Component's command registry. They enable granular control over
70
+ * instances of a certain native component from js and give the ability
71
+ * to call 'functions' on them.
72
+ * @return map between names (used in js) and command ids (used in native code).
73
+ */
74
+ override fun getCommandsMap(): MutableMap<String, Int> = mutableMapOf(
75
+ "attachPlayer" to Commands.ATTACH_PLAYER.ordinal,
76
+ "detachPlayer" to Commands.DETACH_PLAYER.ordinal,
77
+ )
78
+
79
+ /**
80
+ * Callback triggered in response to command dispatches from the js side.
81
+ * @param root Root native view of the targeted component.
82
+ * @param commandId Command number identifier. It's a number even though RN sends it as a string.
83
+ * @param args Arguments list sent from the js side.
84
+ */
85
+ override fun receiveCommand(view: RNPlayerView, commandId: String?, args: ReadableArray?) {
86
+ super.receiveCommand(view, commandId, args)
87
+ commandId?.toInt()?.let {
88
+ when (it) {
89
+ Commands.ATTACH_PLAYER.ordinal -> attachPlayer(view, args?.getString(1))
90
+ Commands.DETACH_PLAYER.ordinal -> detachPlayer(view, args?.getString(1))
91
+ else -> {}
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Set the `Player` instance for the target view using `playerId`.
98
+ * @param view Target `RNPlayerView`.
99
+ * @param playerId `Player` instance id inside `PlayerModule`'s registry.
100
+ */
101
+ private fun attachPlayer(view: RNPlayerView, playerId: String?) {
102
+ uiManager()?.addUIBlock {
103
+ val player = getPlayerModule()?.getPlayer(playerId)
104
+ if (view.playerView != null) {
105
+ view.player = player
106
+ } else {
107
+ val playerView = PlayerView(context, player)
108
+ playerView.layoutParams = LayoutParams(
109
+ LayoutParams.MATCH_PARENT,
110
+ LayoutParams.MATCH_PARENT)
111
+ view.addPlayerView(playerView)
112
+ }
113
+ view.startBubblingEvents()
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Stop sending `Player` bubbling events from `PlayerView`.
119
+ * @param view Target `RNPlayerView`.
120
+ * @param playerId `Player` instance id inside `PlayerModule`'s registry.
121
+ */
122
+ private fun detachPlayer(view: RNPlayerView, playerId: String?) {
123
+ uiManager()?.addUIBlock {
124
+ view.stopBubblingEvents()
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Helper function that gets the instantiated `PlayerModule` from modules registry.
130
+ */
131
+ private fun getPlayerModule(): PlayerModule? =
132
+ context.getNativeModule(PlayerModule::class.java)
133
+
134
+ /**
135
+ * Helper function that returns the initialized `UIManager` instance.
136
+ */
137
+ private fun uiManager(): UIManagerModule? =
138
+ context.getNativeModule(UIManagerModule::class.java)
139
+ }
@@ -0,0 +1,33 @@
1
+ package com.bitmovin.player.reactnative
2
+
3
+ import android.view.View
4
+ import com.facebook.react.ReactPackage
5
+ import com.facebook.react.bridge.NativeModule
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.uimanager.ReactShadowNode
8
+ import com.facebook.react.uimanager.ViewManager
9
+
10
+ /**
11
+ * React package registry.
12
+ */
13
+ class RNPlayerViewPackage : ReactPackage {
14
+ /**
15
+ * Register `RNPlayerViewManager` as a base react native module. This allows
16
+ * accessing methods on `NativePlayerView` on the js side.
17
+ */
18
+ override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
19
+ return mutableListOf(
20
+ PlayerModule(reactContext),
21
+ RNPlayerViewManager(reactContext),
22
+ )
23
+ }
24
+
25
+ /**
26
+ * Register `RNPlayerViewManager` as a view manager. This allows creating
27
+ * native component instances with `<NativePlayerView {...} />` on the js
28
+ * side.
29
+ */
30
+ override fun createViewManagers(reactContext: ReactApplicationContext): MutableList<ViewManager<out View, out ReactShadowNode<*>>> {
31
+ return mutableListOf(RNPlayerViewManager(reactContext))
32
+ }
33
+ }
@@ -0,0 +1,162 @@
1
+ package com.bitmovin.player.reactnative.converter
2
+
3
+ import com.bitmovin.player.api.PlayerConfig
4
+ import com.bitmovin.player.api.event.PlayerEvent
5
+ import com.bitmovin.player.api.event.SourceEvent
6
+ import com.bitmovin.player.api.event.data.SeekPosition
7
+ import com.bitmovin.player.api.source.Source
8
+ import com.bitmovin.player.api.source.SourceConfig
9
+ import com.bitmovin.player.api.source.SourceType
10
+ import com.bitmovin.player.reactnative.extensions.getName
11
+ import com.facebook.react.bridge.*
12
+
13
+ /**
14
+ * Helper class to gather all conversion methods between JS -> Native objects.
15
+ */
16
+ class JsonConverter {
17
+ companion object {
18
+ /**
19
+ * Converts an arbitrary `json` to `PlayerConfig`.
20
+ * @param json JS object representing the `PlayerConfig`.
21
+ * @return The generated `PlayerConfig` if successful, `null` otherwise.
22
+ */
23
+ @JvmStatic
24
+ fun toPlayerConfig(json: ReadableMap?): PlayerConfig? {
25
+ if (json != null && json.hasKey("licenseKey")) {
26
+ return PlayerConfig(key = json.getString("licenseKey"))
27
+ }
28
+ return PlayerConfig()
29
+ }
30
+
31
+ /**
32
+ * Converts an arbitrary `json` to `SourceConfig`.
33
+ * @param json JS object representing the `SourceConfig`.
34
+ * @return The generated `SourceConfig` if successful, `null` otherwise.
35
+ */
36
+ @JvmStatic
37
+ fun toSourceConfig(json: ReadableMap?): SourceConfig? {
38
+ val url = json?.getString("url")
39
+ val type = json?.getString("type")
40
+ if (json == null || url == null || type == null) {
41
+ return null
42
+ }
43
+ val config = SourceConfig(url, toSourceType(type))
44
+ config.title = json.getString("title")
45
+ config.posterSource = json.getString("poster")
46
+ if (json.hasKey("isPosterPersistent")) {
47
+ config.isPosterPersistent = json.getBoolean("isPosterPersistent")
48
+ }
49
+ return config
50
+ }
51
+
52
+ /**
53
+ * Converts an arbitrary `json` to `SourceType`.
54
+ * @param json JS string representing the `SourceType`.
55
+ * @return The generated `SourceType` if successful or `SourceType.Dash` otherwise.
56
+ */
57
+ @JvmStatic
58
+ fun toSourceType(json: String?): SourceType = when (json) {
59
+ "dash" -> SourceType.Dash
60
+ "hls" -> SourceType.Hls
61
+ "smooth" -> SourceType.Smooth
62
+ "progressive" -> SourceType.Progressive
63
+ else -> SourceType.Dash
64
+ }
65
+
66
+ /**
67
+ * Converts any given `Source` object into its `json` representation.
68
+ * @param source `Source` object to be converted.
69
+ * @return The `json` representation of the given `Source`.
70
+ */
71
+ @JvmStatic
72
+ fun fromSource(source: Source?): WritableMap? {
73
+ if (source == null) {
74
+ return null
75
+ }
76
+ val json = Arguments.createMap()
77
+ json.putDouble("duration", source.duration)
78
+ json.putBoolean("isActive", source.isActive)
79
+ json.putBoolean("isAttachedToPlayer", source.isAttachedToPlayer)
80
+ json.putInt("loadingState", source.loadingState.ordinal)
81
+ json.putNull("metadata")
82
+ return json
83
+ }
84
+
85
+ /**
86
+ * Converts any given `SeekPosition` object into its `json` representation.
87
+ * @param seekPosition `SeekPosition` object to be converted.
88
+ * @return The `json` representation of the given `SeekPosition`.
89
+ */
90
+ @JvmStatic
91
+ fun fromSeekPosition(seekPosition: SeekPosition): WritableMap? {
92
+ val json = Arguments.createMap()
93
+ json.putDouble("time", seekPosition.time)
94
+ json.putMap("source", fromSource(seekPosition.source))
95
+ return json
96
+ }
97
+
98
+ /**
99
+ * Converts any given `SourceEvent` object into its `json` representation.
100
+ * @param event `SourceEvent` object to be converted.
101
+ * @return The `json` representation of the given `SourceEvent`.
102
+ */
103
+ @JvmStatic
104
+ fun fromSourceEvent(event: SourceEvent): WritableMap? {
105
+ val json = Arguments.createMap()
106
+ json.putString("name", event.getName())
107
+ json.putDouble("timestamp", event.timestamp.toDouble())
108
+ if (event is SourceEvent.Load) {
109
+ json.putMap("source", fromSource(event.source))
110
+ }
111
+ if (event is SourceEvent.Loaded) {
112
+ json.putMap("source", fromSource(event.source))
113
+ }
114
+ if (event is SourceEvent.Error) {
115
+ json.putInt("code", event.code.value)
116
+ json.putString("message", event.message)
117
+ }
118
+ if (event is SourceEvent.Warning) {
119
+ json.putInt("code", event.code.value)
120
+ json.putString("message", event.message)
121
+ }
122
+ return json
123
+ }
124
+
125
+ /**
126
+ * Converts any given `PlayerEvent` object into its `json` representation.
127
+ * @param event `PlayerEvent` object to be converted.
128
+ * @return The `json` representation of given `PlayerEvent`.
129
+ */
130
+ @JvmStatic
131
+ fun fromPlayerEvent(event: PlayerEvent): WritableMap? {
132
+ val json = Arguments.createMap()
133
+ json.putString("name", event.getName())
134
+ json.putDouble("timestamp", event.timestamp.toDouble())
135
+ if (event is PlayerEvent.Error) {
136
+ json.putInt("code", event.code.value)
137
+ json.putString("message", event.message)
138
+ }
139
+ if (event is PlayerEvent.Warning) {
140
+ json.putInt("code", event.code.value)
141
+ json.putString("message", event.message)
142
+ }
143
+ if (event is PlayerEvent.Play) {
144
+ json.putDouble("time", event.time)
145
+ }
146
+ if (event is PlayerEvent.Playing) {
147
+ json.putDouble("time", event.time)
148
+ }
149
+ if (event is PlayerEvent.Paused) {
150
+ json.putDouble("time", event.time)
151
+ }
152
+ if (event is PlayerEvent.TimeChanged) {
153
+ json.putDouble("currentTime", event.time)
154
+ }
155
+ if (event is PlayerEvent.Seek) {
156
+ json.putMap("from", fromSeekPosition(event.from))
157
+ json.putMap("to", fromSeekPosition(event.to))
158
+ }
159
+ return json
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,15 @@
1
+ package com.bitmovin.player.reactnative.extensions
2
+
3
+ import com.bitmovin.player.api.event.PlayerEvent
4
+ import com.bitmovin.player.api.event.SourceEvent
5
+
6
+ fun PlayerEvent.getName(): String {
7
+ if (this is PlayerEvent.Error || this is PlayerEvent.Warning) {
8
+ return "onPlayer${this.javaClass.simpleName}"
9
+ }
10
+ return "on${this.javaClass.simpleName}"
11
+ }
12
+
13
+ fun SourceEvent.getName(): String {
14
+ return "onSource${this.javaClass.simpleName}"
15
+ }