senza-sdk 4.2.51-60558b6.0 → 4.2.51-77d7fb8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "senza-sdk",
3
- "version": "4.2.51-60558b6.0",
3
+ "version": "4.2.51-77d7fb8.0",
4
4
  "main": "./src/api.js",
5
5
  "description": "API for Senza application",
6
6
  "license": "MIT",
@@ -695,7 +695,7 @@ class RemotePlayer extends EventTarget {
695
695
  return Promise.resolve(undefined);
696
696
  }
697
697
 
698
- _play() {
698
+ _play(streamType = StreamType.AUDIO) {
699
699
  if (window.cefQuery) {
700
700
  const FCID = getFCID();
701
701
  const logger = sdkLogger.withFields({ FCID });
@@ -719,7 +719,7 @@ class RemotePlayer extends EventTarget {
719
719
  if (this._remotePlayerApiVersion >= 2) {
720
720
  if (this._isAudioSyncEnabled()) {
721
721
  message.switchMode = SwitchMode.SEAMLESS;
722
- message.streamType = StreamType.AUDIO;
722
+ message.streamType = streamType;
723
723
  waitForResponse = true;
724
724
  } else {
725
725
  logger.log("remotePlayer play request ignored and will be sent with the lifecycle.moveToBackground()");
@@ -817,6 +817,52 @@ class RemotePlayer extends EventTarget {
817
817
  return Promise.resolve(undefined);
818
818
  }
819
819
 
820
+ _stop(streamType = StreamType.AUDIO) {
821
+ if (window.cefQuery) {
822
+ this._changePlayMode(false);
823
+ const FCID = getFCID();
824
+ const logger = sdkLogger.withFields({ FCID });
825
+ logger.log(`remotePlayer stop: sending stop action for streamType ${streamType}`);
826
+ const message = {
827
+ type: "remotePlayer.stop",
828
+ class: "remotePlayer",
829
+ action: "stop",
830
+ streamType: streamType,
831
+ fcid: FCID
832
+ };
833
+ const request = { target: "TC", waitForResponse: true, message: JSON.stringify(message) };
834
+ return new Promise((resolve, reject) => {
835
+ let timerId = 0;
836
+ const timeBeforeSendingRequest = Date.now();
837
+ const queryId = window.cefQuery({
838
+ request: JSON.stringify(request),
839
+ persistent: false,
840
+ onSuccess: () => {
841
+ const duration = Date.now() - timeBeforeSendingRequest;
842
+ logger.withFields({ duration }).log(`stop completed successfully after ${duration} ms`);
843
+ timerId = clearTimer(timerId);
844
+ resolve();
845
+ },
846
+ onFailure: (code, msg) => {
847
+ const duration = Date.now() - timeBeforeSendingRequest;
848
+ logger.withFields({ duration }).log(`stop failed after ${duration} ms. Error code: ${code}, error message: ${msg}`);
849
+ timerId = clearTimer(timerId);
850
+ reject(new RemotePlayerError(code, msg));
851
+ }
852
+ });
853
+ logger.log(`window.cefQuery for stop returned query id ${queryId}`);
854
+ const timeout = this._remotePlayerConfirmationTimeout + 1000;
855
+ timerId = setTimeout(() => {
856
+ logger.log(`stop reached timeout of ${timeout} ms, canceling query id ${queryId}`);
857
+ window.cefQueryCancel(queryId);
858
+ reject(new RemotePlayerError(6000, `stop reached timeout of ${timeout} ms`));
859
+ }, timeout, queryId);
860
+ });
861
+ }
862
+ sdkLogger.error("remotePlayer play: window.cefQuery is undefined");
863
+ return Promise.resolve(undefined);
864
+ }
865
+
820
866
  /** In order to support a seamless switch between the video in the UI and ABR, the web application must
821
867
  * register the video element being used for the currently played video before calling the load and play apis.
822
868
  * @param {object} video The video element currently playing video in the web application
@@ -1235,8 +1281,7 @@ class RemotePlayer extends EventTarget {
1235
1281
  case 2:
1236
1282
  return this._selectAudioTrackV2(audioTrackId, prevSelectedAudioTrack);
1237
1283
  default:
1238
- this._pendingAudioLanguage = audioTrackId;
1239
- return this._atomicSetAudioLanguage();
1284
+ return this._atomicSetAudioLanguage(audioTrackId, prevSelectedAudioTrack);
1240
1285
  }
1241
1286
  }
1242
1287
 
@@ -1283,11 +1328,10 @@ class RemotePlayer extends EventTarget {
1283
1328
  * Available only from v3 and on
1284
1329
  *
1285
1330
  * @param {string} audioTrackId - The ID of the audio track to select.
1286
- * @param {string} prevSelectedAudioTrack - The previously selected audio track ID.
1287
1331
  * @returns {Promise<void>} Resolves when the operation is complete.
1288
1332
  * */
1289
- async _selectAudioTrackV3(audioTrackId, prevSelectedAudioTrack) {
1290
- sdkLogger.log(`remotePlayer _selectAudioTrackV3: prevAudioTrack=${prevSelectedAudioTrack} audioTrackId=${audioTrackId} isPlaying=${this._isPlaying}`);
1333
+ async _selectAudioTrackV3(audioTrackId) {
1334
+ sdkLogger.log(`remotePlayer _selectAudioTrackV3: audioTrackId=${audioTrackId} isPlaying=${this._isPlaying}`);
1291
1335
  if (window.cefQuery) {
1292
1336
  const FCID = getFCID();
1293
1337
  const logger = sdkLogger.withFields({ FCID });
@@ -1373,8 +1417,7 @@ class RemotePlayer extends EventTarget {
1373
1417
  case 2:
1374
1418
  return this._selectTextTrackV2(textTrackId, prevSelectedTextTrack);
1375
1419
  default:
1376
- this._pendingSubtitleLanguage = textTrackId;
1377
- return this._atomicSetSubtitleLanguage();
1420
+ return this._atomicSetSubtitleLanguage(textTrackId, prevSelectedTextTrack);
1378
1421
  }
1379
1422
  }
1380
1423
 
@@ -1421,11 +1464,9 @@ class RemotePlayer extends EventTarget {
1421
1464
  * Available only from v3 and on
1422
1465
  *
1423
1466
  * @param {string} textTrackId - The ID of the text track to select.
1424
- * @param {string} prevSelectedTextTrack - The previously selected text track ID.
1425
1467
  * @returns {Promise<void>} Resolves when the operation is complete.
1426
1468
  * */
1427
- async _selectTextTrackV3(textTrackId, prevSelectedTextTrack) {
1428
- sdkLogger.log(`remotePlayer _selectTextTrackV3: prevAudioTrack=${prevSelectedTextTrack} textTrackId=${textTrackId} isPlaying=${this._isPlaying}`);
1469
+ async _selectTextTrackV3(textTrackId) {
1429
1470
  if (window.cefQuery) {
1430
1471
  const FCID = getFCID();
1431
1472
  const logger = sdkLogger.withFields({ FCID });
@@ -1435,7 +1476,7 @@ class RemotePlayer extends EventTarget {
1435
1476
  class: "remotePlayer",
1436
1477
  action: "setSubtitleLanguage",
1437
1478
  fcid: FCID,
1438
- language: textTrackId,
1479
+ language: textTrackId
1439
1480
  };
1440
1481
  const request = { target: "TC", waitForResponse: true, message: JSON.stringify(message) };
1441
1482
  return new Promise((resolve, reject) => {
@@ -1701,117 +1742,101 @@ class RemotePlayer extends EventTarget {
1701
1742
  sdkLogger.info("Seeking: local video element seeking end");
1702
1743
  }
1703
1744
 
1704
- async _atomicSetSubtitleLanguage() {
1705
- sdkLogger.info("SetSubtitleLanguage: local video element set start while isPLaying=", this._isPlaying);
1745
+ async _atomicSetAudioLanguage(audioTrackId, prevSelectedAudioTrack) {
1746
+ this._targetSetAudioPlayingState = this._isPlaying ? TargetPlayingState.PLAYING_UI : TargetPlayingState.PAUSED;
1706
1747
 
1707
- this._targetSetSubtitlePlayingState = this._isPlaying ? TargetPlayingState.PLAYING_UI : TargetPlayingState.PAUSED;
1708
- this._abortSetSubtitleLanguage = false;
1709
- this._isSetSubtitleByApplication = true;
1748
+ sdkLogger.log(`remotePlayer _atomicSetAudioLanguage: prevAudioTrack=${prevSelectedAudioTrack} audioTrackId=${audioTrackId} isPlaying=${this._isPlaying} targetState=${this._targetSetAudioPlayingState}`);
1710
1749
 
1711
- let state = SetSubtitleLanguageState.INIT;
1750
+ this._abortSetAudioLanguage = false;
1751
+ this._isSetAudioByApplication = true;
1712
1752
 
1713
- let previousPendingSubtitleLanguage = this._pendingSubtitleLanguage;
1714
- let initialSubtitleLanguage= this._pendingSubtitleLanguage;
1753
+ let state = SetAudioLanguageState.INIT;
1715
1754
  let res;
1716
1755
 
1717
- while (!this._abortSetSubtitleLanguage && state !== SetSubtitleLanguageState.DONE) {
1756
+ while (!this._abortSetAudioLanguage && state !== SetAudioLanguageState.DONE) {
1718
1757
  try {
1719
- // TODO - Implement the logic for setting audio language
1720
1758
  switch(state) {
1721
- case SetSubtitleLanguageState.INIT:
1722
- state = this._isPlaying ? SetSubtitleLanguageState.STOPPED : SetSubtitleLanguageState.SET;
1759
+ case SetAudioLanguageState.INIT:
1760
+ // always stop stream before changing language to flush current segments
1761
+ // because we cannot differentiate if player is paused/stopped
1762
+ state = SetAudioLanguageState.STOPPED;
1723
1763
  break;
1724
- case SetSubtitleLanguageState.STOPPED:
1725
- sdkLogger.error("BEFORE STOP BEFORE SET SUBTITLE");
1726
- await lifecycle.moveToForeground();
1727
- sdkLogger.error("AFTER STOP BEFORE SET SUBTITLE");
1728
- state = SetSubtitleLanguageState.SET;
1764
+ case SetAudioLanguageState.STOPPED:
1765
+ await this._stop(StreamType.AUDIO);
1766
+ state = SetAudioLanguageState.SET;
1729
1767
  break;
1730
- case SetSubtitleLanguageState.SET:
1731
- initialSubtitleLanguage = this._pendingSubtitleLanguage;
1732
- previousPendingSubtitleLanguage = this._selectedSubtitleTrack;
1733
- res = await this._selectTextTrackV3(initialSubtitleLanguage, previousPendingSubtitleLanguage);
1734
- sdkLogger.error("BEFORE PLAY AFTER SET SUBTITLE 1");
1735
- state = SetSubtitleLanguageState.DONE;
1768
+ case SetAudioLanguageState.SET:
1769
+ res = await this._selectAudioTrackV3(audioTrackId);
1770
+ // check if we need to resume playback or leave player state as is
1771
+ state = this._targetSetAudioPlayingState !== TargetPlayingState.PAUSED ? SetAudioLanguageState.PLAYING: SetAudioLanguageState.DONE;
1772
+ sdkLogger.log(`remotePlayer _atomicSetAudioLanguage: audioTrackId=${audioTrackId} isPlaying=${this._isPlaying} targetState=${this._targetSetAudioPlayingState}`);
1773
+ break;
1774
+ case SetAudioLanguageState.PLAYING:
1775
+ if (!this._abortSetAudioLanguage) {
1776
+ await this._play(StreamType.AUDIO);
1777
+ }
1778
+ state = SetAudioLanguageState.DONE;
1736
1779
  break;
1737
1780
  }
1738
1781
  } catch (error) {
1739
- sdkLogger.error(`Error during set subtitle process: ${error.message}`);
1740
- state = SetSubtitleLanguageState.DONE;
1782
+ sdkLogger.error(`remotePlayer _atomicSetAudioLanguage: audioTrackId=${audioTrackId} failed with error ${error.message}.`);
1783
+ state = SetAudioLanguageState.DONE;
1741
1784
  res = Promise.reject(error);
1742
- } finally {
1743
- sdkLogger.error("ABORT SET SUBTITLE", this._abortSetSubtitleLanguage);
1744
- if (!this._abortSetSubtitleLanguage) {
1745
- sdkLogger.error("TARGET PLAYING STATE", this._targetSetSubtitlePlayingState);
1746
- if (this._targetSetSubtitlePlayingState === TargetPlayingState.PLAYING_UI) {
1747
- sdkLogger.error("BEFORE PLAY AFTER SET SUBTITLE 2");
1748
- this._play();
1749
- } else if (this._targetSetSubtitlePlayingState === TargetPlayingState.PLAYING_ABR) {
1750
- sdkLogger.error("BEFORE MOVE_TO_BACKGROUND AFTER SET SUBTITLE");
1751
- lifecycle._moveToBackground();
1752
- }
1753
- }
1754
- this._isSetSubtitleByApplication = false;
1755
- sdkLogger.info("SetSubtitleLanguage: local video element set subtitle end");
1756
1785
  }
1757
1786
  }
1758
- return res
1759
- }
1760
1787
 
1761
- async _atomicSetAudioLanguage() {
1762
- sdkLogger.info("SetAudioLanguage: local video element set start while isPLaying=", this._isPlaying);
1788
+ this._isSetAudioByApplication = false;
1789
+ sdkLogger.log(`remotePlayer _atomicSetAudioLanguage: audioTrackId=${audioTrackId} ended.`);
1790
+ return res;
1791
+ }
1763
1792
 
1764
- this._targetSetAudioPlayingState = this._isPlaying ? TargetPlayingState.PLAYING_UI : TargetPlayingState.PAUSED;
1765
- this._abortSetAudioLanguage = false;
1766
- this._isSetAudioByApplication = true;
1793
+ async _atomicSetSubtitleLanguage(textTrackId, prevSelectedTextTrack) {
1794
+ this._targetSetSubtitlePlayingState = this._isPlaying ? TargetPlayingState.PLAYING_UI : TargetPlayingState.PAUSED;
1795
+ sdkLogger.log(`remotePlayer _atomicSetSubtitleLanguage: prevTextTrack=${prevSelectedTextTrack} textTrackId=${textTrackId} isPlaying=${this._isPlaying} targetState=${this._targetSetSubtitlePlayingState}`);
1767
1796
 
1768
- let state = SetAudioLanguageState.INIT;
1797
+ this._abortSetSubtitleLanguage = false;
1798
+ this._isSetSubtitleByApplication = true;
1769
1799
 
1770
- let previousPendingAudioLanguage = this._pendingAudioLanguage;
1771
- let initialAudioLanguage= this._pendingAudioLanguage;
1800
+ let state = SetSubtitleLanguageState.INIT;
1772
1801
  let res;
1773
-
1774
- while (!this._abortSetAudioLanguage && state !== SetAudioLanguageState.DONE) {
1802
+
1803
+ while (!this._abortSetSubtitleLanguage && state !== SetSubtitleLanguageState.DONE) {
1775
1804
  try {
1776
- // TODO - Implement the logic for setting audio language
1777
1805
  switch(state) {
1778
- case SetAudioLanguageState.INIT:
1779
- state = this._isPlaying ? SetAudioLanguageState.STOPPED : SetAudioLanguageState.SET;
1806
+ case SetSubtitleLanguageState.INIT:
1807
+ // always stop stream before changing language to flush current segments
1808
+ // because we cannot differentiate if player is paused/stopped
1809
+ state = SetSubtitleLanguageState.STOPPED;
1780
1810
  break;
1781
- case SetAudioLanguageState.STOPPED:
1782
- await lifecycle.moveToForeground();
1783
- state = SetAudioLanguageState.SET;
1811
+ case SetSubtitleLanguageState.STOPPED:
1812
+ await this._stop(StreamType.SUBTITLE);
1813
+ state = SetSubtitleLanguageState.SET;
1784
1814
  break;
1785
- case SetAudioLanguageState.SET:
1786
- initialAudioLanguage = this._pendingAudioLanguage;
1787
- previousPendingAudioLanguage = this._selectedAudioTrack;
1788
- res = await this._selectAudioTrackV3(initialAudioLanguage, previousPendingAudioLanguage);
1789
- sdkLogger.error("BEFORE PLAY AFTER SET AUDIO 1");
1790
- state = SetAudioLanguageState.DONE;
1815
+ case SetSubtitleLanguageState.SET:
1816
+ res = await this._selectTextTrackV3(textTrackId);
1817
+ // check if we need to resume playback or leave player state as is
1818
+ state = this._targetSetSubtitlePlayingState !== TargetPlayingState.PAUSED ? SetSubtitleLanguageState.PLAYING: SetSubtitleLanguageState.DONE;
1819
+ sdkLogger.log(`remotePlayer _atomicSetSubtitleLanguage: textTrackId=${textTrackId} isPlaying=${this._isPlaying} targetState=${this._targetSetSubtitlePlayingState}`);
1820
+ break;
1821
+ case SetSubtitleLanguageState.PLAYING:
1822
+ if (!this._abortSetSubtitleLanguage) {
1823
+ await this._play(StreamType.SUBTITLE | StreamType.AUDIO);
1824
+ }
1825
+ state = SetSubtitleLanguageState.DONE;
1791
1826
  break;
1792
1827
  }
1793
1828
  } catch (error) {
1794
- sdkLogger.error(`Error during set audio process: ${error.message}`);
1795
- state = SetAudioLanguageState.DONE;
1829
+ sdkLogger.error(`remotePlayer _atomicSetSubtitleLanguage: textTrackId=${textTrackId} failed with error ${error.message}.`);
1830
+ state = SetSubtitleLanguageState.DONE;
1796
1831
  res = Promise.reject(error);
1797
- } finally {
1798
- sdkLogger.error("ABORT SET AUDIO", this._abortSetAudioLanguage);
1799
- if (!this._abortSetAudioLanguage) {
1800
- sdkLogger.error("TARGET PLAYING STATE", this._targetSetAudioPlayingState);
1801
- if (this._targetSetAudioPlayingState === TargetPlayingState.PLAYING_UI) {
1802
- sdkLogger.error("BEFORE PLAY AFTER SET AUDIO 2");
1803
- this._play();
1804
- } else if (this._targetSetAudioPlayingState === TargetPlayingState.PLAYING_ABR) {
1805
- sdkLogger.error("BEFORE MOVE_TO_BACKGROUND AFTER SET AUDIO");
1806
- lifecycle._moveToBackground();
1807
- }
1808
- }
1809
- this._isSetAudioByApplication = false;
1810
- sdkLogger.info("SetAudioLanguage: local video element set audio end");
1811
1832
  }
1812
1833
  }
1813
- return res
1834
+
1835
+ this._isSetSubtitleByApplication = false;
1836
+ sdkLogger.log(`remotePlayer _atomicSetSubtitleLanguage: textTrackId=${textTrackId} ended.`);
1837
+ return res;
1814
1838
  }
1839
+
1815
1840
  }
1816
1841
  /**
1817
1842
  *
package/src/utils.js CHANGED
@@ -159,8 +159,7 @@ export const SetAudioLanguageState = Object.freeze({
159
159
  INIT: "init",
160
160
  STOPPED: "stopped",
161
161
  SET: "set",
162
- MULTI_SET: "multiSet",
163
- WAITING: "waiting",
162
+ PLAYING: "playing",
164
163
  DONE: "done"
165
164
  });
166
165
 
@@ -168,8 +167,7 @@ export const SetSubtitleLanguageState = Object.freeze({
168
167
  INIT: "init",
169
168
  STOPPED: "stopped",
170
169
  SET: "set",
171
- MULTI_SET: "multiSet",
172
- WAITING: "waiting",
170
+ PLAYING: "playing",
173
171
  DONE: "done"
174
172
  });
175
173