senza-sdk 4.2.65-a3f8c5a.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/bundle.js +1 -1
  2. package/dist/bundle.js.LICENSE.txt +0 -4
  3. package/dist/implementation.bundle.js +2 -0
  4. package/dist/implementation.bundle.js.LICENSE.txt +57 -0
  5. package/package.json +16 -8
  6. package/src/api.js +258 -327
  7. package/src/{alarmManager.js → implementation/alarmManager.js} +15 -52
  8. package/src/implementation/api.js +363 -0
  9. package/src/{deviceManager.js → implementation/deviceManager.js} +6 -78
  10. package/src/{lifecycle.js → implementation/lifecycle.js} +14 -192
  11. package/src/implementation/messageManager.js +55 -0
  12. package/src/{platformManager.js → implementation/platformManager.js} +5 -23
  13. package/src/{remotePlayer.js → implementation/remotePlayer.js} +5 -276
  14. package/src/{senzaShakaPlayer.js → implementation/senzaShakaPlayer.js} +8 -120
  15. package/src/{utils.js → implementation/utils.js} +15 -6
  16. package/src/interface/alarmManager.js +76 -0
  17. package/src/interface/api.js +8 -0
  18. package/src/interface/deviceManager.js +143 -0
  19. package/src/interface/lifecycle.js +284 -0
  20. package/src/interface/messageManager.js +54 -0
  21. package/src/interface/platformManager.js +42 -0
  22. package/src/interface/remotePlayer.js +469 -0
  23. package/src/interface/senzaShakaPlayer.js +168 -0
  24. package/src/interface/utils.js +45 -0
  25. package/src/messageManager.js +0 -88
  26. /package/src/{SessionInfo.js → implementation/SessionInfo.js} +0 -0
  27. /package/src/{devHelper.js → implementation/devHelper.js} +0 -0
  28. /package/src/{eventListenersManager.js → implementation/eventListenersManager.js} +0 -0
  29. /package/src/{subtitlesUtils.js → implementation/subtitlesUtils.js} +0 -0
  30. /package/src/{devSequence.js → interface/devSequence.js} +0 -0
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line no-unused-vars
2
+ import { RemotePlayer as RemotePlayerInterface, RemotePlayerError as RemotePlayerErrorInterface, Config } from "../interface/remotePlayer";
1
3
  import {
2
4
  getFCID,
3
5
  isAudioSyncConfigured,
@@ -27,11 +29,7 @@ const cloneDeep = (element) => {
27
29
  return JSON.parse(JSON.stringify(element));
28
30
  };
29
31
 
30
- // TODO: check that the link below to the error list is working on dashreadme
31
- /** Error object to be thrown on remotePlayer api failures.
32
- * [See error list]{@link RemotePlayer#error}
33
- */
34
- export class RemotePlayerError extends Error {
32
+ export class RemotePlayerError extends RemotePlayerErrorInterface {
35
33
  constructor(code, message) {
36
34
  super(message);
37
35
  this.code = code;
@@ -63,27 +61,7 @@ function setPlaybackInfo(playbackInfo) {
63
61
  }
64
62
  }
65
63
 
66
-
67
- /**
68
- * @typedef {Object} Config
69
- * @property {string} preferredAudioLanguage
70
- * @property {string} preferredSubtitlesLanguage
71
- * @property {number} minSuggestedPresentationDelay - minimal delay allowed for live playback in seconds
72
- * @property {boolean} autoPlay - (Not implemented yet) upon loading start playing automatically
73
- */
74
-
75
- /**
76
- * RemotePlayer a singleton class to communicate with remote player
77
- * @fires timeupdate
78
- * @fires tracksupdate
79
- * @fires ended
80
- * @fires error
81
- * @fires onloadmodechange
82
- * @fires playing
83
- * @fires seeking (Not implemented yet)
84
- * @fires seeked (Not implemented yet)
85
- */
86
- class RemotePlayer extends EventTarget {
64
+ class RemotePlayer extends RemotePlayerInterface {
87
65
  constructor() {
88
66
  super();
89
67
  /**
@@ -163,56 +141,11 @@ class RemotePlayer extends EventTarget {
163
141
  */
164
142
  this._isPlaying = false;
165
143
 
166
- /**
167
- * @type {string}
168
- * @description the last set blackout time as epoch seconds.
169
- * @private
170
- */
171
- this._blackoutTime = undefined;
172
-
173
- /**
174
- * @event RemotePlayer#canplay
175
- * @description canplay event will be dispatched when the remote player can start play the event
176
- * @example
177
- * remotePlayer.addEventListener("canplay", () => {
178
- * console.info("remotePlayer canplay");
179
- * remotePlayer.play();
180
- * });
181
- * */
182
-
183
- /**
184
- * @event RemotePlayer#playing
185
- * @description playing event will be dispatched when the remote player started playback of the first audio frame. This event can be used to synchronize the local player with the remote player.
186
- * @example
187
- * remotePlayer.addEventListener("playing", () => {
188
- * console.info("remotePlayer playing");
189
- * });
190
- * */
191
-
192
- /**
193
- * @event RemotePlayer#loadedmetadata
194
- * @description loadedmetadata event will be dispatched when the remote player metadata is loaded
195
- * and the audio/video tracks are available
196
- * @example
197
- * remotePlayer.addEventListener("loadedmetadata", () => {
198
- * console.info("remotePlayer loadedmetadata", remotePlayer.getAudioTracks(), remotePlayer.getTextTracks());
199
- * });
200
- * */
201
144
  typeof document !== "undefined" && document.addEventListener("hs/remotePlayerEvent", (e) => {
202
145
  sdkLogger.info("Got hs/remotePlayerEvent event with detail", JSON.stringify(e?.detail));
203
146
  this.dispatchEvent(new Event(e?.detail?.eventName));
204
147
  });
205
148
 
206
- /**
207
- *
208
- * @event RemotePlayer#timeupdate
209
- * @example
210
- * remotePlayer.addEventListener("timeupdate", () => {
211
- * console.info("remotePlayer timeupdate", remotePlayer.currentTime);
212
- * localPlayer.getMediaElement().currentTime = remotePlayer.currentTime || 0;
213
- * });
214
- *
215
- */
216
149
  typeof document !== "undefined" && document.addEventListener("hs/playbackInfoEvent", () => {
217
150
  sdkLogger.info("Got hs/playbackInfoEvent");
218
151
  // When attached, the sdk controls the synchronization between the local and remote player.
@@ -226,15 +159,6 @@ class RemotePlayer extends EventTarget {
226
159
  }
227
160
  });
228
161
 
229
- /**
230
- *
231
- * @event RemotePlayer#tracksupdate
232
- * @example
233
- * remotePlayer.addEventListener("tracksupdate", () => {
234
- * console.info("remotePlayer tracksupdate", remotePlayer.getAudioTracks(), remotePlayer.getTextTracks());
235
- * });
236
- *
237
- */
238
162
  typeof document !== "undefined" && document.addEventListener("hs/playback", (e) => {
239
163
  sdkLogger.info("Got hs/playback event with detail", JSON.stringify(e?.detail));
240
164
  this._availabilityStartTime = e?.detail?.availabilityStartTime;
@@ -242,13 +166,6 @@ class RemotePlayer extends EventTarget {
242
166
  this.dispatchEvent(new Event("tracksupdate"));
243
167
  });
244
168
 
245
- /**
246
- * @event RemotePlayer#ended
247
- * @example
248
- * remotePlayer.addEventListener("ended", () => {
249
- * console.info("remotePlayer ended");
250
- * });
251
- */
252
169
  typeof document !== "undefined" && document.addEventListener("hs/EOS", () => {
253
170
  sdkLogger.info("Got hs/EOS event");
254
171
  this.dispatchEvent(new Event("ended"));
@@ -281,72 +198,7 @@ class RemotePlayer extends EventTarget {
281
198
  sdkLogger.info(`Adding ${event.detail} seconds, previousTime=${previousCurrentTime} currentTime=${this._videoElement.currentTime}`);
282
199
  });
283
200
 
284
- /**
285
- *
286
- * @event RemotePlayer#error
287
- * @type {object}
288
- * @property {int} detail.errorCode
289
- * @property {string} detail.message
290
- *
291
- * @see Possible error codes:
292
- *
293
- * | Code | Domain | Description |
294
- * | :-------- | :---------------- | :-----------------------------------------------------------------------------------------------|
295
- * | 23 | Player | load() failed due to remote player initialization error |
296
- * | 98 | Player | load() failed due to remote player failure to send message to the client |
297
- * | 99 | Player | load() failed due to remote player reporting invalid message |
298
- * | 1000 | Encrypted content | Failed to create or initialise the CDM |
299
- * | 1001 | Encrypted content | Failed to create a CDM session |
300
- * | 1002 | Encrypted content | CDM failed to generate a license request |
301
- * | 1003 | Encrypted content | The CDM rejected the license server response |
302
- * | 1004 | Encrypted content | The CDM rejected the license server certificate |
303
- * | 1005 | Encrypted content | All keys in the license have expired |
304
- * | 1006 | Encrypted content | Output device is incompatible with the license requirements (HDCP) |
305
- * | 1007 | Encrypted content | The device has been revoked |
306
- * | 1008 | Encrypted content | The device secrets aren't available |
307
- * | 1009 | Encrypted content | Keys are loaded but the KID requested by playback isn't found. The app has likely issued a license for the wrong content or there is a mismatch between the KIDs in the license and the data plane |
308
- * | 1010 | Encrypted content | The CDM failed to provision, therefore it is not possible to play encrypted content |
309
- * | 1100 | Encrypted content | The CDM session has already received a license response. The app has likely issued 2, or more, license responses for the same request. The subsequent licenses will be ignored so this error is informational only |
310
- * | 1101 | Encrypted content | The license has been rejected since an error was received by the CDM. The app has likely sent a non-200 code to `WriteLicenseResponse` |
311
- * | 1102 | Encrypted content | A license response wasn't received from the app within a pre-defined timeout |
312
- * | 1103 | Encrypted content | The CDM session associated with this license response is in an invalid state. This is an internal Senza platform error |
313
- * | 1104 | Encrypted content | The CDM failed to send a license request to the app. This is an internal Senza platform error |
314
- * | 1999 | Encrypted content | An unknown encrypted content error |
315
- * | 2000 | Player | Content makes reference to no or unsupported key system |
316
- * | 3000 | Player | Unexpected problem with playback, only used if no more specific code in 3xxx range applies |
317
- * | 3001 | Player | Problem accessing content manifest, only used if no more specific code in 8xxx range applies |
318
- * | 3002 | Player | Unexpectedly stopped playback |
319
- * | 3100 | Player | Problem parsing MP4 content |
320
- * | 3200 | Player | Problem with decoder |
321
- * | 3300 | Player | DRM keys unavailable, player waited for keys but none arrived |
322
- * | 3400 | Player | Problem accessing segments, only used if no more specific code in 34xx range applies |
323
- * | 3401 | Player | Problem accessing segments, connection issue or timeout |
324
- * | 3402 | Player | Problem accessing segments, server returned HTTP error code |
325
- * | 3403 | Player | Problem accessing segments, server authentication issue |
326
- * | 3404 | Player | Problem accessing segments, server returned not found |
327
- * | 3900-3999 | Player | Internal player error |
328
- * | 6000 | Player | The remote player api call has reached the configurable timeout with no response from the remote player |
329
- * | 6001 | Player | play() was called while the remote player is not loaded |
330
- * | 6002 | Player | load() was called while the application was in state 'background' or 'inTransitionToBackground' |
331
- * | 6500 | Player | remotePlayer api was called before initializing remotePlayer |
332
- * | 6501 | Player | load() was called while previous load/unload was still in progress |
333
- * | 6502 | Player | unload() was called while previous unload/load was still in progress |
334
- * | 8001 | Player | Error pulling manifest. bad parameters |
335
- * | 8002 | Player | Error pulling manifest. filters returned no data |
336
- * | 8003 | Player | Error pulling manifest. fetch error |
337
- * | 8004 | Player | Error pulling manifest. parse error |
338
- * | 8005 | Player | Error pulling manifest. stale manifest detected |
339
- * | 8006 | Player | Error updating manifest. internal cache error |
340
- * | 8007 | Player | Error updating manifest. internal error during backoff |
341
- * | 8008 | Player | Error pulling manifest. sidx parsing error |
342
- * | 8009 | Player | Error pulling manifest. internal error |
343
- *
344
- * @example
345
- * remotePlayer.addEventListener("error", (event) => {
346
- * console.error("received remotePlayer error:", event.detail.errorCode, event.detail.message);
347
- * });
348
- *
349
- */
201
+
350
202
  typeof document !== "undefined" && document.addEventListener("hs/ERR", (event) => {
351
203
  sdkLogger.info("Got hs/ERR event");
352
204
  delete event?.detail?.type; // type is always videoPlaybackEvent, so no need to pass it
@@ -354,58 +206,6 @@ class RemotePlayer extends EventTarget {
354
206
  this.dispatchEvent(new CustomEvent("error", event));
355
207
  });
356
208
 
357
- /**
358
- *
359
- * @event RemotePlayer#license-request
360
- * @description Fired whenever the platform requires a license to play encrypted content.
361
- * The Web App is responsible for passing the (opaque) license request blob to the license server and passing the (opaque) license server response to the CDM by calling the `writeLicenseResponse` method on the event.
362
- * @type {LicenseRequestEvent}
363
- * @property {object} detail - Object containing ievent data
364
- * @property {string} detail.licenseRequest - Base64 coded opaque license request. The app is responsible for decoding the request before sending to the license server. Note that after decoding, the request may still be in Base64 form and this form should be sent to the license server without further decoding
365
- * @property {writeLicenseResponse} writeLicenseResponse - Write the license server response to the platform
366
- * @example
367
- * Whilst the payload structure and access controls are specific to each license server implementation, the Widevine UAT license server requires no authentication and minimal payload formatting and therefore serves as a useful case study that may be adapted.
368
- *
369
- * remotePlayer.addEventListener("license-request", async (event) => {
370
- * console.log("Got license-request event");
371
- * const requestBuffer = event?.detail?.licenseRequest;
372
- * const requestBufferStr = String.fromCharCode.apply(null, new Uint8Array(requestBuffer));
373
- * console.log("License Request in base64:", requestBufferStr);
374
- * const decodedLicenseRequest = window.atob(requestBufferStr); // from base 64
375
- * const licenseRequestBytes = Uint8Array.from(decodedLicenseRequest, (l) => l.charCodeAt(0));
376
- * // call Google API
377
- * const res = await getLicenseFromServer(licenseRequestBytes.buffer);
378
- * console.log("Writing response to platform ", res.code, res.responseBody);
379
- * event.writeLicenseResponse(res.code, res.responseBody);
380
- * });
381
-
382
- * async function getLicenseFromServer(licenseRequest) {
383
- * console.log("Requesting License from Widevine server");
384
- * const response = await fetch("https://proxy.uat.widevine.com/proxy", {
385
- * "method": "POST",
386
- * "body": licenseRequest,
387
- * "headers" : {
388
- * "Content-Type": "application/octet-stream"
389
- * }
390
- * });
391
- * const code = response.status;
392
- * if (code !== 200) {
393
- * console.error("failed to to get response from widevine:", code);
394
- * const responseBody = await response.text();
395
- * console.error(responseBody);
396
- * return {code, responseBody};
397
- * }
398
- * const responseBody = await response.arrayBuffer();
399
- * console.info("Got response: ");
400
- * return {code, responseBody};
401
- * }
402
- **/
403
- /**
404
- * @function writeLicenseResponse
405
- * @param {number} statusCode - License server HTTP response code, e.g. 200, 401, etc. Must be 200 to indicate a successful license exchange.
406
- * @param {string} response - License server response as opaque binary data in an ArrayBuffer.
407
- *
408
- * */
409
209
  typeof document !== "undefined" && document.addEventListener("hs/getLicense", (event) => {
410
210
  sdkLogger.info("Got hs/getLicense event");
411
211
  const getLicenseEventData = event?.detail;
@@ -425,20 +225,6 @@ class RemotePlayer extends EventTarget {
425
225
  });
426
226
  }
427
227
 
428
- /**
429
- * @typedef {Object} LoadMode
430
- * @property {string} NOT_LOADED
431
- * @property {string} LOADING
432
- * @property {string} LOADED
433
- * @property {string} UNLOADING
434
- */
435
- LoadMode = Object.freeze({
436
- NOT_LOADED: "notLoaded",
437
- LOADING: "loading",
438
- LOADED: "loaded",
439
- UNLOADING: "unloading"
440
- });
441
-
442
228
  /** @private Initialize the remote player
443
229
  * @param {Object} uiStreamerSettings ui-streamer portion of the settings taken from session info
444
230
  * */
@@ -958,7 +744,6 @@ class RemotePlayer extends EventTarget {
958
744
  this._abortSetAudioLanguage = true;
959
745
  this._abortSetSubtitleLanguage = true;
960
746
  this._abortSeeking = true;
961
- this._blackoutTime = undefined;
962
747
  if (reset) {
963
748
  this._reset();
964
749
  }
@@ -1570,62 +1355,6 @@ class RemotePlayer extends EventTarget {
1570
1355
  }
1571
1356
  }
1572
1357
 
1573
- setBlackoutTime(blackoutTime) {
1574
-
1575
- if (!this._isInitialized) {
1576
- throw new RemotePlayerError(6500, "Cannot call setBlackoutTime() if remote player is not initialized");
1577
- }
1578
-
1579
- if (this._loadMode !== this.LoadMode.LOADED) {
1580
- throw new RemotePlayerError(6001, "Cannot call setBlackoutTime() if player is not loaded");
1581
- }
1582
-
1583
- if (window.cefQuery) {
1584
- const FCID = getFCID();
1585
- const logger = sdkLogger.withFields({ FCID });
1586
- logger.log("remotePlayer setBlackoutTime: sending screenBlackout action");
1587
- const message = {
1588
- type: "remotePlayer.screenBlackout",
1589
- class: "remotePlayer",
1590
- action: "screenBlackout",
1591
- fcid: FCID,
1592
- blackoutTime
1593
- };
1594
- const request = { target: "TC", waitForResponse: true, message: JSON.stringify(message) };
1595
- return new Promise((resolve, reject) => {
1596
- let timerId = 0;
1597
- const timeBeforeSendingRequest = Date.now();
1598
- const queryId = window.cefQuery({
1599
- request: JSON.stringify(request),
1600
- persistent: false,
1601
- onSuccess: () => {
1602
- this._blackoutTime = blackoutTime;
1603
- const duration = Date.now() - timeBeforeSendingRequest;
1604
- logger.withFields({ duration }).log(`setBlackoutTime completed successfully after ${duration} ms`);
1605
- timerId = clearTimer(timerId);
1606
- resolve();
1607
- },
1608
- onFailure: (code, msg) => {
1609
- const duration = Date.now() - timeBeforeSendingRequest;
1610
- logger.withFields({ duration }).log(`setBlackoutTime failed after ${duration} ms. Error code: ${code}, error message: ${msg}`);
1611
- timerId = clearTimer(timerId);
1612
- reject(new RemotePlayerError(code, msg));
1613
- }
1614
- });
1615
-
1616
- logger.log(`window.cefQuery for setBlackoutTime returned query id ${queryId}`);
1617
- const timeout = this._remotePlayerConfirmationTimeout + 1000;
1618
- timerId = setTimeout(() => {
1619
- logger.log(`setBlackoutTime reached timeout of ${timeout} ms, canceling query id ${queryId}`);
1620
- window.cefQueryCancel(queryId);
1621
- reject(new RemotePlayerError(6000, `setBlackoutTime reached timeout of ${timeout} ms`));
1622
- }, timeout, queryId);
1623
- });
1624
- }
1625
- sdkLogger.error("remotePlayer setBlackoutTime: window.cefQuery is undefined");
1626
- return Promise.resolve(undefined);
1627
- }
1628
-
1629
1358
  /**
1630
1359
  * Getter/Setter for currentTime
1631
1360
  */
@@ -1,4 +1,5 @@
1
- import * as shaka from "shaka-player";
1
+ import { SenzaShakaPlayer as SenzaShakaInterface, shaka } from "../interface/senzaShakaPlayer";
2
+
2
3
  import { remotePlayer, lifecycle, getPlatformInfo } from "./api";
3
4
  import { sdkLogger, iso6393to1 } from "./utils";
4
5
  import moment from "moment";
@@ -32,31 +33,7 @@ class SenzaError extends shaka.util.Error {
32
33
  }
33
34
 
34
35
 
35
- // Copy the shaka module and replace the Player class with SenzaShakaPlayer
36
- // if we don't Copy the shaka module, the Player class will be replaced for all the other modules that import shaka
37
- const senzaShaka = { ...shaka };
38
-
39
-
40
- /**
41
- * SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
42
- *
43
- * @class SenzaShakaPlayer
44
- *
45
- * @example
46
- * import { SenzaShakaPlayer } from "./senzaShakaPlayer.js";
47
- *
48
- * try {
49
- * const videoElement = document.getElementById("video");
50
- * const player = new SenzaShakaPlayer(videoElement);
51
- * await player.load("http://playable.url/file.mpd");
52
- * await videoElement.play(); // will start the playback
53
- *
54
- * } catch (err) {
55
- * console.error("SenzaShakaPlayer failed with error", err);
56
- * }
57
- */
58
-
59
- export class SenzaShakaPlayer extends shaka.Player {
36
+ export class SenzaShakaPlayer extends SenzaShakaInterface {
60
37
  /** @private {SenzaShakaPlayer|null} Previous instance of the player */
61
38
  static _prevInstance = null;
62
39
 
@@ -141,7 +118,7 @@ export class SenzaShakaPlayer extends shaka.Player {
141
118
  });
142
119
  }
143
120
  },
144
- "pause" : () => {
121
+ "pause": () => {
145
122
  this._resetPlayPromise();
146
123
  this.remotePlayer.pause()
147
124
  .catch(error => {
@@ -187,7 +164,7 @@ export class SenzaShakaPlayer extends shaka.Player {
187
164
  originatesFromRemotePlayer: true
188
165
  };
189
166
 
190
- const response = await this.getNetworkingEngine().request(senzaShaka.net.NetworkingEngine.RequestType.LICENSE, request).promise;
167
+ const response = await this.getNetworkingEngine().request(shaka.net.NetworkingEngine.RequestType.LICENSE, request).promise;
191
168
 
192
169
  let responseBody = response.data;
193
170
  if (response.status < 200 || response.status >= 300) {
@@ -346,14 +323,6 @@ export class SenzaShakaPlayer extends shaka.Player {
346
323
  return undefined;
347
324
  }
348
325
 
349
- /**
350
- * Creates an instance of SenzaShakaPlayer, which is a subclass of shaka.Player.
351
- *
352
- * @param {HTMLVideoElement} videoElement - The video element to be used for local playback. This parameter is optional. If not provided, the video element can be attached later using the attach method.
353
- * @param {HTMLElement=} videoContainer - The videoContainer to construct UITextDisplayer
354
- * @param {function(shaka.Player)=} dependencyInjector Optional callback
355
- * which is called to inject mocks into the Player. Used for testing.
356
- */
357
326
  constructor(videoElement, videoContainer, dependencyInjector) {
358
327
  super(videoElement, videoContainer, dependencyInjector);
359
328
 
@@ -371,7 +340,7 @@ export class SenzaShakaPlayer extends shaka.Player {
371
340
  this._addRemotePlayerEventListeners();
372
341
  SenzaShakaPlayer._prevInstance = this;
373
342
  const playTimeout = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"]?.playingEventTimeout;
374
- this._playingTimeout = (playTimeout >= 0) ? playTimeout*1000 : this._playingTimeout;
343
+ this._playingTimeout = (playTimeout >= 0) ? playTimeout * 1000 : this._playingTimeout;
375
344
 
376
345
  // Initialize minSuggestedPresentationDelay from UI settings or use default
377
346
  const uiSettings = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"];
@@ -451,27 +420,11 @@ export class SenzaShakaPlayer extends shaka.Player {
451
420
  this._attachVideoElementToRemotePlayer();
452
421
  }
453
422
 
454
- /**
455
- * Overrides the attach method of shaka.Player to attach the video element.
456
- *
457
- * @param {HTMLVideoElement} videoElement - The video element to be used for local playback.
458
- * @param {boolean} [initializeMediaSource=true] - Whether to initialize the media source.
459
- */
460
423
  async attach(videoElement, initializeMediaSource = true) {
461
424
  await super.attach(videoElement, initializeMediaSource);
462
425
  this._attach(videoElement);
463
426
  }
464
427
 
465
- /**
466
- * Detach the player from the current media element. Leaves the player in a
467
- * state where it cannot play media, until it has been attached to something
468
- * else.
469
- *
470
- * @param {boolean=} keepAdManager
471
- *
472
- * @return {!Promise}
473
- * @export
474
- */
475
428
  async detach(keepAdManager = false) {
476
429
  // Clear any pending timeout
477
430
  this._resetPlayPromise();
@@ -502,14 +455,6 @@ export class SenzaShakaPlayer extends shaka.Player {
502
455
  this.videoElement = null;
503
456
  }
504
457
 
505
- /**
506
- * Unloads the currently playing stream, if any.
507
- *
508
- * @param {boolean=} initializeMediaSource
509
- * @param {boolean=} keepAdManager
510
- * @return {!Promise}
511
- * @export
512
- */
513
458
  async unload(initializeMediaSource = true, keepAdManager = false) {
514
459
  // Call the remote player's unload method
515
460
  try {
@@ -524,27 +469,14 @@ export class SenzaShakaPlayer extends shaka.Player {
524
469
  await super.unload(initializeMediaSource, keepAdManager);
525
470
  }
526
471
 
527
- /**
528
- * Overrides the getTextTracks method to use the remote player's text tracks.
529
- * @returns {Array} An array of text tracks.
530
- */
531
472
  getTextLanguages() {
532
473
  return Object.keys(this._textTracksMap);
533
474
  }
534
475
 
535
- /**
536
- * Overrides the getAudioTracks method to use the remote player's audio tracks.
537
- * @returns {Array} An array of audio tracks.
538
- */
539
476
  getAudioLanguages() {
540
477
  return Object.keys(this._audioTracksMap);
541
478
  }
542
479
 
543
- /**
544
- * Overrides the selectAudioLanguage method to use the remote player's audio track selection.
545
- * @param {string} language - The language to select.
546
- * @param {string=} role - The role of the track to select. (e.g. 'main', 'caption', or 'commentary')
547
- */
548
480
  selectAudioLanguage(language, role) {
549
481
  sdkLogger.log("Selecting audio language:", language, "with role: ", role);
550
482
  if (this._audioTracksMap[language]) {
@@ -555,11 +487,6 @@ export class SenzaShakaPlayer extends shaka.Player {
555
487
  super.selectAudioLanguage(language, role);
556
488
  }
557
489
 
558
- /**
559
- * Overrides the selectTextLanguage method to use the remote player's text track selection.
560
- * @param {string} language - The language to select.
561
- * @param {string=} role - The role of the track to select.
562
- */
563
490
  selectTextLanguage(language, role) {
564
491
  sdkLogger.log("Selecting text language:", language, "with role:", role);
565
492
  if (this._textTracksMap[language]) {
@@ -570,20 +497,12 @@ export class SenzaShakaPlayer extends shaka.Player {
570
497
  super.selectTextLanguage(language, role);
571
498
  }
572
499
 
573
- /**
574
- * Overrides the setTextTrackVisibility method to use the remote player's text track visibility settings.
575
- * @param {boolean} visible - Whether the text tracks should be visible.
576
- */
577
500
  setTextTrackVisibility(visible) {
578
501
  sdkLogger.log("Setting text track visibility to:", visible);
579
502
  remotePlayer.setTextTrackVisibility(visible);
580
503
  super.setTextTrackVisibility(visible);
581
504
  }
582
505
 
583
- /**
584
- * Helper function that makes it easier to check if lifecycle.state is
585
- * either background or inTransitionToBackground.
586
- */
587
506
  get isInRemotePlayback() {
588
507
  return lifecycle.state === lifecycle.UiState.BACKGROUND || lifecycle.state === lifecycle.UiState.IN_TRANSITION_TO_BACKGROUND;
589
508
  }
@@ -649,12 +568,6 @@ export class SenzaShakaPlayer extends shaka.Player {
649
568
  this.dispatchEvent(new shaka.util.FakeEvent("error", errorMap));
650
569
  }
651
570
 
652
- /**
653
- * Loads a media URL into both local and remote players.
654
- *
655
- * @param {string} url - The URL of the media to load.
656
- * @returns {Promise<void>}
657
- */
658
571
  async load(url, startTime, mimeType) {
659
572
 
660
573
  // Create a promise that will resolve when _remotePlayerLoad is called
@@ -741,13 +654,6 @@ export class SenzaShakaPlayer extends shaka.Player {
741
654
 
742
655
  }
743
656
 
744
- /***
745
- *
746
- * Configure the Player instance.
747
- * @param {Object} config the configuration object
748
- * @returns {Boolean}
749
- */
750
-
751
657
  async destroy() {
752
658
  await lifecycle.moveToForeground();
753
659
  SenzaShakaPlayer._prevInstance = null;
@@ -755,10 +661,6 @@ export class SenzaShakaPlayer extends shaka.Player {
755
661
  return super.destroy();
756
662
  }
757
663
 
758
- /**
759
- * A temporary override for older versions of Shaka.
760
- * Senza doesn't support out-of-band subtitles
761
- */
762
664
  addTextTrack(uri, language, kind, mimeType, codec, label, forced = false) {
763
665
  sdkLogger.warn("addTextTrack is deprecated, please use addTextTrackAsync");
764
666
  super.addTextTrackAsync(uri, language, kind, mimeType, codec, label, forced).then(subs => {
@@ -766,20 +668,6 @@ export class SenzaShakaPlayer extends shaka.Player {
766
668
  });
767
669
  }
768
670
 
769
- /**
770
- * Override the configure method to add custom configuration handling
771
- * Supports the following additional configuration options:
772
- * - shouldStopOnRemotePlayerError: boolean - If true, local player will be stopped on remote player error
773
- *
774
- * @override
775
- * @param {Object} config - Configuration object to be merged with existing config
776
- * @param {boolean} [config.shouldStopOnRemotePlayerError=true] - Whether to stop local player on remote player error
777
- * @example
778
- * player.configure({
779
- * shouldStopOnRemotePlayerError: false, // Don't stop local playback on remote player error
780
- * // ... other shaka configurations
781
- * });
782
- */
783
671
  configure(config) {
784
672
  sdkLogger.log("configure player with: ", JSON.stringify(config));
785
673
 
@@ -889,5 +777,5 @@ export class SenzaShakaPlayer extends shaka.Player {
889
777
 
890
778
  }
891
779
 
892
- senzaShaka.Player = SenzaShakaPlayer;
893
- export { senzaShaka as shaka };
780
+ shaka.Player = SenzaShakaPlayer;
781
+ export { shaka };
@@ -1,10 +1,15 @@
1
1
  import { getPlatformInfo } from "./api";
2
- import pack from "../package.json";
3
2
  import { sessionInfo } from "./SessionInfo";
4
- const { version } = pack;
5
3
 
6
4
  const REST_RESPONSE_TIMEOUT_SECONDS = 5;
7
5
 
6
+ export function getVersion() {
7
+ return typeof IMPLEMENTATION_VERSION !== "undefined"
8
+ // eslint-disable-next-line no-undef
9
+ ? IMPLEMENTATION_VERSION
10
+ : "unknown";
11
+ };
12
+
8
13
  export function getFCID() {
9
14
  return Math.round(Math.random() * 100000) + "-" + getPlatformInfo().sessionInfo?.connectionId;
10
15
  }
@@ -42,7 +47,7 @@ class SdkLogger {
42
47
  console.info(`[hs-sdk] [metrics] ${JSON.stringify(metricObj)}`);
43
48
  }
44
49
  withFields(logFields) {
45
- return new SdkLogger({...this.logFields, ...logFields});
50
+ return new SdkLogger({ ...this.logFields, ...logFields });
46
51
  }
47
52
  formatLogString(data) {
48
53
  let logString = "[hs-sdk] " + data.join(" ");
@@ -51,9 +56,13 @@ class SdkLogger {
51
56
  }
52
57
  return logString;
53
58
  }
59
+ addfields(fields) {
60
+ this.logFields = { ...this.logFields, ...fields };
61
+ return this;
62
+ }
54
63
  }
55
64
 
56
- export const sdkLogger = new SdkLogger({sdkVersion: version, url: window?.location?.href ?? ""});
65
+ export const sdkLogger = new SdkLogger({ sdkVersion: getVersion(), url: window?.location?.href ?? "" });
57
66
 
58
67
  export async function getRestResponse(messageName) {
59
68
 
@@ -64,14 +73,14 @@ export async function getRestResponse(messageName) {
64
73
 
65
74
  return new Promise((resolve, reject) => {
66
75
  const FCID = getFCID();
67
- const logger = sdkLogger.withFields({FCID});
76
+ const logger = sdkLogger.withFields({ FCID });
68
77
  const message = {
69
78
  type: "restRequest",
70
79
  name: messageName,
71
80
  method: "GET",
72
81
  fcid: FCID
73
82
  };
74
- const request = {target: "TC", waitForResponse: true, message: JSON.stringify(message)};
83
+ const request = { target: "TC", waitForResponse: true, message: JSON.stringify(message) };
75
84
  let timeoutHandler = 0;
76
85
  const queryId = window.cefQuery({
77
86
  request: JSON.stringify(request),