senza-sdk 4.2.64-70c0747.0 → 4.2.64

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 (27) hide show
  1. package/dist/bundle.js +1 -1
  2. package/dist/bundle.js.LICENSE.txt +4 -0
  3. package/package.json +10 -16
  4. package/src/{implementation/alarmManager.js → alarmManager.js} +52 -15
  5. package/src/api.js +350 -183
  6. package/src/{interface/devSequence.js → devSequence.js} +35 -0
  7. package/src/{implementation/deviceManager.js → deviceManager.js} +65 -4
  8. package/src/{implementation/lifecycle.js → lifecycle.js} +181 -5
  9. package/src/{implementation/messageManager.js → messageManager.js} +6 -6
  10. package/src/{implementation/platformManager.js → platformManager.js} +4 -5
  11. package/src/{implementation/remotePlayer.js → remotePlayer.js} +16 -7
  12. package/src/{implementation/senzaShakaPlayer.js → senzaShakaPlayer.js} +114 -25
  13. package/src/{implementation/utils.js → utils.js} +6 -15
  14. package/src/implementation/api.js +0 -367
  15. package/src/interface/alarmManager.js +0 -69
  16. package/src/interface/api.js +0 -8
  17. package/src/interface/deviceManager.js +0 -133
  18. package/src/interface/lifecycle.js +0 -278
  19. package/src/interface/messageManager.js +0 -46
  20. package/src/interface/platformManager.js +0 -35
  21. package/src/interface/remotePlayer.js +0 -441
  22. package/src/interface/senzaShakaPlayer.js +0 -171
  23. package/src/interface/utils.js +0 -45
  24. /package/src/{implementation/SessionInfo.js → SessionInfo.js} +0 -0
  25. /package/src/{implementation/devHelper.js → devHelper.js} +0 -0
  26. /package/src/{implementation/eventListenersManager.js → eventListenersManager.js} +0 -0
  27. /package/src/{implementation/subtitlesUtils.js → subtitlesUtils.js} +0 -0
@@ -1,4 +1,3 @@
1
- import { DeviceManager as DeviceManagerInterface } from "../interface/deviceManager";
2
1
  import { getFCID, sdkLogger, getRestResponse } from "./utils";
3
2
  import { isRunningE2E } from "./api";
4
3
  import { sessionInfo } from "./SessionInfo";
@@ -36,7 +35,10 @@ async function getWifiStatus() {
36
35
  }
37
36
  }
38
37
 
39
- class DeviceManager extends DeviceManagerInterface {
38
+ /**
39
+ * DeviceManager is a singleton class that manages the device
40
+ */
41
+ class DeviceManager extends EventTarget {
40
42
 
41
43
  constructor() {
42
44
  super();
@@ -44,7 +46,15 @@ class DeviceManager extends DeviceManagerInterface {
44
46
  wifiInfo.quality = 0;
45
47
  wifiInfo.ssid = "unknown";
46
48
  wifiInfo.bssid = "unknown";
47
-
49
+ /**
50
+ * @deprecated Instead, call deviceManager.getWifiInfo() periodically
51
+ * @event DeviceManager#wifiInfoUpdated
52
+ * @example
53
+ * deviceManager.addEventListener("wifiInfoUpdated", () => {
54
+ * console.info("Wifi info has been updated to", deviceManager.wifiInfo);
55
+ * });
56
+ *
57
+ */
48
58
  typeof document !== "undefined" && document.addEventListener("wifiSignalReport", (e) => {
49
59
  wifiInfo.level = e.detail.level;
50
60
  wifiInfo.quality = e.detail.quality;
@@ -55,6 +65,17 @@ class DeviceManager extends DeviceManagerInterface {
55
65
 
56
66
  }
57
67
 
68
+ /**
69
+ * @property {object} DeviceInfo
70
+ * @property {string} DeviceInfo.deviceId
71
+ * @property {string} DeviceInfo.modelNumber
72
+ * @property {string} DeviceInfo.connectionId
73
+ * @property {string} DeviceInfo.community
74
+ * @property {string} DeviceInfo.tenant
75
+ * @property {string} DeviceInfo.clientIp
76
+ * @property {string} DeviceInfo.countryCode A 2-letter code as defined in ISO_3166-1
77
+ * @property {string} DeviceInfo.connectionType The type of device used during the current connection. Possible values are "device" which mean real device, "simulator" - simulated device - that used during development.
78
+ */
58
79
  get deviceInfo() {
59
80
  const sessionInfoObj = sessionInfo.sessionInfoObj;
60
81
  if (isRunningE2E() && sessionInfoObj) {
@@ -82,10 +103,23 @@ class DeviceManager extends DeviceManagerInterface {
82
103
  };
83
104
  }
84
105
 
106
+ /**
107
+ * @deprecated use deviceManager.getWifiInfo() instead
108
+ * @property {object} WifiInfo
109
+ * @property {number} WifiInfo.level
110
+ * @property {number} WifiInfo.quality
111
+ * @property {string} WifiInfo.ssid
112
+ * @property {string} WifiInfo.bssid
113
+ */
85
114
  get wifiInfo() {
86
115
  return wifiInfo;
87
116
  }
88
117
 
118
+ /**
119
+ * Reboot the device
120
+ * @return {Promise} Promise which is resolved when the reboot command has been successfully processed.
121
+ * Failure to process the reboot command will result in the promise being rejected.
122
+ */
89
123
  reboot() {
90
124
  return new Promise((resolve, reject) => {
91
125
  if (window.cefQuery) {
@@ -115,6 +149,11 @@ class DeviceManager extends DeviceManagerInterface {
115
149
  });
116
150
  }
117
151
 
152
+ /**
153
+ * Delete current wifi configuration and forget network
154
+ * @return {Promise} Promise which is resolved when the clearWifi command has been successfully processed.
155
+ * Failure to process the clearWifi command will result in the promise being rejected.
156
+ */
118
157
  clearWifi() {
119
158
  return new Promise((resolve, reject) => {
120
159
  const FCID = getFCID();
@@ -139,6 +178,16 @@ class DeviceManager extends DeviceManagerInterface {
139
178
  });
140
179
  }
141
180
 
181
+ /**
182
+ * Send raw data directly to a customer's device via the USB serial connection of a Senza device.
183
+ * This function is specifically designed for customers who have their devices connected to a Senza device.
184
+ * Using this API, these customers can transmit messages or data directly to their connected devices.
185
+ * The transmission occurs through the Senza device's USB serial interface, facilitating direct communication
186
+ * between the customer's web application and their device.
187
+ * @param {String} data raw data to be passed to the device
188
+ * @return {Promise} Promise which is resolved when the command has been successfully processed.
189
+ * Failure to process the command will result in the promise being rejected.
190
+ */
142
191
  sendDataToDevice(data) {
143
192
  if (typeof data !== "string") {
144
193
  throw new Error("data must be of type 'string'");
@@ -170,6 +219,12 @@ class DeviceManager extends DeviceManagerInterface {
170
219
  });
171
220
  }
172
221
 
222
+ /**
223
+ * Perform device factory reset.
224
+ * @param {Boolean} [reboot=true] a flag that is passed to the device to indicate whether it should reboot after the factory reset. defaults to true.
225
+ * @return {Promise} Promise which is resolved when factoryReset has been successfully performed
226
+ * Failure to factoryReset for any reason, result in the promise being rejected.
227
+ */
173
228
  async factoryReset(reboot = true) {
174
229
  if (typeof reboot !== "boolean") {
175
230
  throw new Error("reboot param must be of type 'boolean'");
@@ -227,6 +282,12 @@ class DeviceManager extends DeviceManagerInterface {
227
282
  * @property {number} quality a measure of the signal quality, in the range 0 to 100 (the higher, the better). The quality value is derived from the signal EVM.
228
283
  * */
229
284
 
285
+ /**
286
+ * Get Wi-Fi info - access point data and status (the status is cached for 5 seconds)
287
+ * @returns {WiFiInfo} An object containing the Wi-Fi info
288
+ * @alpha API has not yet been released
289
+ * */
290
+ // This api is part of epic HSDEV-4185
230
291
  async getWifiInfo() {
231
292
  await Promise.all([getWifiApData(), getWifiStatus()]);
232
293
  return { ...wifi_ap_data, ...wifi_status };
@@ -234,7 +295,7 @@ class DeviceManager extends DeviceManagerInterface {
234
295
  }
235
296
 
236
297
  /**
237
-
298
+ *
238
299
  * @module
239
300
  * @example
240
301
  * import { deviceManager } from "senza-sdk";
@@ -1,6 +1,4 @@
1
- import { Lifecycle as LifecycleInterface } from "../interface/lifecycle";
2
- import { getPlatformInfo } from "./api";
3
- import { alarmManager } from "./alarmManager";
1
+ import { alarmManager, getPlatformInfo } from "./api";
4
2
  import {
5
3
  getFCID,
6
4
  isAudioSyncConfigured,
@@ -26,7 +24,76 @@ const DEFAULT_AUTO_BACKGROUND_ENABLED = false;
26
24
  * @fires userinactivity
27
25
  * @fires userdisconnected
28
26
  */
29
- class Lifecycle extends LifecycleInterface {
27
+ class Lifecycle extends EventTarget {
28
+
29
+ /**
30
+ * @typedef {Object} ConnectReason - The reason the ui app has been loaded
31
+ * @property {string} UNKNOWN
32
+ * @property {string} INITIAL_CONNECTION - Indicates that ui app has been loaded for the first time
33
+ * @property {string} APPLICATION_RELOAD - Indicates that ui app has been reloaded (e.g. after HOME keypress)
34
+ * @property {string} UI_RELEASE - Indicates that ui app has been reloaded after ui release
35
+ * @property {string} UI_TERMINATION - Indicates that ui app has been reloaded due to ui termination
36
+ * @property {string} WEBRTC_ERROR - Indicates that ui app has been reloaded due to webrtc error
37
+ * @property {string} UI_WATCHDOG - Indicates that ui app has been reloaded due to ui watchdog not receiving ui frames
38
+ */
39
+ ConnectReason = Object.freeze({
40
+ UNKNOWN: "unknown",
41
+ INITIAL_CONNECTION: "initial_connection",
42
+ APPLICATION_RELOAD: "reload_app",
43
+ UI_RELEASE: "ui_release",
44
+ UI_TERMINATION: "ui_termination",
45
+ WEBRTC_ERROR: "webrtc_error",
46
+ UI_WATCHDOG: "ui_watchdog"
47
+ });
48
+
49
+ /**
50
+ * @typedef {Object} UiState - The ui lifecycle state
51
+ * @property {string} UNKNOWN - state is unknown at this time
52
+ * @property {string} FOREGROUND - ui is displayed
53
+ * @property {string} IN_TRANSITION_TO_FOREGROUND - ui is about to be displayed
54
+ * @property {string} BACKGROUND - remote player is playing (full screen playback is displayed)
55
+ * @property {string} IN_TRANSITION_TO_BACKGROUND - remote player is about to be playing
56
+ */
57
+ UiState = Object.freeze({
58
+ UNKNOWN: "unknown",
59
+ FOREGROUND: "foreground",
60
+ IN_TRANSITION_TO_FOREGROUND: "inTransitionToForeground",
61
+ BACKGROUND: "background",
62
+ IN_TRANSITION_TO_BACKGROUND: "inTransitionToBackground"
63
+ });
64
+
65
+ /**
66
+ * @event Lifecycle#onstatechange
67
+ * @description Fired after transition from one state to another.<br>
68
+ * The flow is: foreground --> inTransitionToBackground --> background --> inTransitionToForeground --> foreground
69
+ * @property {UiState} state - Indicates the new state.
70
+ * @example
71
+ * lifecycle.addEventListener("onstatechange", (e) => {
72
+ * console.log("new state is", e.state);
73
+ * });
74
+ */
75
+
76
+ /**
77
+ * @event Lifecycle#userinactivity
78
+ * @description Fired after the ui has been inactive (i.e. no key presses) for a configurable number of seconds.<br>
79
+ * @property {number} timeout - the number of seconds after which the application will be unloaded.
80
+ * @example
81
+ * lifecycle.addEventListener("userinactivity", (e) => {
82
+ * console.log(`Application will be unloaded in ${e.timeout} seconds`);
83
+ * });
84
+ * @alpha API has not yet been released
85
+ */
86
+
87
+ /**
88
+ * @event Lifecycle#userdisconnected
89
+ * @description Fired when the user session ends .
90
+ * This event is useful for cleaning up application state or saving data before the application closes. Event callback should return promise to ensure that the event is handled before the application is terminated
91
+ * @example
92
+ * lifecycle.addEventListener("userdisconnected", () => {
93
+ * console.log("User session ended, cleaning up application state");
94
+ * // Perform any necessary cleanup here
95
+ * });
96
+ */
30
97
  constructor() {
31
98
  super();
32
99
 
@@ -238,6 +305,15 @@ class Lifecycle extends LifecycleInterface {
238
305
  return this._autoBackgroundOnUIDelay;
239
306
  }
240
307
 
308
+ /**
309
+ * Configure lifecycle settings
310
+ * @param {Object} config - Configuration object
311
+ * @param {Object} [config.autoBackground] - Auto background settings
312
+ * @param {boolean} [config.autoBackground.enabled] - Enable/disable auto background
313
+ * @param {Object} [config.autoBackground.timeout] - Timeout settings
314
+ * @param {number|false} [config.autoBackground.timeout.playing=30] - Timeout in seconds when video is playing, false to disable
315
+ * @param {number|false} [config.autoBackground.timeout.idle=false] - Timeout in seconds when in UI mode, false to disable
316
+ */
241
317
  configure(config) {
242
318
  if (config?.autoBackground) {
243
319
  const { enabled, timeout } = config.autoBackground;
@@ -277,6 +353,15 @@ class Lifecycle extends LifecycleInterface {
277
353
  }
278
354
  }
279
355
 
356
+ /**
357
+ * Get the current configuration settings
358
+ * @returns {Object} The current configuration object
359
+ * @example
360
+ * const config = lifecycle.getConfiguration();
361
+ * console.log(config.autoBackground.enabled); // true/false
362
+ * console.log(config.autoBackground.timeout.playing); // 30
363
+ * console.log(config.autoBackground.timeout.idle); // false
364
+ */
280
365
  getConfiguration() {
281
366
  return {
282
367
  autoBackground: {
@@ -325,6 +410,10 @@ class Lifecycle extends LifecycleInterface {
325
410
  return Promise.resolve(true);
326
411
  }
327
412
 
413
+ /**
414
+ * Getter for returning the ui lifecycle state
415
+ * @returns {UiState} the current application lifecycle state
416
+ */
328
417
  get state() {
329
418
  if (!this._isInitialized) {
330
419
  this._state = this.UiState.UNKNOWN;
@@ -332,6 +421,10 @@ class Lifecycle extends LifecycleInterface {
332
421
  return this._state;
333
422
  }
334
423
 
424
+ /**
425
+ * Getter for returning the application connection reason
426
+ * @returns {ConnectReason} the application connection reason
427
+ */
335
428
  get connectReason() {
336
429
  if (!this._isInitialized) {
337
430
  this._connectReason = this.ConnectReason.UNKNOWN;
@@ -339,6 +432,11 @@ class Lifecycle extends LifecycleInterface {
339
432
  return this._connectReason;
340
433
  }
341
434
 
435
+ /**
436
+ * Getter for returning the event that triggered the reloading of the ui after ui has been released
437
+ * @returns {Object} trigger event
438
+ * @property {string} type - the type of the trigger event (e.g. keyPressEvent, videoPlaybackEvent)
439
+ * @property {object} data - data of the event, dependent on its type (e.g. keyPressEvent has data of keyValue) */
342
440
  get triggerEvent() {
343
441
  if (!this._isInitialized) {
344
442
  this._triggerEvent = {};
@@ -346,6 +444,14 @@ class Lifecycle extends LifecycleInterface {
346
444
  return this._triggerEvent;
347
445
  }
348
446
 
447
+ /**
448
+ * @deprecated Use `lifecycle.configure()` instead.
449
+ * Controls the autoBackground feature.<br>
450
+ * When enabled, the application will automatically move to the background state after a configurable
451
+ * period of inactivity. Use the `configure` method to set timeouts for video playback and UI states.
452
+ * @type {boolean}
453
+ * @see {@link Lifecycle#configure}
454
+ */
349
455
  set autoBackground(enabled) {
350
456
  this._autoBackground = enabled;
351
457
  if (this._isAutoBackgroundEnabled()) {
@@ -359,6 +465,14 @@ class Lifecycle extends LifecycleInterface {
359
465
  return this._autoBackground;
360
466
  }
361
467
 
468
+ /**
469
+ * @deprecated Use `lifecycle.configure()` instead.
470
+ * The number of seconds of user inactivity before the application moves to the background state while playing video.
471
+ * Use the `configure` method to set this timeout.
472
+ * @type {integer}
473
+ * @default 30
474
+ * @see {@link Lifecycle#configure}
475
+ */
362
476
  set autoBackgroundDelay(delay) {
363
477
  this._autoBackgroundOnVideoDelay = delay;
364
478
  if (this._isAutoBackgroundEnabled() && remotePlayer._isPlaying) {
@@ -370,6 +484,14 @@ class Lifecycle extends LifecycleInterface {
370
484
  return this._autoBackgroundOnVideoDelay;
371
485
  }
372
486
 
487
+ /**
488
+ * @deprecated Use `lifecycle.configure()` instead.
489
+ * The number of seconds of user inactivity before the application moves to the background state while in the UI (not playing).
490
+ * Use the `configure` method to set this timeout.
491
+ * @type {integer}
492
+ * @default -1
493
+ * @see {@link Lifecycle#configure}
494
+ */
373
495
  set autoBackgroundOnUIDelay(delay) {
374
496
  this._autoBackgroundOnUIDelay = delay;
375
497
  if (this._isAutoBackgroundEnabled() && !remotePlayer._isPlaying) {
@@ -412,6 +534,18 @@ class Lifecycle extends LifecycleInterface {
412
534
  this._countdown = null;
413
535
  }
414
536
 
537
+ /**
538
+ * @deprecated use lifecycle.state instead.
539
+ * Async function that returns the ui lifecycle state
540
+ * @returns {UiState} the current application lifecycle state
541
+ * @example
542
+ * try {
543
+ * const state = await lifecycle.getState();
544
+ * console.log("current state is", state);
545
+ * } catch (e) {
546
+ * console.error("getState failed", e);
547
+ * }
548
+ */
415
549
  getState() {
416
550
  if (window.cefQuery) {
417
551
  return new Promise((resolve, reject) => {
@@ -432,6 +566,14 @@ class Lifecycle extends LifecycleInterface {
432
566
  sdkLogger.warn("lifecycle getState is not supported if NOT running e2e");
433
567
  }
434
568
 
569
+ /**
570
+ * Once playback starts on the remote player,
571
+ * the application is moved from foreground to inTransitionToBackground and eventually to background.
572
+ * The application will need to call moveToForeground when it receives an event that needs the UI to be displayed again,
573
+ * for example a key press, a playback end-of-file or a playback error.
574
+ * @return {Promise} Promise which is resolved when the moveToForeground command has been successfully processed.
575
+ * Failure to process the moveToForeground command will result in the promise being rejected.
576
+ */
435
577
  moveToForeground() {
436
578
  if (window.cefQuery) {
437
579
  if (this._inTransition || this._state === this.UiState.FOREGROUND || this._state === this.UiState.IN_TRANSITION_TO_FOREGROUND) {
@@ -593,6 +735,17 @@ class Lifecycle extends LifecycleInterface {
593
735
  return Promise.resolve(false);
594
736
  }
595
737
 
738
+ /**
739
+ * This method moves the application to the background.
740
+ * It should be called after remotePlayer.play().
741
+ * As a consequence, remote player playback will be displayed in full screen.
742
+ * @example
743
+ * remotePlayer.load("https://example.com/video.mp4", 0);
744
+ * remotePlayer.play();
745
+ * lifecycle.moveToBackground();
746
+ * @return {Promise} Promise which is resolved when the moveToBackground command has been successfully processed.
747
+ * Failure to process the moveToBackground command will result in the promise being rejected.
748
+ */
596
749
  moveToBackground() {
597
750
  if (window.cefQuery) {
598
751
  if (this._inTransition || this._state === this.UiState.BACKGROUND || this._state === this.UiState.IN_TRANSITION_TO_BACKGROUND) {
@@ -616,6 +769,13 @@ class Lifecycle extends LifecycleInterface {
616
769
  return this._moveToBackground();
617
770
  }
618
771
 
772
+ /**
773
+ * Use this api to switch to another tenant (other than the home tenant) which will launch the application associated with the tenantId. The tenantId must be configured in the
774
+ * Senza platform. Switching to the home tenant should use the exitApplication().
775
+ * @param {string} tenantId The tenantId to switch
776
+ * @return {Promise} Promise which is resolved when the switchTenant command has been successfully processed.
777
+ * Failure to process the switchTenant command will result in the promise being rejected.
778
+ */
619
779
  switchTenant(tenantId) {
620
780
  if (tenantId && tenantId.length > 0) {
621
781
  if (tenantId === getPlatformInfo().sessionInfo?.tenantId) {
@@ -661,6 +821,11 @@ class Lifecycle extends LifecycleInterface {
661
821
  return Promise.reject("SwitchTenant requires a valid tenantId string parameter");
662
822
  }
663
823
 
824
+ /**
825
+ * Use this api to exit the application which will redirect the browser to the home tenant application.
826
+ * @return {Promise} Promise which is resolved when the exitApplication command has been successfully processed.
827
+ * Failure to process the exitApplication command will result in the promise being rejected.
828
+ */
664
829
  exitApplication() {
665
830
  if (window.cefQuery) {
666
831
  return new Promise((resolve, reject) => {
@@ -709,6 +874,12 @@ class Lifecycle extends LifecycleInterface {
709
874
  return Promise.reject("exitApplication is not supported if NOT running e2e");
710
875
  }
711
876
 
877
+ /**
878
+ * Add event listener for lifecycle events
879
+ * @param {string} type - The event type to listen for
880
+ * @param {Function} listener - The callback function. Listeners for 'userdisconnected' events should return a promise to ensure the event is processed before the application exits.
881
+ * @param {Object} options - Event listener options
882
+ */
712
883
  addEventListener(type, listener, options) {
713
884
  if (type === "userdisconnected") {
714
885
  // Use the event manager for userdisconnected events
@@ -719,7 +890,12 @@ class Lifecycle extends LifecycleInterface {
719
890
  }
720
891
  }
721
892
 
722
-
893
+ /**
894
+ * Remove event listener
895
+ * @param {string} type - The event type
896
+ * @param {Function} listener - The callback function to remove
897
+ * @param {Object} options - Event listener options
898
+ */
723
899
  removeEventListener(type, listener, options) {
724
900
  if (type === "userdisconnected") {
725
901
  // Use the event manager for userdisconnected events
@@ -1,12 +1,12 @@
1
- import { MessageManager as MessageManagerInterface } from "../interface/messageManager";
2
- import { getFCID, sdkLogger } from "./utils";
1
+
2
+ import {getFCID, sdkLogger} from "./utils";
3
3
 
4
4
  /**
5
5
  * MessageManager is a singleton class that manages the external messages received by the application. It fires custom events as "message" with the payload as the content
6
6
  * @fires MessageManager#message
7
7
  */
8
8
 
9
- class MessageManager extends MessageManagerInterface {
9
+ class MessageManager extends EventTarget {
10
10
 
11
11
  /**
12
12
  * @typedef {object} MessageDetails - object which contains the content of the message
@@ -34,7 +34,7 @@ class MessageManager extends MessageManagerInterface {
34
34
  super();
35
35
  typeof document !== "undefined" && document.addEventListener("hs/externalEvent", (e) => {
36
36
  sdkLogger.log("Got hs/externalEvent", JSON.stringify(e.detail));
37
- this.dispatchEvent(new CustomEvent("message", { detail: { eventName: e.detail.eventName, payload: e.detail.payload, fcid: e.detail.fcid } }));
37
+ this.dispatchEvent(new CustomEvent("message", {detail: {eventName: e.detail.eventName, payload: e.detail.payload, fcid: e.detail.fcid } }));
38
38
  });
39
39
  }
40
40
 
@@ -49,13 +49,13 @@ class MessageManager extends MessageManagerInterface {
49
49
  return new Promise((resolve, reject) => {
50
50
  if (window.cefQuery) {
51
51
  const FCID = getFCID();
52
- const logger = sdkLogger.withFields({ FCID });
52
+ const logger = sdkLogger.withFields({FCID});
53
53
  const message = {
54
54
  type: "registerGroupEvent",
55
55
  fcid: FCID,
56
56
  groups
57
57
  };
58
- const request = { target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message) };
58
+ const request = {target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message)};
59
59
  window.cefQuery({
60
60
  request: JSON.stringify(request),
61
61
  persistent: false,
@@ -1,12 +1,11 @@
1
- import { PlatformManager as PlatformManagerInterface } from "../interface/platformManager";
2
1
  import { sdkLogger } from "./utils";
3
- import { sessionInfo } from "./SessionInfo";
2
+ import {sessionInfo} from "./SessionInfo";
4
3
 
5
4
 
6
5
  /**
7
6
  * PlatformManager is a singleton class that manages the platform
8
7
  */
9
- class PlatformManager extends PlatformManagerInterface {
8
+ class PlatformManager extends EventTarget {
10
9
 
11
10
  constructor() {
12
11
  super();
@@ -23,7 +22,7 @@ class PlatformManager extends PlatformManagerInterface {
23
22
  get appConfig() {
24
23
  const sessionInfoObj = sessionInfo.sessionInfoObj;
25
24
  const appConfig = sessionInfoObj.homeSessionInfo?.["appConfig"] || {};
26
- sdkLogger.info("PlatformManager get appConfig: \n" + JSON.stringify(appConfig, null, 2));
25
+ sdkLogger.info("PlatformManager get appConfig: \n" + JSON.stringify(appConfig, null,2));
27
26
  return appConfig;
28
27
  }
29
28
 
@@ -36,7 +35,7 @@ class PlatformManager extends PlatformManagerInterface {
36
35
  */
37
36
  setTimezone(timezone) {
38
37
  if (window.cefQuery) {
39
- const request = { message: JSON.stringify({ type: "setTimeZone", timezone }), waitForResponse: false, target: "UI-Streamer" };
38
+ const request = {message: JSON.stringify({type: "setTimeZone", timezone}), waitForResponse: false, target: "UI-Streamer"};
40
39
  window.cefQuery({
41
40
  request: JSON.stringify(request),
42
41
  persistent: false,
@@ -1,4 +1,3 @@
1
- import { RemotePlayer as RemotePlayerInterface } from "../interface/remotePlayer";
2
1
  import {
3
2
  getFCID,
4
3
  isAudioSyncConfigured,
@@ -69,6 +68,7 @@ function setPlaybackInfo(playbackInfo) {
69
68
  * @typedef {Object} Config
70
69
  * @property {string} preferredAudioLanguage
71
70
  * @property {string} preferredSubtitlesLanguage
71
+ * @property {number} minSuggestedPresentationDelay - minimal delay allowed for live playback in seconds
72
72
  * @property {boolean} autoPlay - (Not implemented yet) upon loading start playing automatically
73
73
  */
74
74
 
@@ -79,11 +79,11 @@ function setPlaybackInfo(playbackInfo) {
79
79
  * @fires ended
80
80
  * @fires error
81
81
  * @fires onloadmodechange
82
+ * @fires playing
82
83
  * @fires seeking (Not implemented yet)
83
84
  * @fires seeked (Not implemented yet)
84
- * @fires loadedmetadata (Not implemented yet)
85
85
  */
86
- class RemotePlayer extends RemotePlayerInterface {
86
+ class RemotePlayer extends EventTarget {
87
87
  constructor() {
88
88
  super();
89
89
  /**
@@ -92,7 +92,8 @@ class RemotePlayer extends RemotePlayerInterface {
92
92
  */
93
93
  this._config = {
94
94
  preferredAudioLanguage: "",
95
- preferredSubtitlesLanguage: ""
95
+ preferredSubtitlesLanguage: "",
96
+ minSuggestedPresentationDelay: 0
96
97
  };
97
98
  /**
98
99
  * @type {string}
@@ -525,10 +526,10 @@ class RemotePlayer extends RemotePlayerInterface {
525
526
 
526
527
  /** setting values for properties in the player configuration using an object.
527
528
  * If the config does not support a property this is a no-op.
528
- * @param {Object} props the object with all the different properties to change
529
+ * @param {Config} props the object with all the different properties to change.
529
530
  * @example
530
531
  * remotePlayer.configure({ preferredAudioLanguage: 'en-US' })
531
- *
532
+ * remotePlayer.configure({ minSuggestedPresentationDelay: 6 })
532
533
  * */
533
534
  configure(props) {
534
535
  Object.entries(props).forEach(([key, value]) => {
@@ -897,6 +898,9 @@ class RemotePlayer extends RemotePlayerInterface {
897
898
  this._updateSeekListeners(video);
898
899
  }
899
900
  this._videoElement = video;
901
+
902
+ // Emit a custom event to notify about the attachment of the video element
903
+ this.dispatchEvent(new Event("videoelementattached"));
900
904
  }
901
905
  }
902
906
 
@@ -912,7 +916,7 @@ class RemotePlayer extends RemotePlayerInterface {
912
916
  /** Tell the remote player to load the given URL.
913
917
  * @param {string} url url to load
914
918
  * @param {number} [position] start position in seconds (if not provided, start from beginning (VOD) or current time (LTV))
915
- * @returns {Promise}
919
+ * @returns {Promise}
916
920
  * @throws {RemotePlayerError} error object contains code & msg
917
921
  *
918
922
  * */
@@ -977,6 +981,11 @@ class RemotePlayer extends RemotePlayerInterface {
977
981
  message.action = "load";
978
982
  message.audioLanguage = audioLanguage;
979
983
  message.subtitlesLanguage = subtitlesLanguage;
984
+ if (this.getConfiguration().minSuggestedPresentationDelay > 0) {
985
+ message.cloudPlayerParams = {
986
+ "mspd": this.getConfiguration().minSuggestedPresentationDelay
987
+ };
988
+ }
980
989
  } else {
981
990
  message.type = "setPlayableUri";
982
991
  }