@100mslive/react-native-hms 1.10.2 → 1.10.4
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/android/local.properties +8 -1
- package/android/src/main/java/com/reactnativehmssdk/HMSDecoder.kt +3 -0
- package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt +94 -0
- package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayerManager.kt +32 -0
- package/ios/HMSDecoder.swift +12 -0
- package/ios/HMSHLSPlayerManager.m +6 -0
- package/ios/HMSHLSPlayerManager.swift +140 -1
- package/ios/Hmssdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/Hmssdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/Hmssdk.xcodeproj/project.xcworkspace/xcuserdata/jatinnagar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/Hmssdk.xcodeproj/xcuserdata/jatinnagar.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/lib/commonjs/classes/HMSEncoder.js +11 -1
- package/lib/commonjs/classes/HMSEncoder.js.map +1 -1
- package/lib/commonjs/classes/HMSHLSPlaylistType.js +12 -0
- package/lib/commonjs/classes/HMSHLSPlaylistType.js.map +1 -0
- package/lib/commonjs/classes/HMSHLSVariant.js +2 -0
- package/lib/commonjs/classes/HMSHLSVariant.js.map +1 -1
- package/lib/commonjs/classes/HMSNoiseCancellationPlugin.js +1 -0
- package/lib/commonjs/classes/HMSNoiseCancellationPlugin.js.map +1 -1
- package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js +98 -2
- package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
- package/lib/commonjs/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
- package/lib/commonjs/components/HMSHLSPlayer/hooks.js +16 -6
- package/lib/commonjs/components/HMSHLSPlayer/hooks.js.map +1 -1
- package/lib/commonjs/components/HMSHLSPlayer/index.js +15 -1
- package/lib/commonjs/components/HMSHLSPlayer/index.js.map +1 -1
- package/lib/commonjs/index.js +12 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/stores/hls-player-playback-slice.js +6 -0
- package/lib/commonjs/stores/hls-player-playback-slice.js.map +1 -1
- package/lib/commonjs/stores/hls-player-stats-store.js +27 -15
- package/lib/commonjs/stores/hls-player-stats-store.js.map +1 -1
- package/lib/commonjs/stores/types.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/classes/HMSEncoder.js +11 -1
- package/lib/module/classes/HMSEncoder.js.map +1 -1
- package/lib/module/classes/HMSHLSPlaylistType.js +6 -0
- package/lib/module/classes/HMSHLSPlaylistType.js.map +1 -0
- package/lib/module/classes/HMSHLSVariant.js +2 -0
- package/lib/module/classes/HMSHLSVariant.js.map +1 -1
- package/lib/module/classes/HMSNoiseCancellationPlugin.js +1 -0
- package/lib/module/classes/HMSNoiseCancellationPlugin.js.map +1 -1
- package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js +101 -5
- package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
- package/lib/module/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
- package/lib/module/components/HMSHLSPlayer/hooks.js +12 -4
- package/lib/module/components/HMSHLSPlayer/hooks.js.map +1 -1
- package/lib/module/components/HMSHLSPlayer/index.js +1 -1
- package/lib/module/components/HMSHLSPlayer/index.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/stores/hls-player-playback-slice.js +6 -0
- package/lib/module/stores/hls-player-playback-slice.js.map +1 -1
- package/lib/module/stores/hls-player-stats-store.js +27 -15
- package/lib/module/stores/hls-player-stats-store.js.map +1 -1
- package/lib/module/stores/types.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/classes/HMSEncoder.d.ts +2 -0
- package/lib/typescript/classes/HMSHLSPlaylistType.d.ts +4 -0
- package/lib/typescript/classes/HMSHLSVariant.d.ts +3 -0
- package/lib/typescript/classes/HMSNoiseCancellationPlugin.d.ts +1 -0
- package/lib/typescript/components/HMSHLSPlayer/HMSHLSPlayer.d.ts +6 -0
- package/lib/typescript/components/HMSHLSPlayer/RCTHMSHLSPlayer.d.ts +5 -1
- package/lib/typescript/components/HMSHLSPlayer/hooks.d.ts +3 -0
- package/lib/typescript/components/HMSHLSPlayer/index.d.ts +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/stores/hls-player-stats-store.d.ts +4 -3
- package/lib/typescript/stores/types.d.ts +7 -1
- package/lib/typescript/types.d.ts +9 -0
- package/package.json +1 -1
- package/sdk-versions.json +2 -2
- package/src/classes/HMSEncoder.ts +13 -0
- package/src/classes/HMSHLSPlaylistType.ts +4 -0
- package/src/classes/HMSHLSVariant.ts +5 -0
- package/src/classes/HMSNoiseCancellationPlugin.ts +1 -0
- package/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx +158 -4
- package/src/components/HMSHLSPlayer/RCTHMSHLSPlayer.ts +12 -0
- package/src/components/HMSHLSPlayer/hooks.ts +16 -4
- package/src/components/HMSHLSPlayer/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/stores/hls-player-playback-slice.ts +8 -0
- package/src/stores/hls-player-stats-store.ts +28 -18
- package/src/stores/types.ts +9 -1
- package/src/types.ts +15 -0
package/android/local.properties
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
+
# as it contains information specific to your local configuration.
|
|
3
|
+
#
|
|
4
|
+
# Location of the SDK. This is only used by Gradle.
|
|
5
|
+
# For customization when using a Version Control System, please read the
|
|
6
|
+
# header note.
|
|
7
|
+
#Mon Nov 14 20:51:00 IST 2022
|
|
8
|
+
sdk.dir=/Users/jatinnagar/Library/Android/sdk
|
|
@@ -3,12 +3,16 @@ package com.reactnativehmssdk
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.view.LayoutInflater
|
|
6
|
+
import android.view.View
|
|
6
7
|
import android.widget.FrameLayout
|
|
7
8
|
import androidx.media3.common.Player
|
|
8
9
|
import androidx.media3.common.VideoSize
|
|
10
|
+
import androidx.media3.common.text.CueGroup
|
|
9
11
|
import androidx.media3.ui.PlayerView
|
|
10
12
|
import com.facebook.react.bridge.Arguments
|
|
11
13
|
import com.facebook.react.bridge.ReactContext
|
|
14
|
+
import com.facebook.react.bridge.ReadableArray
|
|
15
|
+
import com.facebook.react.bridge.ReadableMap
|
|
12
16
|
import com.facebook.react.bridge.WritableMap
|
|
13
17
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
14
18
|
import live.hms.hls_player.*
|
|
@@ -25,6 +29,7 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
25
29
|
private var hmsHlsPlayer: HmsHlsPlayer? = null // 100ms HLS Player
|
|
26
30
|
private var hmssdkInstance: HMSSDK? = null
|
|
27
31
|
private var statsMonitorAttached = false
|
|
32
|
+
private var shouldSendCaptionsToJS = false
|
|
28
33
|
private val hmsHlsPlaybackEventsObject =
|
|
29
34
|
object : HmsHlsPlaybackEvents {
|
|
30
35
|
override fun onCue(cue: HmsHlsCue) {
|
|
@@ -115,6 +120,7 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
115
120
|
val localPlayerView = view.findViewById<PlayerView>(R.id.hls_view)
|
|
116
121
|
playerView = localPlayerView
|
|
117
122
|
localPlayerView.useController = false
|
|
123
|
+
localPlayerView.subtitleView?.visibility = View.GONE
|
|
118
124
|
|
|
119
125
|
val hmssdkCollection = context.getNativeModule(HMSManager::class.java)?.getHmsInstance()
|
|
120
126
|
hmssdkInstance = hmssdkCollection?.get("12345")?.hmsSDK
|
|
@@ -144,6 +150,13 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
144
150
|
sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_RESOLUTION_CHANGE_EVENT, data)
|
|
145
151
|
}
|
|
146
152
|
}
|
|
153
|
+
|
|
154
|
+
override fun onCues(cueGroup: CueGroup) {
|
|
155
|
+
super.onCues(cueGroup)
|
|
156
|
+
if (!shouldSendCaptionsToJS) return
|
|
157
|
+
val ccText = cueGroup.cues.firstOrNull()?.text?.toString()
|
|
158
|
+
sendHLSPlayerCuesEventToJS(ccText)
|
|
159
|
+
}
|
|
147
160
|
},
|
|
148
161
|
)
|
|
149
162
|
}
|
|
@@ -204,6 +217,38 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
204
217
|
hmsHlsPlayer?.volume = level
|
|
205
218
|
}
|
|
206
219
|
|
|
220
|
+
fun areClosedCaptionSupported(requestId: Int) {
|
|
221
|
+
hmsHlsPlayer.let {
|
|
222
|
+
if (it == null) {
|
|
223
|
+
sendHLSDataRequestEventToJS(requestId, false)
|
|
224
|
+
} else {
|
|
225
|
+
sendHLSDataRequestEventToJS(requestId, it.areClosedCaptionsSupported())
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
fun isClosedCaptionEnabled(requestId: Int) {
|
|
231
|
+
sendHLSDataRequestEventToJS(requestId, shouldSendCaptionsToJS)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fun enableClosedCaption() {
|
|
235
|
+
shouldSendCaptionsToJS = true
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
fun disableClosedCaption() {
|
|
239
|
+
shouldSendCaptionsToJS = false
|
|
240
|
+
sendHLSPlayerCuesEventToJS(null)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
fun getPlayerDurationDetails(requestId: Int) {
|
|
244
|
+
val data: WritableMap = Arguments.createMap()
|
|
245
|
+
hmsHlsPlayer?.getNativePlayer()?.let { exoPlayer ->
|
|
246
|
+
data.putInt("rollingWindowTime", exoPlayer.seekParameters.toleranceAfterUs.div(1000).toInt())
|
|
247
|
+
data.putInt("streamDuration", exoPlayer.duration.toInt())
|
|
248
|
+
}
|
|
249
|
+
sendHLSDataRequestEventToJS(requestId, data)
|
|
250
|
+
}
|
|
251
|
+
|
|
207
252
|
fun enableStats(enable: Boolean) {
|
|
208
253
|
if (enable) {
|
|
209
254
|
attachStatsMonitor()
|
|
@@ -215,11 +260,13 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
215
260
|
fun enableControls(show: Boolean) {
|
|
216
261
|
playerView?.let {
|
|
217
262
|
if (show) {
|
|
263
|
+
it.subtitleView?.visibility = View.VISIBLE
|
|
218
264
|
it.useController = true
|
|
219
265
|
it.showController()
|
|
220
266
|
} else {
|
|
221
267
|
it.hideController()
|
|
222
268
|
it.useController = false
|
|
269
|
+
it.subtitleView?.visibility = View.GONE
|
|
223
270
|
}
|
|
224
271
|
}
|
|
225
272
|
}
|
|
@@ -263,6 +310,46 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) {
|
|
|
263
310
|
val reactContext = context as ReactContext
|
|
264
311
|
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, HMSHLSPlayerConstants.HMS_HLS_STATS_EVENT, event)
|
|
265
312
|
}
|
|
313
|
+
|
|
314
|
+
private fun sendHLSDataRequestEventToJS(
|
|
315
|
+
requestId: Int,
|
|
316
|
+
data: Any,
|
|
317
|
+
) {
|
|
318
|
+
val event: WritableMap = Arguments.createMap()
|
|
319
|
+
event.putInt("requestId", requestId)
|
|
320
|
+
|
|
321
|
+
if (data is Boolean) {
|
|
322
|
+
event.putBoolean("data", data)
|
|
323
|
+
} else if (data is String) {
|
|
324
|
+
event.putString("data", data)
|
|
325
|
+
} else if (data is Int) {
|
|
326
|
+
event.putInt("data", data)
|
|
327
|
+
} else if (data is Double) {
|
|
328
|
+
event.putDouble("data", data)
|
|
329
|
+
} else if (data is ReadableMap) {
|
|
330
|
+
event.putMap("data", data)
|
|
331
|
+
} else if (data is ReadableArray) {
|
|
332
|
+
event.putArray("data", data)
|
|
333
|
+
} else {
|
|
334
|
+
event.putNull("data")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
val reactContext = context as ReactContext
|
|
338
|
+
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, HMSHLSPlayerConstants.HLS_DATA_REQUEST_EVENT, event)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
private fun sendHLSPlayerCuesEventToJS(ccText: String?) {
|
|
342
|
+
val event: WritableMap = Arguments.createMap()
|
|
343
|
+
event.putString("event", HMSHLSPlayerConstants.ON_CLOSED_CAPTION_UPDATE)
|
|
344
|
+
|
|
345
|
+
if (ccText is String) {
|
|
346
|
+
event.putString("data", ccText)
|
|
347
|
+
} else {
|
|
348
|
+
event.putNull("data")
|
|
349
|
+
}
|
|
350
|
+
val reactContext = context as ReactContext
|
|
351
|
+
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, HMSHLSPlayerConstants.HLS_PLAYER_CUES_EVENT, event)
|
|
352
|
+
}
|
|
266
353
|
}
|
|
267
354
|
|
|
268
355
|
object HMSHLSPlayerConstants {
|
|
@@ -277,4 +364,11 @@ object HMSHLSPlayerConstants {
|
|
|
277
364
|
const val HMS_HLS_STATS_EVENT = "hmsHlsStatsEvent"
|
|
278
365
|
const val ON_STATS_EVENT_UPDATE = "ON_STATS_EVENT_UPDATE"
|
|
279
366
|
const val ON_STATS_EVENT_ERROR = "ON_STATS_EVENT_ERROR"
|
|
367
|
+
|
|
368
|
+
// HLS Requested Data Returned
|
|
369
|
+
const val HLS_DATA_REQUEST_EVENT = "hlsDataRequestEvent"
|
|
370
|
+
|
|
371
|
+
// HLS Player Cues Events
|
|
372
|
+
const val HLS_PLAYER_CUES_EVENT = "hlsPlayerCuesEvent"
|
|
373
|
+
const val ON_CLOSED_CAPTION_UPDATE = "ON_CLOSED_CAPTION_UPDATE"
|
|
280
374
|
}
|
|
@@ -31,6 +31,10 @@ class HMSHLSPlayerManager : SimpleViewManager<HMSHLSPlayer>() {
|
|
|
31
31
|
MapBuilder.of("registrationName", "onHmsHlsPlaybackEvent"),
|
|
32
32
|
HMSHLSPlayerConstants.HMS_HLS_STATS_EVENT,
|
|
33
33
|
MapBuilder.of("registrationName", "onHmsHlsStatsEvent"),
|
|
34
|
+
HMSHLSPlayerConstants.HLS_DATA_REQUEST_EVENT,
|
|
35
|
+
MapBuilder.of("registrationName", "onDataReturned"),
|
|
36
|
+
HMSHLSPlayerConstants.HLS_PLAYER_CUES_EVENT,
|
|
37
|
+
MapBuilder.of("registrationName", "onHlsPlayerCuesEvent"),
|
|
34
38
|
)
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -68,6 +72,29 @@ class HMSHLSPlayerManager : SimpleViewManager<HMSHLSPlayer>() {
|
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
}
|
|
75
|
+
90 -> {
|
|
76
|
+
args.let {
|
|
77
|
+
if (it != null) {
|
|
78
|
+
root.areClosedCaptionSupported(it.getInt(0))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
100 -> {
|
|
83
|
+
args.let {
|
|
84
|
+
if (it != null) {
|
|
85
|
+
root.isClosedCaptionEnabled(it.getInt(0))
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
110 -> root.enableClosedCaption()
|
|
90
|
+
120 -> root.disableClosedCaption()
|
|
91
|
+
130 -> {
|
|
92
|
+
args.let {
|
|
93
|
+
if (it != null) {
|
|
94
|
+
root.getPlayerDurationDetails(it.getInt(0))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
71
98
|
}
|
|
72
99
|
}
|
|
73
100
|
|
|
@@ -81,6 +108,11 @@ class HMSHLSPlayerManager : SimpleViewManager<HMSHLSPlayer>() {
|
|
|
81
108
|
.put("seekForward", 60)
|
|
82
109
|
.put("seekBackward", 70)
|
|
83
110
|
.put("setVolume", 80)
|
|
111
|
+
.put("areClosedCaptionSupported", 90)
|
|
112
|
+
.put("isClosedCaptionEnabled", 100)
|
|
113
|
+
.put("enableClosedCaption", 110)
|
|
114
|
+
.put("disableClosedCaption", 120)
|
|
115
|
+
.put("getPlayerDurationDetails", 130)
|
|
84
116
|
.build()
|
|
85
117
|
}
|
|
86
118
|
|
package/ios/HMSDecoder.swift
CHANGED
|
@@ -811,12 +811,24 @@ class HMSDecoder: NSObject {
|
|
|
811
811
|
if let startedAt = variant.startedAt?.timeIntervalSince1970 {
|
|
812
812
|
decodedVariant["startedAt"] = startedAt * 1000
|
|
813
813
|
}
|
|
814
|
+
if let type = variant.playlistType {
|
|
815
|
+
decodedVariant["playlistType"] = getHLSVariantPlaylistType(from: type)
|
|
816
|
+
}
|
|
814
817
|
variants.append(decodedVariant)
|
|
815
818
|
}
|
|
816
819
|
}
|
|
817
820
|
return variants
|
|
818
821
|
}
|
|
819
822
|
|
|
823
|
+
static func getHLSVariantPlaylistType(from type: HMSHLSPlaylistType) -> String {
|
|
824
|
+
switch type {
|
|
825
|
+
case .dvr:
|
|
826
|
+
return "DVR"
|
|
827
|
+
default:
|
|
828
|
+
return "NODVR"
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
820
832
|
static func getHMSRTCStats(_ data: HMSRTCStats) -> [Any] {
|
|
821
833
|
// [bitrateReceived, bitrateSent, bytesReceived, bytesSent, packetsLost, packetsReceived, roundTripTime]
|
|
822
834
|
return [
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
RCT_EXPORT_VIEW_PROPERTY(url, NSString);
|
|
8
8
|
RCT_EXPORT_VIEW_PROPERTY(enableStats, BOOL);
|
|
9
9
|
RCT_EXPORT_VIEW_PROPERTY(enableControls, BOOL);
|
|
10
|
+
RCT_EXPORT_VIEW_PROPERTY(onDataReturned, RCTDirectEventBlock);
|
|
10
11
|
RCT_EXPORT_VIEW_PROPERTY(onHmsHlsPlaybackEvent, RCTDirectEventBlock);
|
|
11
12
|
RCT_EXPORT_VIEW_PROPERTY(onHmsHlsStatsEvent, RCTDirectEventBlock);
|
|
12
13
|
|
|
@@ -18,5 +19,10 @@ RCT_EXTERN_METHOD(seekToLivePosition:(nonnull NSNumber *)node)
|
|
|
18
19
|
RCT_EXTERN_METHOD(seekForward:(nonnull NSNumber *)node seconds:(nonnull NSNumber *)seconds)
|
|
19
20
|
RCT_EXTERN_METHOD(seekBackward:(nonnull NSNumber *)node seconds:(nonnull NSNumber *)seconds)
|
|
20
21
|
RCT_EXTERN_METHOD(setVolume:(nonnull NSNumber *)node level:(nonnull NSNumber *)level)
|
|
22
|
+
RCT_EXTERN_METHOD(areClosedCaptionSupported:(nonnull NSNumber *)node requestId:(nonnull NSNumber *)requestId)
|
|
23
|
+
RCT_EXTERN_METHOD(isClosedCaptionEnabled:(nonnull NSNumber *)node requestId:(nonnull NSNumber *)requestId)
|
|
24
|
+
RCT_EXTERN_METHOD(enableClosedCaption:(nonnull NSNumber *)node)
|
|
25
|
+
RCT_EXTERN_METHOD(disableClosedCaption:(nonnull NSNumber *)node)
|
|
26
|
+
RCT_EXTERN_METHOD(getPlayerDurationDetails:(nonnull NSNumber *)node requestId:(nonnull NSNumber *)requestId)
|
|
21
27
|
|
|
22
28
|
@end
|
|
@@ -87,6 +87,46 @@ class HMSHLSPlayerManager: RCTViewManager {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
|
|
91
|
+
@objc func areClosedCaptionSupported(_ node: NSNumber, requestId: NSNumber) {
|
|
92
|
+
DispatchQueue.main.async {
|
|
93
|
+
if let component = self.bridge.uiManager.view(forReactTag: node) as? HMSHLSPlayer {
|
|
94
|
+
component.areClosedCaptionSupported(requestId: UInt(truncating: requestId))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc func isClosedCaptionEnabled(_ node: NSNumber, requestId: NSNumber) {
|
|
100
|
+
DispatchQueue.main.async {
|
|
101
|
+
if let component = self.bridge.uiManager.view(forReactTag: node) as? HMSHLSPlayer {
|
|
102
|
+
component.isClosedCaptionEnabled(requestId: UInt(truncating: requestId))
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@objc func enableClosedCaption(_ node: NSNumber) {
|
|
108
|
+
DispatchQueue.main.async {
|
|
109
|
+
if let component = self.bridge.uiManager.view(forReactTag: node) as? HMSHLSPlayer {
|
|
110
|
+
component.enableClosedCaption()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@objc func disableClosedCaption(_ node: NSNumber) {
|
|
116
|
+
DispatchQueue.main.async {
|
|
117
|
+
if let component = self.bridge.uiManager.view(forReactTag: node) as? HMSHLSPlayer {
|
|
118
|
+
component.disableClosedCaption()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@objc func getPlayerDurationDetails(_ node: NSNumber, requestId: NSNumber) {
|
|
124
|
+
DispatchQueue.main.async {
|
|
125
|
+
if let component = self.bridge.uiManager.view(forReactTag: node) as? HMSHLSPlayer {
|
|
126
|
+
component.getPlayerDurationDetails(requestId: UInt(truncating: requestId))
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
90
130
|
}
|
|
91
131
|
|
|
92
132
|
class HMSHLSPlayer: UIView {
|
|
@@ -105,6 +145,8 @@ class HMSHLSPlayer: UIView {
|
|
|
105
145
|
|
|
106
146
|
// MARK: Handle HMSHLSPlayer RN Component props
|
|
107
147
|
|
|
148
|
+
@objc var onDataReturned: RCTDirectEventBlock?
|
|
149
|
+
|
|
108
150
|
@objc var onHmsHlsPlaybackEvent: RCTDirectEventBlock?
|
|
109
151
|
|
|
110
152
|
@objc var onHmsHlsStatsEvent: RCTDirectEventBlock?
|
|
@@ -158,6 +200,97 @@ class HMSHLSPlayer: UIView {
|
|
|
158
200
|
hmsHLSPlayer.stop()
|
|
159
201
|
}
|
|
160
202
|
|
|
203
|
+
private func isCCSupported() -> Bool {
|
|
204
|
+
guard let playerItem = hmsHLSPlayer._nativePlayer.currentItem else {
|
|
205
|
+
return false
|
|
206
|
+
}
|
|
207
|
+
guard let mediaSelectionGroup = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
guard let firstMediaSelectionGroupOption = mediaSelectionGroup.options.first else {
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
return firstMediaSelectionGroupOption.mediaType == .subtitle
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private func isCCEnabled() -> Bool {
|
|
217
|
+
guard let playerItem = hmsHLSPlayer._nativePlayer.currentItem else {
|
|
218
|
+
return false
|
|
219
|
+
}
|
|
220
|
+
guard let subtitle = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
|
|
221
|
+
return false
|
|
222
|
+
}
|
|
223
|
+
let selectedOption = playerItem.currentMediaSelection.selectedMediaOption(in: subtitle)
|
|
224
|
+
return selectedOption != nil
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@objc func areClosedCaptionSupported(requestId: UInt) {
|
|
228
|
+
let supported = isCCSupported()
|
|
229
|
+
|
|
230
|
+
sendRequestedDataToJS(requestId, supported)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@objc func isClosedCaptionEnabled(requestId: UInt) {
|
|
234
|
+
let enabled = isCCEnabled()
|
|
235
|
+
|
|
236
|
+
sendRequestedDataToJS(requestId, enabled)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@objc func enableClosedCaption() {
|
|
240
|
+
if !isCCSupported() {
|
|
241
|
+
print("#func Closed Caption is not supported")
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
if isCCEnabled() {
|
|
245
|
+
print("#func Closed Caption already enabled!")
|
|
246
|
+
return
|
|
247
|
+
}
|
|
248
|
+
guard let playerItem = hmsHLSPlayer._nativePlayer.currentItem else {
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
guard let subtitle = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
guard let firstSubtitleTrack = subtitle.options.first(where: {$0.mediaType == .subtitle}) else {
|
|
255
|
+
return
|
|
256
|
+
}
|
|
257
|
+
playerItem.select(firstSubtitleTrack, in: subtitle)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@objc func disableClosedCaption() {
|
|
261
|
+
if !isCCSupported() {
|
|
262
|
+
print("#func Closed Caption is not supported")
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
if !isCCEnabled() {
|
|
266
|
+
print("#func Closed Caption already disabled!")
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
guard let playerItem = hmsHLSPlayer._nativePlayer.currentItem else {
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
guard let subtitle = playerItem.asset.mediaSelectionGroup(forMediaCharacteristic: .legible) else {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
playerItem.select(nil, in: subtitle)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@objc func getPlayerDurationDetails(requestId: UInt) {
|
|
279
|
+
var map = [String: Any?]()
|
|
280
|
+
guard let playerItem = hmsHLSPlayer._nativePlayer.currentItem else {
|
|
281
|
+
sendRequestedDataToJS(requestId, map)
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
// If duration is known
|
|
285
|
+
if !playerItem.duration.isIndefinite {
|
|
286
|
+
map["streamDuration"] = playerItem.duration.seconds
|
|
287
|
+
}
|
|
288
|
+
if let timeRange = playerItem.seekableTimeRanges.last as? CMTimeRange {
|
|
289
|
+
map["rollingWindowTime"] = timeRange.duration.seconds * 1000
|
|
290
|
+
}
|
|
291
|
+
sendRequestedDataToJS(requestId, map)
|
|
292
|
+
}
|
|
293
|
+
|
|
161
294
|
@objc func pause() {
|
|
162
295
|
hmsHLSPlayer.pause()
|
|
163
296
|
}
|
|
@@ -182,7 +315,7 @@ class HMSHLSPlayer: UIView {
|
|
|
182
315
|
hmsHLSPlayer.volume = level
|
|
183
316
|
}
|
|
184
317
|
|
|
185
|
-
// MARK:
|
|
318
|
+
// MARK: Lifecycle methods
|
|
186
319
|
|
|
187
320
|
override init(frame: CGRect) {
|
|
188
321
|
super.init(frame: frame)
|
|
@@ -234,6 +367,12 @@ class HMSHLSPlayer: UIView {
|
|
|
234
367
|
onHmsHlsPlaybackEvent(["event": eventName, "data": data])
|
|
235
368
|
}
|
|
236
369
|
|
|
370
|
+
private func sendRequestedDataToJS(_ requestId: UInt, _ data: Any) {
|
|
371
|
+
guard let onDataReturned = onDataReturned else { return }
|
|
372
|
+
|
|
373
|
+
onDataReturned(["requestId": requestId, "data": data])
|
|
374
|
+
}
|
|
375
|
+
|
|
237
376
|
private func sendHLSStatsEventToJS(_ eventName: String, _ data: [String: Any]) {
|
|
238
377
|
guard let onHmsHlsStatsEvent = onHmsHlsStatsEvent else { return }
|
|
239
378
|
|
|
Binary file
|
package/ios/Hmssdk.xcodeproj/xcuserdata/jatinnagar.xcuserdatad/xcschemes/xcschememanagement.plist
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Hmssdk.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
</dict>
|
|
14
|
+
</plist>
|
|
@@ -45,6 +45,7 @@ var _HMSLayer = require("./HMSLayer");
|
|
|
45
45
|
var _HMSSimulcastLayerDefinition = require("./HMSSimulcastLayerDefinition");
|
|
46
46
|
var _HMSQualityLimitationReasons = require("./HMSQualityLimitationReasons");
|
|
47
47
|
var _HMSTrackType = require("./HMSTrackType");
|
|
48
|
+
var _HMSHLSPlaylistType = require("./HMSHLSPlaylistType");
|
|
48
49
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
49
50
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
50
51
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
@@ -420,12 +421,21 @@ class HMSEncoder {
|
|
|
420
421
|
hlsStreamUrl: item.hlsStreamUrl,
|
|
421
422
|
meetingUrl: item.meetingUrl,
|
|
422
423
|
metadata: item !== null && item !== void 0 && item.metaData ? item === null || item === void 0 ? void 0 : item.metadata : undefined,
|
|
423
|
-
startedAt: HMSEncoder.encodeDate(item === null || item === void 0 ? void 0 : item.startedAt)
|
|
424
|
+
startedAt: HMSEncoder.encodeDate(item === null || item === void 0 ? void 0 : item.startedAt),
|
|
425
|
+
playlistType: item !== null && item !== void 0 && item.playlistType ? this.getHLSVariantPlaylistType(item.playlistType.toUpperCase()) : undefined
|
|
424
426
|
});
|
|
425
427
|
variants.push(variant);
|
|
426
428
|
});
|
|
427
429
|
return variants;
|
|
428
430
|
}
|
|
431
|
+
static getHLSVariantPlaylistType(type) {
|
|
432
|
+
switch (type) {
|
|
433
|
+
case 'DVR':
|
|
434
|
+
return _HMSHLSPlaylistType.HMSHLSPlaylistType.DVR;
|
|
435
|
+
default:
|
|
436
|
+
return _HMSHLSPlaylistType.HMSHLSPlaylistType.noDVR;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
429
439
|
static encodeHMSNetworkQuality(data) {
|
|
430
440
|
if (data) {
|
|
431
441
|
return new _HMSNetworkQuality.HMSNetworkQuality({
|