@100mslive/react-native-hms 1.10.3 → 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.
Files changed (84) hide show
  1. package/android/local.properties +8 -1
  2. package/android/src/main/java/com/reactnativehmssdk/HMSDecoder.kt +3 -0
  3. package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt +94 -0
  4. package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayerManager.kt +32 -0
  5. package/ios/HMSDecoder.swift +12 -0
  6. package/ios/HMSHLSPlayerManager.m +6 -0
  7. package/ios/HMSHLSPlayerManager.swift +140 -1
  8. package/ios/Hmssdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  9. package/ios/Hmssdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  10. package/ios/Hmssdk.xcodeproj/project.xcworkspace/xcuserdata/jatinnagar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  11. package/ios/Hmssdk.xcodeproj/xcuserdata/jatinnagar.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  12. package/lib/commonjs/classes/HMSEncoder.js +11 -1
  13. package/lib/commonjs/classes/HMSEncoder.js.map +1 -1
  14. package/lib/commonjs/classes/HMSHLSPlaylistType.js +12 -0
  15. package/lib/commonjs/classes/HMSHLSPlaylistType.js.map +1 -0
  16. package/lib/commonjs/classes/HMSHLSVariant.js +2 -0
  17. package/lib/commonjs/classes/HMSHLSVariant.js.map +1 -1
  18. package/lib/commonjs/classes/HMSNoiseCancellationPlugin.js +1 -0
  19. package/lib/commonjs/classes/HMSNoiseCancellationPlugin.js.map +1 -1
  20. package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js +98 -2
  21. package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
  22. package/lib/commonjs/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
  23. package/lib/commonjs/components/HMSHLSPlayer/hooks.js +16 -6
  24. package/lib/commonjs/components/HMSHLSPlayer/hooks.js.map +1 -1
  25. package/lib/commonjs/components/HMSHLSPlayer/index.js +15 -1
  26. package/lib/commonjs/components/HMSHLSPlayer/index.js.map +1 -1
  27. package/lib/commonjs/index.js +12 -0
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/stores/hls-player-playback-slice.js +6 -0
  30. package/lib/commonjs/stores/hls-player-playback-slice.js.map +1 -1
  31. package/lib/commonjs/stores/hls-player-stats-store.js +27 -15
  32. package/lib/commonjs/stores/hls-player-stats-store.js.map +1 -1
  33. package/lib/commonjs/stores/types.js.map +1 -1
  34. package/lib/commonjs/types.js.map +1 -1
  35. package/lib/module/classes/HMSEncoder.js +11 -1
  36. package/lib/module/classes/HMSEncoder.js.map +1 -1
  37. package/lib/module/classes/HMSHLSPlaylistType.js +6 -0
  38. package/lib/module/classes/HMSHLSPlaylistType.js.map +1 -0
  39. package/lib/module/classes/HMSHLSVariant.js +2 -0
  40. package/lib/module/classes/HMSHLSVariant.js.map +1 -1
  41. package/lib/module/classes/HMSNoiseCancellationPlugin.js +1 -0
  42. package/lib/module/classes/HMSNoiseCancellationPlugin.js.map +1 -1
  43. package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js +101 -5
  44. package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
  45. package/lib/module/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
  46. package/lib/module/components/HMSHLSPlayer/hooks.js +12 -4
  47. package/lib/module/components/HMSHLSPlayer/hooks.js.map +1 -1
  48. package/lib/module/components/HMSHLSPlayer/index.js +1 -1
  49. package/lib/module/components/HMSHLSPlayer/index.js.map +1 -1
  50. package/lib/module/index.js +1 -0
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/stores/hls-player-playback-slice.js +6 -0
  53. package/lib/module/stores/hls-player-playback-slice.js.map +1 -1
  54. package/lib/module/stores/hls-player-stats-store.js +27 -15
  55. package/lib/module/stores/hls-player-stats-store.js.map +1 -1
  56. package/lib/module/stores/types.js.map +1 -1
  57. package/lib/module/types.js.map +1 -1
  58. package/lib/typescript/classes/HMSEncoder.d.ts +2 -0
  59. package/lib/typescript/classes/HMSHLSPlaylistType.d.ts +4 -0
  60. package/lib/typescript/classes/HMSHLSVariant.d.ts +3 -0
  61. package/lib/typescript/classes/HMSNoiseCancellationPlugin.d.ts +1 -0
  62. package/lib/typescript/components/HMSHLSPlayer/HMSHLSPlayer.d.ts +6 -0
  63. package/lib/typescript/components/HMSHLSPlayer/RCTHMSHLSPlayer.d.ts +5 -1
  64. package/lib/typescript/components/HMSHLSPlayer/hooks.d.ts +3 -0
  65. package/lib/typescript/components/HMSHLSPlayer/index.d.ts +1 -1
  66. package/lib/typescript/index.d.ts +1 -0
  67. package/lib/typescript/stores/hls-player-stats-store.d.ts +4 -3
  68. package/lib/typescript/stores/types.d.ts +7 -1
  69. package/lib/typescript/types.d.ts +9 -0
  70. package/package.json +1 -1
  71. package/sdk-versions.json +2 -2
  72. package/src/classes/HMSEncoder.ts +13 -0
  73. package/src/classes/HMSHLSPlaylistType.ts +4 -0
  74. package/src/classes/HMSHLSVariant.ts +5 -0
  75. package/src/classes/HMSNoiseCancellationPlugin.ts +1 -0
  76. package/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx +158 -4
  77. package/src/components/HMSHLSPlayer/RCTHMSHLSPlayer.ts +12 -0
  78. package/src/components/HMSHLSPlayer/hooks.ts +16 -4
  79. package/src/components/HMSHLSPlayer/index.ts +2 -0
  80. package/src/index.ts +1 -0
  81. package/src/stores/hls-player-playback-slice.ts +8 -0
  82. package/src/stores/hls-player-stats-store.ts +28 -18
  83. package/src/stores/types.ts +9 -1
  84. package/src/types.ts +15 -0
@@ -1 +1,8 @@
1
- sdk.dir=/Users/yogesh/Library/Android/sdk
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
@@ -747,6 +747,9 @@ object HMSDecoder {
747
747
  variant.startedAt?.let {
748
748
  input.putString("startedAt", it.toString())
749
749
  }
750
+ variant.playlistType?.let {
751
+ input.putString("playlistType", it.name.uppercase())
752
+ }
750
753
  variants.pushMap(input)
751
754
  }
752
755
  }
@@ -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
 
@@ -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: Constructor & Deconstructor
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
 
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "self:">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,8 @@
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>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -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({