bitmovin-player-react-native 0.3.1 → 0.5.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/README.md +486 -24
- package/RNBitmovinPlayer.podspec +5 -1
- package/android/build.gradle +8 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/AnalyticsModule.kt +154 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/DrmModule.kt +4 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +41 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +318 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +70 -9
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +3 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/SourceModule.kt +4 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/UuidModule.kt +3 -1
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +389 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/Any.kt +27 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReactContextExtension.kt +8 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReadableArray.kt +19 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/String.kt +8 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/WritableMap.kt +19 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/FullscreenHandlerBridge.kt +37 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/FullscreenHandlerModule.kt +73 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/RNPictureInPictureHandler.kt +191 -0
- package/ios/AnalyticsModule.m +14 -0
- package/ios/AnalyticsModule.swift +180 -0
- package/ios/AudioSessionModule.m +10 -0
- package/ios/AudioSessionModule.swift +65 -0
- package/ios/Event+JSON.swift +134 -0
- package/ios/FullscreenHandlerBridge.swift +33 -0
- package/ios/FullscreenHandlerModule.m +9 -0
- package/ios/FullscreenHandlerModule.swift +71 -0
- package/ios/PlayerModule.m +6 -0
- package/ios/PlayerModule.swift +44 -0
- package/ios/RCTConvert+BitmovinPlayer.swift +382 -0
- package/ios/RNPlayerView+PlayerListener.swift +56 -0
- package/ios/RNPlayerView+UserInterfaceListener.swift +35 -0
- package/ios/RNPlayerView.swift +22 -0
- package/ios/RNPlayerViewManager.m +24 -1
- package/ios/RNPlayerViewManager.swift +23 -1
- package/lib/index.d.ts +1013 -150
- package/lib/index.js +251 -48
- package/lib/index.mjs +231 -34
- package/package.json +1 -1
- package/src/advertising.ts +155 -0
- package/src/analytics/collector.ts +97 -0
- package/src/analytics/config.ts +218 -0
- package/src/analytics/index.ts +2 -0
- package/src/audioSession.ts +47 -0
- package/src/components/PlayerView/events.ts +49 -3
- package/src/components/PlayerView/index.tsx +68 -11
- package/src/components/PlayerView/native.ts +4 -1
- package/src/events.ts +255 -0
- package/src/index.ts +4 -0
- package/src/media.ts +33 -0
- package/src/player.ts +57 -1
- package/src/source.ts +4 -0
- package/src/styleConfig.ts +87 -0
- package/src/ui/fullscreenhandler.ts +19 -0
- package/src/ui/fullscreenhandlerbridge.ts +59 -0
|
@@ -4,29 +4,54 @@ import android.os.Handler
|
|
|
4
4
|
import android.os.Looper
|
|
5
5
|
import android.view.ViewGroup.LayoutParams
|
|
6
6
|
import com.bitmovin.player.PlayerView
|
|
7
|
+
import com.bitmovin.player.reactnative.extensions.getModule
|
|
8
|
+
import com.bitmovin.player.reactnative.ui.FullscreenHandlerBridge
|
|
9
|
+
import com.bitmovin.player.reactnative.ui.FullscreenHandlerModule
|
|
10
|
+
import com.bitmovin.player.reactnative.ui.RNPictureInPictureHandler
|
|
7
11
|
import com.facebook.react.bridge.*
|
|
12
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
8
13
|
import com.facebook.react.uimanager.SimpleViewManager
|
|
9
14
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
10
15
|
|
|
16
|
+
private const val MODULE_NAME = "NativePlayerView"
|
|
17
|
+
|
|
18
|
+
@ReactModule(name = MODULE_NAME)
|
|
11
19
|
class RNPlayerViewManager(private val context: ReactApplicationContext) : SimpleViewManager<RNPlayerView>() {
|
|
12
20
|
/**
|
|
13
21
|
* Native component functions.
|
|
14
22
|
*/
|
|
15
23
|
enum class Commands {
|
|
16
24
|
ATTACH_PLAYER,
|
|
25
|
+
ATTACH_FULLSCREEN_BRIDGE
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
/**
|
|
20
29
|
* Exported module name to JS.
|
|
21
30
|
*/
|
|
22
|
-
override fun getName() =
|
|
31
|
+
override fun getName() = MODULE_NAME
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* React Native PiP handler instance. It can be subclassed, then set from other native
|
|
35
|
+
* modules in case a full-custom implementation is needed. A default implementation is provided
|
|
36
|
+
* out-of-the-box.
|
|
37
|
+
*/
|
|
38
|
+
var pictureInPictureHandler = RNPictureInPictureHandler(context)
|
|
23
39
|
|
|
24
40
|
/**
|
|
25
|
-
* The component's native view factory. RN
|
|
41
|
+
* The component's native view factory. RN may call this method multiple times
|
|
26
42
|
* for each component instance.
|
|
27
43
|
*/
|
|
28
44
|
override fun createViewInstance(reactContext: ThemedReactContext) = RNPlayerView(context)
|
|
29
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Called when the component's view gets detached from the view hierarchy. Useful to perform
|
|
48
|
+
* cleanups.
|
|
49
|
+
*/
|
|
50
|
+
override fun onDropViewInstance(view: RNPlayerView) {
|
|
51
|
+
super.onDropViewInstance(view)
|
|
52
|
+
view.dispose()
|
|
53
|
+
}
|
|
54
|
+
|
|
30
55
|
/**
|
|
31
56
|
* A mapping between a event native identifier and its bubbled version that will
|
|
32
57
|
* be accessed from React.
|
|
@@ -45,6 +70,8 @@ class RNPlayerViewManager(private val context: ReactApplicationContext) : Simple
|
|
|
45
70
|
"playbackFinished" to "onPlaybackFinished",
|
|
46
71
|
"seek" to "onSeek",
|
|
47
72
|
"seeked" to "onSeeked",
|
|
73
|
+
"stallStarted" to "onStallStarted",
|
|
74
|
+
"stallEnded" to "onStallEnded",
|
|
48
75
|
"timeChanged" to "onTimeChanged",
|
|
49
76
|
"sourceLoad" to "onSourceLoad",
|
|
50
77
|
"sourceLoaded" to "onSourceLoaded",
|
|
@@ -54,6 +81,25 @@ class RNPlayerViewManager(private val context: ReactApplicationContext) : Simple
|
|
|
54
81
|
"subtitleAdded" to "onSubtitleAdded",
|
|
55
82
|
"subtitleChanged" to "onSubtitleChanged",
|
|
56
83
|
"subtitleRemoved" to "onSubtitleRemoved",
|
|
84
|
+
"pictureInPictureAvailabilityChanged" to "onPictureInPictureAvailabilityChanged",
|
|
85
|
+
"pictureInPictureEnter" to "onPictureInPictureEnter",
|
|
86
|
+
"pictureInPictureExit" to "onPictureInPictureExit",
|
|
87
|
+
"adBreakFinished" to "onAdBreakFinished",
|
|
88
|
+
"adBreakStarted" to "onAdBreakStarted",
|
|
89
|
+
"adClicked" to "onAdClicked",
|
|
90
|
+
"adError" to "onAdError",
|
|
91
|
+
"adFinished" to "onAdFinished",
|
|
92
|
+
"adManifestLoad" to "onAdManifestLoad",
|
|
93
|
+
"adManifestLoaded" to "onAdManifestLoaded",
|
|
94
|
+
"adQuartile" to "onAdQuartile",
|
|
95
|
+
"adScheduled" to "onAdScheduled",
|
|
96
|
+
"adSkipped" to "onAdSkipped",
|
|
97
|
+
"adStarted" to "onAdStarted",
|
|
98
|
+
"videoPlaybackQualityChanged" to "onVideoPlaybackQualityChanged",
|
|
99
|
+
"fullscreenEnabled" to "onFullscreenEnabled",
|
|
100
|
+
"fullscreenDisabled" to "onFullscreenDisabled",
|
|
101
|
+
"fullscreenEnter" to "onFullscreenEnter",
|
|
102
|
+
"fullscreenExit" to "onFullscreenExit",
|
|
57
103
|
)
|
|
58
104
|
|
|
59
105
|
/**
|
|
@@ -75,7 +121,8 @@ class RNPlayerViewManager(private val context: ReactApplicationContext) : Simple
|
|
|
75
121
|
* @return map between names (used in js) and command ids (used in native code).
|
|
76
122
|
*/
|
|
77
123
|
override fun getCommandsMap(): MutableMap<String, Int> = mutableMapOf(
|
|
78
|
-
"attachPlayer" to Commands.ATTACH_PLAYER.ordinal
|
|
124
|
+
"attachPlayer" to Commands.ATTACH_PLAYER.ordinal,
|
|
125
|
+
"attachFullscreenBridge" to Commands.ATTACH_FULLSCREEN_BRIDGE.ordinal,
|
|
79
126
|
)
|
|
80
127
|
|
|
81
128
|
/**
|
|
@@ -88,36 +135,50 @@ class RNPlayerViewManager(private val context: ReactApplicationContext) : Simple
|
|
|
88
135
|
super.receiveCommand(view, commandId, args)
|
|
89
136
|
commandId?.toInt()?.let {
|
|
90
137
|
when (it) {
|
|
91
|
-
Commands.ATTACH_PLAYER.ordinal -> attachPlayer(view, args?.getString(1))
|
|
138
|
+
Commands.ATTACH_PLAYER.ordinal -> attachPlayer(view, args?.getString(1), args?.getMap(2))
|
|
139
|
+
Commands.ATTACH_FULLSCREEN_BRIDGE.ordinal -> args?.getString(1)?.let { fullscreenBridgeId ->
|
|
140
|
+
attachFullscreenBridge(view, fullscreenBridgeId)
|
|
141
|
+
}
|
|
92
142
|
else -> {}
|
|
93
143
|
}
|
|
94
144
|
}
|
|
95
145
|
}
|
|
96
146
|
|
|
147
|
+
private fun attachFullscreenBridge(view: RNPlayerView, fullscreenBridgeId: NativeId) {
|
|
148
|
+
Handler(Looper.getMainLooper()).post {
|
|
149
|
+
view.playerView?.setFullscreenHandler(
|
|
150
|
+
context.getModule<FullscreenHandlerModule>()?.getInstance(fullscreenBridgeId)
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
97
155
|
/**
|
|
98
156
|
* Set the `Player` instance for the target view using `playerId`.
|
|
99
157
|
* @param view Target `RNPlayerView`.
|
|
100
158
|
* @param playerId `Player` instance id inside `PlayerModule`'s registry.
|
|
101
159
|
*/
|
|
102
|
-
private fun attachPlayer(view: RNPlayerView, playerId: NativeId?) {
|
|
160
|
+
private fun attachPlayer(view: RNPlayerView, playerId: NativeId?, playerConfig: ReadableMap?) {
|
|
103
161
|
Handler(Looper.getMainLooper()).post {
|
|
104
162
|
val player = getPlayerModule()?.getPlayer(playerId)
|
|
163
|
+
playerConfig?.getMap("playbackConfig")?.getBoolean("isPictureInPictureEnabled")?.let {
|
|
164
|
+
pictureInPictureHandler.isPictureInPictureEnabled = it
|
|
165
|
+
view.pictureInPictureHandler = pictureInPictureHandler
|
|
166
|
+
}
|
|
105
167
|
if (view.playerView != null) {
|
|
106
168
|
view.player = player
|
|
107
169
|
} else {
|
|
108
170
|
val playerView = PlayerView(context, player)
|
|
109
171
|
playerView.layoutParams = LayoutParams(
|
|
110
172
|
LayoutParams.MATCH_PARENT,
|
|
111
|
-
LayoutParams.MATCH_PARENT
|
|
173
|
+
LayoutParams.MATCH_PARENT
|
|
174
|
+
)
|
|
112
175
|
view.addPlayerView(playerView)
|
|
113
176
|
}
|
|
114
|
-
view.startBubblingEvents()
|
|
115
177
|
}
|
|
116
178
|
}
|
|
117
179
|
|
|
118
180
|
/**
|
|
119
181
|
* Helper function that gets the instantiated `PlayerModule` from modules registry.
|
|
120
182
|
*/
|
|
121
|
-
private fun getPlayerModule(): PlayerModule? =
|
|
122
|
-
context.getNativeModule(PlayerModule::class.java)
|
|
183
|
+
private fun getPlayerModule(): PlayerModule? = context.getModule()
|
|
123
184
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.bitmovin.player.reactnative
|
|
2
2
|
|
|
3
3
|
import android.view.View
|
|
4
|
+
import com.bitmovin.player.reactnative.ui.FullscreenHandlerModule
|
|
4
5
|
import com.facebook.react.ReactPackage
|
|
5
6
|
import com.facebook.react.bridge.NativeModule
|
|
6
7
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
@@ -21,7 +22,9 @@ class RNPlayerViewPackage : ReactPackage {
|
|
|
21
22
|
PlayerModule(reactContext),
|
|
22
23
|
SourceModule(reactContext),
|
|
23
24
|
DrmModule(reactContext),
|
|
25
|
+
AnalyticsModule(reactContext),
|
|
24
26
|
RNPlayerViewManager(reactContext),
|
|
27
|
+
FullscreenHandlerModule(reactContext)
|
|
25
28
|
)
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -6,7 +6,9 @@ import com.facebook.react.bridge.*
|
|
|
6
6
|
import com.facebook.react.module.annotations.ReactModule
|
|
7
7
|
import com.facebook.react.uimanager.UIManagerModule
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
private const val MODULE_NAME = "SourceModule"
|
|
10
|
+
|
|
11
|
+
@ReactModule(name = MODULE_NAME)
|
|
10
12
|
class SourceModule(private val context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
|
11
13
|
/**
|
|
12
14
|
* In-memory mapping from `nativeId`s to `Source` instances.
|
|
@@ -16,10 +18,7 @@ class SourceModule(private val context: ReactApplicationContext) : ReactContextB
|
|
|
16
18
|
/**
|
|
17
19
|
* JS exported module name.
|
|
18
20
|
*/
|
|
19
|
-
|
|
20
|
-
const val name = "SourceModule"
|
|
21
|
-
}
|
|
22
|
-
override fun getName() = SourceModule.name
|
|
21
|
+
override fun getName() = MODULE_NAME
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* Fetches the `Source` instance associated with `nativeId` from internal sources.
|
|
@@ -5,11 +5,13 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
|
5
5
|
import com.facebook.react.bridge.ReactMethod
|
|
6
6
|
import java.util.*
|
|
7
7
|
|
|
8
|
+
private const val MODULE_NAME = "UuidModule"
|
|
9
|
+
|
|
8
10
|
class UuidModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
|
9
11
|
/**
|
|
10
12
|
* Exported JS module name.
|
|
11
13
|
*/
|
|
12
|
-
override fun getName() =
|
|
14
|
+
override fun getName() = MODULE_NAME
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Synchronously generate a random UUIDv4.
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
package com.bitmovin.player.reactnative.converter
|
|
2
2
|
|
|
3
|
+
import com.bitmovin.analytics.BitmovinAnalyticsConfig
|
|
4
|
+
import com.bitmovin.analytics.data.CustomData
|
|
3
5
|
import com.bitmovin.player.api.DeviceDescription.DeviceName
|
|
4
6
|
import com.bitmovin.player.api.DeviceDescription.ModelName
|
|
5
7
|
import com.bitmovin.player.api.PlaybackConfig
|
|
6
8
|
import com.bitmovin.player.api.PlayerConfig
|
|
7
9
|
import com.bitmovin.player.api.TweaksConfig
|
|
10
|
+
import com.bitmovin.player.api.advertising.*
|
|
8
11
|
import com.bitmovin.player.api.drm.WidevineConfig
|
|
9
12
|
import com.bitmovin.player.api.event.PlayerEvent
|
|
10
13
|
import com.bitmovin.player.api.event.SourceEvent
|
|
11
14
|
import com.bitmovin.player.api.event.data.SeekPosition
|
|
12
15
|
import com.bitmovin.player.api.media.subtitle.SubtitleTrack
|
|
16
|
+
import com.bitmovin.player.api.media.thumbnail.ThumbnailTrack
|
|
17
|
+
import com.bitmovin.player.api.media.video.quality.VideoQuality
|
|
13
18
|
import com.bitmovin.player.api.source.Source
|
|
14
19
|
import com.bitmovin.player.api.source.SourceConfig
|
|
15
20
|
import com.bitmovin.player.api.source.SourceType
|
|
21
|
+
import com.bitmovin.player.api.ui.ScalingMode
|
|
22
|
+
import com.bitmovin.player.api.ui.StyleConfig
|
|
16
23
|
import com.bitmovin.player.reactnative.extensions.getName
|
|
24
|
+
import com.bitmovin.player.reactnative.extensions.putInt
|
|
25
|
+
import com.bitmovin.player.reactnative.extensions.putDouble
|
|
17
26
|
import com.bitmovin.player.reactnative.extensions.toList
|
|
27
|
+
import com.bitmovin.player.reactnative.extensions.toReadableArray
|
|
28
|
+
import com.bitmovin.player.reactnative.extensions.getProperty
|
|
29
|
+
import com.bitmovin.player.reactnative.extensions.setProperty
|
|
18
30
|
import com.facebook.react.bridge.*
|
|
19
31
|
import java.util.UUID
|
|
20
32
|
|
|
@@ -41,11 +53,21 @@ class JsonConverter {
|
|
|
41
53
|
playerConfig.playbackConfig = it
|
|
42
54
|
}
|
|
43
55
|
}
|
|
56
|
+
if (json.hasKey("styleConfig")) {
|
|
57
|
+
toStyleConfig(json.getMap("styleConfig"))?.let {
|
|
58
|
+
playerConfig.styleConfig = it
|
|
59
|
+
}
|
|
60
|
+
}
|
|
44
61
|
if (json.hasKey("tweaksConfig")) {
|
|
45
62
|
toTweaksConfig(json.getMap("tweaksConfig"))?.let {
|
|
46
63
|
playerConfig.tweaksConfig = it
|
|
47
64
|
}
|
|
48
65
|
}
|
|
66
|
+
if (json.hasKey("advertisingConfig")) {
|
|
67
|
+
toAdvertisingConfig(json.getMap("advertisingConfig"))?.let {
|
|
68
|
+
playerConfig.advertisingConfig = it
|
|
69
|
+
}
|
|
70
|
+
}
|
|
49
71
|
return playerConfig
|
|
50
72
|
}
|
|
51
73
|
|
|
@@ -72,6 +94,47 @@ class JsonConverter {
|
|
|
72
94
|
return playbackConfig
|
|
73
95
|
}
|
|
74
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Converts any JS object into a `StyleConfig` object.
|
|
99
|
+
* @param json JS object representing the `StyleConfig`.
|
|
100
|
+
* @return The generated `StyleConfig` if successful, `null` otherwise.
|
|
101
|
+
*/
|
|
102
|
+
@JvmStatic
|
|
103
|
+
fun toStyleConfig(json: ReadableMap?): StyleConfig? {
|
|
104
|
+
if (json == null) {
|
|
105
|
+
return null
|
|
106
|
+
}
|
|
107
|
+
val styleConfig = StyleConfig()
|
|
108
|
+
if (json.hasKey("isUiEnabled")) {
|
|
109
|
+
styleConfig.isUiEnabled = json.getBoolean("isUiEnabled")
|
|
110
|
+
}
|
|
111
|
+
if (json.hasKey("playerUiCss")) {
|
|
112
|
+
val playerUiCss = json.getString("playerUiCss")
|
|
113
|
+
if (!playerUiCss.isNullOrEmpty()) {
|
|
114
|
+
styleConfig.playerUiCss = playerUiCss
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (json.hasKey("supplementalPlayerUiCss")) {
|
|
118
|
+
val supplementalPlayerUiCss = json.getString("supplementalPlayerUiCss")
|
|
119
|
+
if (!supplementalPlayerUiCss.isNullOrEmpty()) {
|
|
120
|
+
styleConfig.supplementalPlayerUiCss = supplementalPlayerUiCss
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (json.hasKey("playerUiJs")) {
|
|
124
|
+
val playerUiJs = json.getString("playerUiJs")
|
|
125
|
+
if (!playerUiJs.isNullOrEmpty()) {
|
|
126
|
+
styleConfig.playerUiJs = playerUiJs
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (json.hasKey("scalingMode")) {
|
|
130
|
+
val scalingMode = json.getString("scalingMode")
|
|
131
|
+
if (!scalingMode.isNullOrEmpty()) {
|
|
132
|
+
styleConfig.scalingMode = ScalingMode.valueOf(scalingMode)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return styleConfig
|
|
136
|
+
}
|
|
137
|
+
|
|
75
138
|
/**
|
|
76
139
|
* Converts any JS object into a `TweaksConfig` object.
|
|
77
140
|
* @param json JS object representing the `TweaksConfig`.
|
|
@@ -124,6 +187,54 @@ class JsonConverter {
|
|
|
124
187
|
return tweaksConfig
|
|
125
188
|
}
|
|
126
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Converts any JS object into an `AdvertisingConfig` object.
|
|
192
|
+
* @param json JS object representing the `AdvertisingConfig`.
|
|
193
|
+
* @return The generated `AdvertisingConfig` if successful, `null` otherwise.
|
|
194
|
+
*/
|
|
195
|
+
@JvmStatic
|
|
196
|
+
fun toAdvertisingConfig(json: ReadableMap?): AdvertisingConfig? = json?.getArray("schedule")
|
|
197
|
+
?.toList<ReadableMap>()
|
|
198
|
+
?.mapNotNull(::toAdItem)
|
|
199
|
+
?.let { AdvertisingConfig(it) }
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Converts any JS object into an `AdItem` object.
|
|
203
|
+
* @param json JS object representing the `AdItem`.
|
|
204
|
+
* @return The generated `AdItem` if successful, `null` otherwise.
|
|
205
|
+
*/
|
|
206
|
+
@JvmStatic
|
|
207
|
+
fun toAdItem(json: ReadableMap?): AdItem? {
|
|
208
|
+
val sources = json?.getArray("sources")
|
|
209
|
+
?.toList<ReadableMap>()
|
|
210
|
+
?.mapNotNull(::toAdSource)
|
|
211
|
+
?.toTypedArray()
|
|
212
|
+
?: return null
|
|
213
|
+
return AdItem(sources, json?.getString("position") ?: "pre")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Converts any JS object into an `AdSource` object.
|
|
218
|
+
* @param json JS object representing the `AdSource`.
|
|
219
|
+
* @return The generated `AdSource` if successful, `null` otherwise.
|
|
220
|
+
*/
|
|
221
|
+
@JvmStatic
|
|
222
|
+
fun toAdSource(json: ReadableMap?): AdSource? = json?.getString("tag")?.let {
|
|
223
|
+
AdSource(toAdSourceType(json.getString("type")), it)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Converts any JS string into an `AdSourceType` enum value.
|
|
228
|
+
* @param json JS string representing the `AdSourceType`.
|
|
229
|
+
* @return The generated `AdSourceType`.
|
|
230
|
+
*/
|
|
231
|
+
@JvmStatic
|
|
232
|
+
fun toAdSourceType(json: String?): AdSourceType = when (json) {
|
|
233
|
+
"ima" -> AdSourceType.Ima
|
|
234
|
+
"progressive" -> AdSourceType.Progressive
|
|
235
|
+
else -> AdSourceType.Unknown
|
|
236
|
+
}
|
|
237
|
+
|
|
127
238
|
/**
|
|
128
239
|
* Converts an arbitrary `json` to `SourceConfig`.
|
|
129
240
|
* @param json JS object representing the `SourceConfig`.
|
|
@@ -150,6 +261,9 @@ class JsonConverter {
|
|
|
150
261
|
}
|
|
151
262
|
}
|
|
152
263
|
}
|
|
264
|
+
if (json.hasKey("thumbnailTrack")) {
|
|
265
|
+
config.thumbnailTrack = toThumbnailTrack(json.getString("thumbnailTrack"))
|
|
266
|
+
}
|
|
153
267
|
return config
|
|
154
268
|
}
|
|
155
269
|
|
|
@@ -270,6 +384,59 @@ class JsonConverter {
|
|
|
270
384
|
json.putMap("from", fromSeekPosition(event.from))
|
|
271
385
|
json.putMap("to", fromSeekPosition(event.to))
|
|
272
386
|
}
|
|
387
|
+
if (event is PlayerEvent.PictureInPictureAvailabilityChanged) {
|
|
388
|
+
json.putBoolean("isPictureInPictureAvailable", event.isPictureInPictureAvailable)
|
|
389
|
+
}
|
|
390
|
+
if (event is PlayerEvent.AdBreakFinished) {
|
|
391
|
+
json.putMap("adBreak", fromAdBreak(event.adBreak))
|
|
392
|
+
}
|
|
393
|
+
if (event is PlayerEvent.AdBreakStarted) {
|
|
394
|
+
json.putMap("adBreak", fromAdBreak(event.adBreak))
|
|
395
|
+
}
|
|
396
|
+
if (event is PlayerEvent.AdClicked) {
|
|
397
|
+
json.putString("clickThroughUrl", event.clickThroughUrl)
|
|
398
|
+
}
|
|
399
|
+
if (event is PlayerEvent.AdError) {
|
|
400
|
+
json.putInt("code", event.code)
|
|
401
|
+
json.putString("message", event.message)
|
|
402
|
+
json.putMap("adConfig", fromAdConfig(event.adConfig))
|
|
403
|
+
json.putMap("adItem", fromAdItem(event.adItem))
|
|
404
|
+
}
|
|
405
|
+
if (event is PlayerEvent.AdFinished) {
|
|
406
|
+
json.putMap("ad", fromAd(event.ad))
|
|
407
|
+
}
|
|
408
|
+
if (event is PlayerEvent.AdManifestLoad) {
|
|
409
|
+
json.putMap("adBreak", fromAdBreak(event.adBreak))
|
|
410
|
+
json.putMap("adConfig", fromAdConfig(event.adConfig))
|
|
411
|
+
}
|
|
412
|
+
if (event is PlayerEvent.AdManifestLoaded) {
|
|
413
|
+
json.putMap("adBreak", fromAdBreak(event.adBreak))
|
|
414
|
+
json.putMap("adConfig", fromAdConfig(event.adConfig))
|
|
415
|
+
json.putDouble("downloadTime", event.downloadTime.toDouble())
|
|
416
|
+
}
|
|
417
|
+
if (event is PlayerEvent.AdQuartile) {
|
|
418
|
+
json.putString("quartile", fromAdQuartile(event.quartile))
|
|
419
|
+
}
|
|
420
|
+
if (event is PlayerEvent.AdScheduled) {
|
|
421
|
+
json.putInt("numberOfAds", event.numberOfAds)
|
|
422
|
+
}
|
|
423
|
+
if (event is PlayerEvent.AdSkipped) {
|
|
424
|
+
json.putMap("ad", fromAd(event.ad))
|
|
425
|
+
}
|
|
426
|
+
if (event is PlayerEvent.AdStarted) {
|
|
427
|
+
json.putMap("ad", fromAd(event.ad))
|
|
428
|
+
json.putString("clickThroughUrl", event.clickThroughUrl)
|
|
429
|
+
json.putString("clientType", fromAdSourceType(event.clientType))
|
|
430
|
+
json.putDouble("duration", event.duration)
|
|
431
|
+
json.putInt("indexInQueue", event.indexInQueue)
|
|
432
|
+
json.putString("position", event.position)
|
|
433
|
+
json.putDouble("skipOffset", event.skipOffset)
|
|
434
|
+
json.putDouble("timeOffset", event.timeOffset)
|
|
435
|
+
}
|
|
436
|
+
if (event is PlayerEvent.VideoPlaybackQualityChanged) {
|
|
437
|
+
json.putMap("newVideoQuality", fromVideoQuality(event.newVideoQuality))
|
|
438
|
+
json.putMap("oldVideoQuality", fromVideoQuality(event.oldVideoQuality))
|
|
439
|
+
}
|
|
273
440
|
return json
|
|
274
441
|
}
|
|
275
442
|
|
|
@@ -287,6 +454,19 @@ class JsonConverter {
|
|
|
287
454
|
widevineConfig
|
|
288
455
|
}
|
|
289
456
|
|
|
457
|
+
/**
|
|
458
|
+
* Converts an `url` string into a `ThumbnailsTrack`.
|
|
459
|
+
* @param url JS object representing the `ThumbnailsTrack`.
|
|
460
|
+
* @return The generated `ThumbnailsTrack` if successful, `null` otherwise.
|
|
461
|
+
*/
|
|
462
|
+
@JvmStatic
|
|
463
|
+
fun toThumbnailTrack(url: String?): ThumbnailTrack? {
|
|
464
|
+
if (url == null) {
|
|
465
|
+
return null
|
|
466
|
+
}
|
|
467
|
+
return ThumbnailTrack(url);
|
|
468
|
+
}
|
|
469
|
+
|
|
290
470
|
/**
|
|
291
471
|
* Converts an arbitrary `json` into a `SubtitleTrack`.
|
|
292
472
|
* @param json JS object representing the `SubtitleTrack`.
|
|
@@ -378,5 +558,214 @@ class JsonConverter {
|
|
|
378
558
|
}
|
|
379
559
|
return mimeType.split("/").last()
|
|
380
560
|
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Converts any `AdBreak` object into its json representation.
|
|
564
|
+
* @param adBreak `AdBreak` object.
|
|
565
|
+
* @return The produced JS object.
|
|
566
|
+
*/
|
|
567
|
+
@JvmStatic
|
|
568
|
+
fun fromAdBreak(adBreak: AdBreak?): WritableMap? = adBreak?.let {
|
|
569
|
+
Arguments.createMap().apply {
|
|
570
|
+
putArray("ads", it.ads.mapNotNull(::fromAd).toReadableArray())
|
|
571
|
+
putString("id", it.id)
|
|
572
|
+
putDouble("scheduleTime", it.scheduleTime)
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Converts any `Ad` object into its json representation.
|
|
578
|
+
* @param ad `Ad` object.
|
|
579
|
+
* @return The produced JS object.
|
|
580
|
+
*/
|
|
581
|
+
@JvmStatic
|
|
582
|
+
fun fromAd(ad: Ad?): WritableMap? = ad?.let {
|
|
583
|
+
Arguments.createMap().apply {
|
|
584
|
+
putString("clickThroughUrl", it.clickThroughUrl)
|
|
585
|
+
putMap("data", fromAdData(it.data))
|
|
586
|
+
putInt("height", it.height)
|
|
587
|
+
putString("id", it.id)
|
|
588
|
+
putBoolean("isLinear", it.isLinear)
|
|
589
|
+
putString("mediaFileUrl", it.mediaFileUrl)
|
|
590
|
+
putInt("width", it.width)
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Converts any `AdData` object into its json representation.
|
|
596
|
+
* @param adData `AdData` object.
|
|
597
|
+
* @return The produced JS object.
|
|
598
|
+
*/
|
|
599
|
+
@JvmStatic
|
|
600
|
+
fun fromAdData(adData: AdData?): WritableMap? = adData?.let {
|
|
601
|
+
Arguments.createMap().apply {
|
|
602
|
+
putInt("bitrate", it.bitrate)
|
|
603
|
+
putInt("maxBitrate", it.maxBitrate)
|
|
604
|
+
putString("mimeType", it.mimeType)
|
|
605
|
+
putInt("minBitrate", it.minBitrate)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Converts any `AdConfig` object into its json representation.
|
|
611
|
+
* @param adConfig `AdConfig` object.
|
|
612
|
+
* @return The produced JS object.
|
|
613
|
+
*/
|
|
614
|
+
@JvmStatic
|
|
615
|
+
fun fromAdConfig(adConfig: AdConfig?): WritableMap? = adConfig?.let {
|
|
616
|
+
Arguments.createMap().apply {
|
|
617
|
+
putDouble("replaceContentDuration", it.replaceContentDuration)
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Converts any `AdItem` object into its json representation.
|
|
623
|
+
* @param adItem `AdItem` object.
|
|
624
|
+
* @return The produced JS object.
|
|
625
|
+
*/
|
|
626
|
+
@JvmStatic
|
|
627
|
+
fun fromAdItem(adItem: AdItem?): WritableMap? = adItem?.let {
|
|
628
|
+
Arguments.createMap().apply {
|
|
629
|
+
putString("position", it.position)
|
|
630
|
+
putArray("sources", it.sources.mapNotNull(::fromAdSource).toReadableArray())
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Converts any `AdSource` object into its json representation.
|
|
636
|
+
* @param adSource `AdSource` object.
|
|
637
|
+
* @return The produced JS object.
|
|
638
|
+
*/
|
|
639
|
+
@JvmStatic
|
|
640
|
+
fun fromAdSource(adSource: AdSource?): WritableMap? = adSource?.let {
|
|
641
|
+
Arguments.createMap().apply {
|
|
642
|
+
putString("tag", it.tag)
|
|
643
|
+
putString("type", fromAdSourceType(it.type))
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Converts any `AdSourceType` value into its json representation.
|
|
649
|
+
* @param adSourceType `AdSourceType` value.
|
|
650
|
+
* @return The produced JS string.
|
|
651
|
+
*/
|
|
652
|
+
@JvmStatic
|
|
653
|
+
fun fromAdSourceType(adSourceType: AdSourceType?): String? = when (adSourceType) {
|
|
654
|
+
AdSourceType.Ima -> "ima"
|
|
655
|
+
AdSourceType.Unknown -> "unknown"
|
|
656
|
+
AdSourceType.Progressive -> "progressive"
|
|
657
|
+
else -> null
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Converts any `AdQuartile` value into its json representation.
|
|
662
|
+
* @param adQuartile `AdQuartile` value.
|
|
663
|
+
* @return The produced JS string.
|
|
664
|
+
*/
|
|
665
|
+
@JvmStatic
|
|
666
|
+
fun fromAdQuartile(adQuartile: AdQuartile?): String? = when (adQuartile) {
|
|
667
|
+
AdQuartile.FirstQuartile -> "first"
|
|
668
|
+
AdQuartile.MidPoint -> "mid_point"
|
|
669
|
+
AdQuartile.ThirdQuartile -> "third"
|
|
670
|
+
else -> null
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Converts an arbitrary json object into a `BitmovinAnalyticsConfig`.
|
|
675
|
+
* @param json JS object representing the `BitmovinAnalyticsConfig`.
|
|
676
|
+
* @return The produced `BitmovinAnalyticsConfig` or null.
|
|
677
|
+
*/
|
|
678
|
+
@JvmStatic
|
|
679
|
+
fun toAnalyticsConfig(json: ReadableMap?): BitmovinAnalyticsConfig? = json?.let {
|
|
680
|
+
var config: BitmovinAnalyticsConfig? = null
|
|
681
|
+
it.getString("key")?.let { key ->
|
|
682
|
+
config = it.getString("playerKey")
|
|
683
|
+
?.let { playerKey -> BitmovinAnalyticsConfig(key, playerKey) }
|
|
684
|
+
?: BitmovinAnalyticsConfig(key)
|
|
685
|
+
}
|
|
686
|
+
it.getString("cdnProvider")?.let { cdnProvider ->
|
|
687
|
+
config?.cdnProvider = cdnProvider
|
|
688
|
+
}
|
|
689
|
+
it.getString("customUserId")?.let { customUserId ->
|
|
690
|
+
config?.customUserId = customUserId
|
|
691
|
+
}
|
|
692
|
+
it.getString("experimentName")?.let { experimentName ->
|
|
693
|
+
config?.experimentName = experimentName
|
|
694
|
+
}
|
|
695
|
+
it.getString("videoId")?.let { videoId ->
|
|
696
|
+
config?.videoId = videoId
|
|
697
|
+
}
|
|
698
|
+
it.getString("title")?.let { title ->
|
|
699
|
+
config?.title = title
|
|
700
|
+
}
|
|
701
|
+
it.getString("path")?.let { path ->
|
|
702
|
+
config?.path = path
|
|
703
|
+
}
|
|
704
|
+
if (it.hasKey("isLive")) {
|
|
705
|
+
config?.isLive = it.getBoolean("isLive")
|
|
706
|
+
}
|
|
707
|
+
if (it.hasKey("ads")) {
|
|
708
|
+
config?.ads = it.getBoolean("ads")
|
|
709
|
+
}
|
|
710
|
+
if (it.hasKey("randomizeUserId")) {
|
|
711
|
+
config?.randomizeUserId = it.getBoolean("randomizeUserId")
|
|
712
|
+
}
|
|
713
|
+
for (n in 1..30) {
|
|
714
|
+
it.getString("customData${n}")?.let { customDataN ->
|
|
715
|
+
config?.setProperty("customData${n}", customDataN)
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
config
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Converts an arbitrary json object into an analytics `CustomData`.
|
|
723
|
+
* @param json JS object representing the `CustomData`.
|
|
724
|
+
* @return The produced `CustomData` or null.
|
|
725
|
+
*/
|
|
726
|
+
@JvmStatic
|
|
727
|
+
fun toAnalyticsCustomData(json: ReadableMap?): CustomData? = json?.let {
|
|
728
|
+
val customData = CustomData()
|
|
729
|
+
for (n in 1..30) {
|
|
730
|
+
it.getString("customData${n}")?.let { customDataN ->
|
|
731
|
+
customData.setProperty("customData${n}", customDataN)
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
customData
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Converts an arbitrary analytics `CustomData` object into a JS value.
|
|
739
|
+
* @param customData `CustomData` to be converted.
|
|
740
|
+
* @return The produced JS value or null.
|
|
741
|
+
*/
|
|
742
|
+
@JvmStatic
|
|
743
|
+
fun fromAnalyticsCustomData(customData: CustomData?): ReadableMap? = customData?.let {
|
|
744
|
+
val json = Arguments.createMap()
|
|
745
|
+
for (n in 1..30) {
|
|
746
|
+
it.getProperty<String>("customData${n}")?.let { customDataN ->
|
|
747
|
+
json.putString("customData${n}", customDataN)
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
json
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Converts any `VideoQuality` value into its json representation.
|
|
755
|
+
* @param videoQuality `VideoQuality` value.
|
|
756
|
+
* @return The produced JS string.
|
|
757
|
+
*/
|
|
758
|
+
@JvmStatic
|
|
759
|
+
fun fromVideoQuality(videoQuality: VideoQuality?): WritableMap? = videoQuality?.let {
|
|
760
|
+
Arguments.createMap().apply {
|
|
761
|
+
putString("id", videoQuality.id)
|
|
762
|
+
putString("label", videoQuality.label)
|
|
763
|
+
putInt("bitrate", videoQuality.bitrate)
|
|
764
|
+
putString("codec", videoQuality.codec)
|
|
765
|
+
putDouble("frameRate", videoQuality.frameRate.toDouble())
|
|
766
|
+
putInt("height", videoQuality.height)
|
|
767
|
+
putInt("width", videoQuality.width)
|
|
768
|
+
}
|
|
769
|
+
}
|
|
381
770
|
}
|
|
382
771
|
}
|