senza-sdk 4.3.1-e113d43.0 → 4.3.2-2e967be.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/dist/bundle.js +1 -1
- package/package.json +9 -8
- package/src/api.js +14 -2
- package/src/implementation/alarmManager.js +21 -0
- package/src/implementation/api.js +14 -13
- package/src/implementation/deviceManager.js +20 -1
- package/src/implementation/lifecycle.js +66 -57
- package/src/implementation/messageManager.js +17 -30
- package/src/implementation/platformManager.js +0 -19
- package/src/implementation/remotePlayer.js +86 -272
- package/src/implementation/senzaShakaPlayer.js +104 -127
- package/src/interface/alarmManager.js +29 -22
- package/src/interface/devSequence.js +35 -0
- package/src/interface/deviceManager.js +30 -20
- package/src/interface/lifecycle.js +46 -40
- package/src/interface/messageManager.js +36 -28
- package/src/interface/platformManager.js +13 -6
- package/src/interface/remotePlayer.js +208 -180
- package/src/interface/senzaShakaPlayer.js +2 -5
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { shaka } from "../interface/senzaShakaPlayer";
|
|
1
|
+
import { SenzaShakaPlayer as SenzaShakaInterface, shaka } from "../interface/senzaShakaPlayer";
|
|
2
2
|
|
|
3
3
|
import { remotePlayer, lifecycle, getPlatformInfo } from "./api";
|
|
4
4
|
import { sdkLogger, iso6393to1 } from "./utils";
|
|
5
|
+
import moment from "moment";
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
// Define custom error category
|
|
7
9
|
shaka.util.Error.Category.SENZA_PLAYER_ERROR = 50;
|
|
@@ -31,26 +33,7 @@ class SenzaError extends shaka.util.Error {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
* SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
|
|
36
|
-
*
|
|
37
|
-
* @class SenzaShakaPlayer
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* import { SenzaShakaPlayer } from "./senzaShakaPlayer.js";
|
|
41
|
-
*
|
|
42
|
-
* try {
|
|
43
|
-
* const videoElement = document.getElementById("video");
|
|
44
|
-
* const player = new SenzaShakaPlayer(videoElement);
|
|
45
|
-
* await player.load("http://playable.url/file.mpd");
|
|
46
|
-
* await videoElement.play(); // will start the playback
|
|
47
|
-
*
|
|
48
|
-
* } catch (err) {
|
|
49
|
-
* console.error("SenzaShakaPlayer failed with error", err);
|
|
50
|
-
* }
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
export class SenzaShakaPlayer extends shaka.Player {
|
|
36
|
+
export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
54
37
|
/** @private {SenzaShakaPlayer|null} Previous instance of the player */
|
|
55
38
|
static _prevInstance = null;
|
|
56
39
|
|
|
@@ -72,9 +55,9 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
72
55
|
* @private
|
|
73
56
|
* @type {number}
|
|
74
57
|
* @description Timeout in milliseconds to wait for playing event
|
|
75
|
-
* @default
|
|
58
|
+
* @default 4000
|
|
76
59
|
*/
|
|
77
|
-
_playingTimeout =
|
|
60
|
+
_playingTimeout = 4000;
|
|
78
61
|
|
|
79
62
|
/**
|
|
80
63
|
* @private
|
|
@@ -89,7 +72,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
89
72
|
* @description Whether to stop remote player on error
|
|
90
73
|
* @default false
|
|
91
74
|
*/
|
|
92
|
-
|
|
75
|
+
_shouldStopOnRemotePlayerError = false;
|
|
93
76
|
|
|
94
77
|
/**
|
|
95
78
|
* @private
|
|
@@ -135,7 +118,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
135
118
|
});
|
|
136
119
|
}
|
|
137
120
|
},
|
|
138
|
-
"pause"
|
|
121
|
+
"pause": () => {
|
|
139
122
|
this._resetPlayPromise();
|
|
140
123
|
this.remotePlayer.pause()
|
|
141
124
|
.catch(error => {
|
|
@@ -280,13 +263,15 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
280
263
|
|
|
281
264
|
|
|
282
265
|
/**
|
|
283
|
-
* Handles errors
|
|
266
|
+
* Handles errors received by remote player while waiting for the playing event.
|
|
267
|
+
* The promise returned to the call for video element play will be rejected.
|
|
284
268
|
* @private
|
|
285
269
|
* @param {Error} error - The error object.
|
|
286
270
|
*/
|
|
287
271
|
_handlePlayPromiseError(error) {
|
|
288
272
|
|
|
289
273
|
sdkLogger.error("Error while waiting for playing event:", error);
|
|
274
|
+
|
|
290
275
|
if (this._playPromiseReject) {
|
|
291
276
|
this._playPromiseReject(error);
|
|
292
277
|
this._playPromiseResolve = null;
|
|
@@ -296,16 +281,48 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
296
281
|
clearTimeout(this._playTimeoutId);
|
|
297
282
|
this._playTimeoutId = null;
|
|
298
283
|
}
|
|
284
|
+
|
|
299
285
|
}
|
|
300
286
|
|
|
301
287
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
* @
|
|
305
|
-
* @
|
|
306
|
-
* @param {function(shaka.Player)=} dependencyInjector Optional callback
|
|
307
|
-
* which is called to inject mocks into the Player. Used for testing.
|
|
288
|
+
* @private
|
|
289
|
+
* @type {number}
|
|
290
|
+
* @description Minimum suggested presentation delay in seconds
|
|
291
|
+
* @default 15
|
|
308
292
|
*/
|
|
293
|
+
_minSuggestedPresentationDelay = 15;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Modifies the suggestedPresentationDelay in the manifest text
|
|
297
|
+
* @private
|
|
298
|
+
* @param {string} manifestText - The MPD manifest text
|
|
299
|
+
* @returns {string} - Modified manifest text , or undefined if no modification was done
|
|
300
|
+
*/
|
|
301
|
+
_updateManifestDelayIfBelowMinimum(manifestText) {
|
|
302
|
+
// Look for suggestedPresentationDelay attribute
|
|
303
|
+
const match = manifestText.match(/suggestedPresentationDelay="([^"]+)"/);
|
|
304
|
+
if (match) {
|
|
305
|
+
const durationString = match[1];
|
|
306
|
+
const duration = moment.duration(durationString);
|
|
307
|
+
const currentDelay = duration.asSeconds();
|
|
308
|
+
|
|
309
|
+
sdkLogger.info(`Found suggestedPresentationDelay in manifest: ${currentDelay.toFixed(3)}s`);
|
|
310
|
+
|
|
311
|
+
if (currentDelay < this._minSuggestedPresentationDelay) {
|
|
312
|
+
// Replace the value in the manifest text with 3 decimal places
|
|
313
|
+
manifestText = manifestText.replace(
|
|
314
|
+
/suggestedPresentationDelay="[^"]+"/,
|
|
315
|
+
`suggestedPresentationDelay="PT${this._minSuggestedPresentationDelay.toFixed(3)}S"`
|
|
316
|
+
);
|
|
317
|
+
sdkLogger.info(`Updated manifest suggestedPresentationDelay to ${this._minSuggestedPresentationDelay.toFixed(3)}s`);
|
|
318
|
+
return manifestText;
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
sdkLogger.info("suggestedPresentationDelay is not defined at the manifest");
|
|
322
|
+
}
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
|
|
309
326
|
constructor(videoElement, videoContainer, dependencyInjector) {
|
|
310
327
|
super(videoElement, videoContainer, dependencyInjector);
|
|
311
328
|
|
|
@@ -323,7 +340,14 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
323
340
|
this._addRemotePlayerEventListeners();
|
|
324
341
|
SenzaShakaPlayer._prevInstance = this;
|
|
325
342
|
const playTimeout = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"]?.playingEventTimeout;
|
|
326
|
-
this._playingTimeout = (playTimeout >= 0) ? playTimeout*1000 : this._playingTimeout;
|
|
343
|
+
this._playingTimeout = (playTimeout >= 0) ? playTimeout * 1000 : this._playingTimeout;
|
|
344
|
+
|
|
345
|
+
// Initialize minSuggestedPresentationDelay from UI settings or use default
|
|
346
|
+
const uiSettings = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"];
|
|
347
|
+
if (uiSettings?.minSuggestedPresentationDelay !== undefined) {
|
|
348
|
+
this._minSuggestedPresentationDelay = uiSettings.minSuggestedPresentationDelay;
|
|
349
|
+
sdkLogger.info(`Using configured minSuggestedPresentationDelay: ${this._minSuggestedPresentationDelay}s`);
|
|
350
|
+
}
|
|
327
351
|
|
|
328
352
|
// if video element is provided, add the listeres here. In this case ,there is no need to call attach.
|
|
329
353
|
if (videoElement) {
|
|
@@ -331,8 +355,25 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
331
355
|
sdkLogger.warn("SenzaShakaPlayer constructor Adding videoElement in the constructor is going to be deprecated in the future. Please use attach method instead.");
|
|
332
356
|
}
|
|
333
357
|
|
|
358
|
+
this.configure({
|
|
359
|
+
manifest: {
|
|
360
|
+
defaultPresentationDelay: this._minSuggestedPresentationDelay // in seconds
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
remotePlayer.configure({
|
|
365
|
+
minSuggestedPresentationDelay: this._minSuggestedPresentationDelay
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
this.addEventListener("buffering", () => {
|
|
369
|
+
if (this.videoElement) {
|
|
370
|
+
sdkLogger.info("Buffering at time:", this.videoElement.currentTime);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
334
374
|
}
|
|
335
375
|
|
|
376
|
+
|
|
336
377
|
_attach(videoElement) {
|
|
337
378
|
this.videoElement = videoElement;
|
|
338
379
|
|
|
@@ -379,27 +420,11 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
379
420
|
this._attachVideoElementToRemotePlayer();
|
|
380
421
|
}
|
|
381
422
|
|
|
382
|
-
/**
|
|
383
|
-
* Overrides the attach method of shaka.Player to attach the video element.
|
|
384
|
-
*
|
|
385
|
-
* @param {HTMLVideoElement} videoElement - The video element to be used for local playback.
|
|
386
|
-
* @param {boolean} [initializeMediaSource=true] - Whether to initialize the media source.
|
|
387
|
-
*/
|
|
388
423
|
async attach(videoElement, initializeMediaSource = true) {
|
|
389
424
|
await super.attach(videoElement, initializeMediaSource);
|
|
390
425
|
this._attach(videoElement);
|
|
391
426
|
}
|
|
392
427
|
|
|
393
|
-
/**
|
|
394
|
-
* Detach the player from the current media element. Leaves the player in a
|
|
395
|
-
* state where it cannot play media, until it has been attached to something
|
|
396
|
-
* else.
|
|
397
|
-
*
|
|
398
|
-
* @param {boolean=} keepAdManager
|
|
399
|
-
*
|
|
400
|
-
* @return {!Promise}
|
|
401
|
-
* @export
|
|
402
|
-
*/
|
|
403
428
|
async detach(keepAdManager = false) {
|
|
404
429
|
// Clear any pending timeout
|
|
405
430
|
this._resetPlayPromise();
|
|
@@ -430,14 +455,6 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
430
455
|
this.videoElement = null;
|
|
431
456
|
}
|
|
432
457
|
|
|
433
|
-
/**
|
|
434
|
-
* Unloads the currently playing stream, if any.
|
|
435
|
-
*
|
|
436
|
-
* @param {boolean=} initializeMediaSource
|
|
437
|
-
* @param {boolean=} keepAdManager
|
|
438
|
-
* @return {!Promise}
|
|
439
|
-
* @export
|
|
440
|
-
*/
|
|
441
458
|
async unload(initializeMediaSource = true, keepAdManager = false) {
|
|
442
459
|
// Call the remote player's unload method
|
|
443
460
|
try {
|
|
@@ -452,27 +469,14 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
452
469
|
await super.unload(initializeMediaSource, keepAdManager);
|
|
453
470
|
}
|
|
454
471
|
|
|
455
|
-
/**
|
|
456
|
-
* Overrides the getTextTracks method to use the remote player's text tracks.
|
|
457
|
-
* @returns {Array} An array of text tracks.
|
|
458
|
-
*/
|
|
459
472
|
getTextLanguages() {
|
|
460
473
|
return Object.keys(this._textTracksMap);
|
|
461
474
|
}
|
|
462
475
|
|
|
463
|
-
/**
|
|
464
|
-
* Overrides the getAudioTracks method to use the remote player's audio tracks.
|
|
465
|
-
* @returns {Array} An array of audio tracks.
|
|
466
|
-
*/
|
|
467
476
|
getAudioLanguages() {
|
|
468
477
|
return Object.keys(this._audioTracksMap);
|
|
469
478
|
}
|
|
470
479
|
|
|
471
|
-
/**
|
|
472
|
-
* Overrides the selectAudioLanguage method to use the remote player's audio track selection.
|
|
473
|
-
* @param {string} language - The language to select.
|
|
474
|
-
* @param {string=} role - The role of the track to select. (e.g. 'main', 'caption', or 'commentary')
|
|
475
|
-
*/
|
|
476
480
|
selectAudioLanguage(language, role) {
|
|
477
481
|
sdkLogger.log("Selecting audio language:", language, "with role: ", role);
|
|
478
482
|
if (this._audioTracksMap[language]) {
|
|
@@ -483,11 +487,6 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
483
487
|
super.selectAudioLanguage(language, role);
|
|
484
488
|
}
|
|
485
489
|
|
|
486
|
-
/**
|
|
487
|
-
* Overrides the selectTextLanguage method to use the remote player's text track selection.
|
|
488
|
-
* @param {string} language - The language to select.
|
|
489
|
-
* @param {string=} role - The role of the track to select.
|
|
490
|
-
*/
|
|
491
490
|
selectTextLanguage(language, role) {
|
|
492
491
|
sdkLogger.log("Selecting text language:", language, "with role:", role);
|
|
493
492
|
if (this._textTracksMap[language]) {
|
|
@@ -498,20 +497,12 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
498
497
|
super.selectTextLanguage(language, role);
|
|
499
498
|
}
|
|
500
499
|
|
|
501
|
-
/**
|
|
502
|
-
* Overrides the setTextTrackVisibility method to use the remote player's text track visibility settings.
|
|
503
|
-
* @param {boolean} visible - Whether the text tracks should be visible.
|
|
504
|
-
*/
|
|
505
500
|
setTextTrackVisibility(visible) {
|
|
506
501
|
sdkLogger.log("Setting text track visibility to:", visible);
|
|
507
502
|
remotePlayer.setTextTrackVisibility(visible);
|
|
508
503
|
super.setTextTrackVisibility(visible);
|
|
509
504
|
}
|
|
510
505
|
|
|
511
|
-
/**
|
|
512
|
-
* Helper function that makes it easier to check if lifecycle.state is
|
|
513
|
-
* either background or inTransitionToBackground.
|
|
514
|
-
*/
|
|
515
506
|
get isInRemotePlayback() {
|
|
516
507
|
return lifecycle.state === lifecycle.UiState.BACKGROUND || lifecycle.state === lifecycle.UiState.IN_TRANSITION_TO_BACKGROUND;
|
|
517
508
|
}
|
|
@@ -556,11 +547,12 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
556
547
|
const isCritical = this._isErrorCritical(remotePlayerErrorCode);
|
|
557
548
|
const error = this._createSenzaError(remotePlayerErrorCode, message, isCritical);
|
|
558
549
|
const errorMap = new Map();
|
|
550
|
+
const shouldStopPlayback = this._shouldStopOnRemotePlayerError && this.videoElement && isCritical;
|
|
559
551
|
errorMap.set("detail", error);
|
|
560
552
|
|
|
561
553
|
// Check if we should stop playback - only for critical errors when configured
|
|
562
|
-
|
|
563
|
-
|
|
554
|
+
|
|
555
|
+
if (shouldStopPlayback) {
|
|
564
556
|
try {
|
|
565
557
|
sdkLogger.warn("Stopping local player playback due to critical error");
|
|
566
558
|
// Stop only local playback
|
|
@@ -568,18 +560,14 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
568
560
|
} catch (stopError) {
|
|
569
561
|
sdkLogger.error("Error while trying to stop video element playback:", stopError);
|
|
570
562
|
}
|
|
563
|
+
// Handle error while waiting for play event. If the error is not critical or the system is configured not to stop remote player on error,
|
|
564
|
+
// the playback timeout will start the local playback
|
|
565
|
+
this._handlePlayPromiseError(error);
|
|
571
566
|
}
|
|
572
|
-
|
|
573
|
-
this._handlePlayPromiseError(error);
|
|
567
|
+
|
|
574
568
|
this.dispatchEvent(new shaka.util.FakeEvent("error", errorMap));
|
|
575
569
|
}
|
|
576
570
|
|
|
577
|
-
/**
|
|
578
|
-
* Loads a media URL into both local and remote players.
|
|
579
|
-
*
|
|
580
|
-
* @param {string} url - The URL of the media to load.
|
|
581
|
-
* @returns {Promise<void>}
|
|
582
|
-
*/
|
|
583
571
|
async load(url, startTime, mimeType) {
|
|
584
572
|
|
|
585
573
|
// Create a promise that will resolve when _remotePlayerLoad is called
|
|
@@ -608,16 +596,30 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
608
596
|
|
|
609
597
|
// This callbakc will be activated when the manifest is loaded. It will trigger load of the remote player.
|
|
610
598
|
// This will ensure that the remote player is loaded only after the manifest is loaded by local player.
|
|
611
|
-
const responseFilterCallback = async (type) => {
|
|
612
|
-
if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST
|
|
613
|
-
manifestLoadHandled = true;
|
|
599
|
+
const responseFilterCallback = async (type, response) => {
|
|
600
|
+
if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
614
601
|
try {
|
|
615
|
-
|
|
616
|
-
|
|
602
|
+
if (response.data && this._minSuggestedPresentationDelay > 0) {
|
|
603
|
+
const manifestText = new TextDecoder().decode(response.data);
|
|
604
|
+
const modifiedText = this._updateManifestDelayIfBelowMinimum(manifestText);
|
|
605
|
+
if (modifiedText) {
|
|
606
|
+
const responseData = new TextEncoder().encode(modifiedText).buffer;
|
|
607
|
+
response.data = responseData;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
617
610
|
} catch (error) {
|
|
618
|
-
|
|
611
|
+
sdkLogger.error("Error processing manifest:", error);
|
|
619
612
|
}
|
|
620
613
|
|
|
614
|
+
if (!manifestLoadHandled) {
|
|
615
|
+
manifestLoadHandled = true;
|
|
616
|
+
try {
|
|
617
|
+
await this._remotePlayerLoad(url, startTime);
|
|
618
|
+
remoteLoadResolver();
|
|
619
|
+
} catch (error) {
|
|
620
|
+
remoteLoadRejecter(error);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
621
623
|
}
|
|
622
624
|
};
|
|
623
625
|
|
|
@@ -652,13 +654,6 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
652
654
|
|
|
653
655
|
}
|
|
654
656
|
|
|
655
|
-
/***
|
|
656
|
-
*
|
|
657
|
-
* Configure the Player instance.
|
|
658
|
-
* @param {Object} config the configuration object
|
|
659
|
-
* @returns {Boolean}
|
|
660
|
-
*/
|
|
661
|
-
|
|
662
657
|
async destroy() {
|
|
663
658
|
await lifecycle.moveToForeground();
|
|
664
659
|
SenzaShakaPlayer._prevInstance = null;
|
|
@@ -666,10 +661,6 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
666
661
|
return super.destroy();
|
|
667
662
|
}
|
|
668
663
|
|
|
669
|
-
/**
|
|
670
|
-
* A temporary override for older versions of Shaka.
|
|
671
|
-
* Senza doesn't support out-of-band subtitles
|
|
672
|
-
*/
|
|
673
664
|
addTextTrack(uri, language, kind, mimeType, codec, label, forced = false) {
|
|
674
665
|
sdkLogger.warn("addTextTrack is deprecated, please use addTextTrackAsync");
|
|
675
666
|
super.addTextTrackAsync(uri, language, kind, mimeType, codec, label, forced).then(subs => {
|
|
@@ -677,30 +668,16 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
677
668
|
});
|
|
678
669
|
}
|
|
679
670
|
|
|
680
|
-
/**
|
|
681
|
-
* Override the configure method to add custom configuration handling
|
|
682
|
-
* Supports the following additional configuration options:
|
|
683
|
-
* - shouldStopRemotePlayerOnError: boolean - If true, remote player will be stopped on error
|
|
684
|
-
*
|
|
685
|
-
* @override
|
|
686
|
-
* @param {Object} config - Configuration object to be merged with existing config
|
|
687
|
-
* @param {boolean} [config.shouldStopRemotePlayerOnError=true] - Whether to stop remote player on error
|
|
688
|
-
* @example
|
|
689
|
-
* player.configure({
|
|
690
|
-
* shouldStopRemotePlayerOnError: false, // Don't stop remote player on error
|
|
691
|
-
* // ... other shaka configurations
|
|
692
|
-
* });
|
|
693
|
-
*/
|
|
694
671
|
configure(config) {
|
|
695
672
|
sdkLogger.log("configure player with: ", JSON.stringify(config));
|
|
696
673
|
|
|
697
674
|
// Handle custom configuration
|
|
698
|
-
if (config.
|
|
699
|
-
this.
|
|
675
|
+
if (config.shouldStopOnRemotePlayerError !== undefined) {
|
|
676
|
+
this._shouldStopOnRemotePlayerError = !!config.shouldStopOnRemotePlayerError;
|
|
700
677
|
// Remove our custom config so it doesn't get passed to parent
|
|
701
678
|
// Use rest operator without creating a named variable for the removed property
|
|
702
679
|
// eslint-disable-next-line no-unused-vars
|
|
703
|
-
const {
|
|
680
|
+
const { shouldStopOnRemotePlayerError, ...shakaConfig } = config;
|
|
704
681
|
config = shakaConfig;
|
|
705
682
|
}
|
|
706
683
|
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import { noop } from "./utils";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* alarm event
|
|
5
|
+
*
|
|
6
|
+
* @event AlarmManager#MyAlarm
|
|
7
|
+
* @description Fired when time of 'MyAlarm' arrives. If this alarm triggers the application load and the application doesn't call
|
|
8
|
+
* lifecycle.moveToForeground() in the alarm callback (i.e. the application remains in the background after the callback is completed),
|
|
9
|
+
* the application will be unloaded.
|
|
10
|
+
* NOTE: If you perform async operations in the callback (without moving to foreground), you must wait for the async
|
|
11
|
+
* operation to finish before returning from the callback, otherwise the application will be unloaded before the async operation is finished.<br>
|
|
12
|
+
* @example
|
|
13
|
+
* alarmManager.addEventListener("MyAlarm", async (e) => {
|
|
14
|
+
* console.log("alarm MyAlarm arrived with data", e.detail);
|
|
15
|
+
* await fetch("http://www.example.com");
|
|
16
|
+
* });
|
|
17
|
+
* alarmManager.addAlarm("MyAlarm", Date.now() + 60*60*1000, "MyData");
|
|
18
|
+
*/
|
|
19
|
+
|
|
2
20
|
/**
|
|
3
|
-
* @class AlarmManager
|
|
4
21
|
* AlarmManager is a singleton class that manages the alarms in the application. It fires events whose types are the names of the alarms.
|
|
5
22
|
* @fires MyAlarm
|
|
6
23
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* alarm event
|
|
11
|
-
*
|
|
12
|
-
* @event AlarmManager#MyAlarm
|
|
13
|
-
* @description Fired when time of 'MyAlarm' arrives. If this alarm triggers the application load and the application doesn't call
|
|
14
|
-
* lifecycle.moveToForeground() in the alarm callback (i.e. the application remains in the background after the callback is completed),
|
|
15
|
-
* the application will be unloaded.
|
|
16
|
-
* NOTE: If you perform async operations in the callback (without moving to foreground), you must wait for the async
|
|
17
|
-
* operation to finish before returning from the callback, otherwise the application will be unloaded before the async operation is finished.<br>
|
|
18
|
-
* @example
|
|
19
|
-
* alarmManager.addEventListener("MyAlarm", async (e) => {
|
|
20
|
-
* console.log("alarm MyAlarm arrived with data", e.detail);
|
|
21
|
-
* await fetch("http://www.example.com");
|
|
22
|
-
* });
|
|
23
|
-
* alarmManager.addAlarm("MyAlarm", Date.now() + 60*60*1000, "MyData");
|
|
24
|
-
*/
|
|
25
|
-
constructor() {
|
|
26
|
-
super();
|
|
27
|
-
}
|
|
24
|
+
class AlarmManager extends EventTarget {
|
|
28
25
|
|
|
29
26
|
addEventListener(type, callback) {
|
|
30
27
|
noop("AlarmManager.addEventListener", type, callback);
|
|
@@ -67,3 +64,13 @@ export class AlarmManager extends EventTarget {
|
|
|
67
64
|
return noop("AlarmManager.getActiveAlarms");
|
|
68
65
|
}
|
|
69
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @module
|
|
70
|
+
* @type {AlarmManager}
|
|
71
|
+
* @example
|
|
72
|
+
* import { alarmManager } from "senza-sdk";
|
|
73
|
+
*
|
|
74
|
+
* @return {AlarmManager} pointer to the AlarmManager singleton
|
|
75
|
+
*/
|
|
76
|
+
export { AlarmManager };
|
|
@@ -204,6 +204,7 @@ const setupSequence = (components, items) => {
|
|
|
204
204
|
};
|
|
205
205
|
methodInject(components, inject, (name) => name.startsWith("_") || name.startsWith("get"));
|
|
206
206
|
handleKeys(items);
|
|
207
|
+
playersEvents(components, items);
|
|
207
208
|
sdkLogger.log("Sequence initialized.");
|
|
208
209
|
};
|
|
209
210
|
|
|
@@ -257,3 +258,37 @@ export const showSequence = (visible = true) => {
|
|
|
257
258
|
}
|
|
258
259
|
container.style.visibility = visible ? "visible" : "hidden";
|
|
259
260
|
};
|
|
261
|
+
function playersEvents(components, items) {
|
|
262
|
+
components.remotePlayer.addEventListener("videoelementattached", () => {
|
|
263
|
+
const video = components.remotePlayer._videoElement;
|
|
264
|
+
if (video && !video._devSequenceRateChangeHandler) {
|
|
265
|
+
video._devSequenceRateChangeHandler = () => {
|
|
266
|
+
items.push({
|
|
267
|
+
component: "localPlayer",
|
|
268
|
+
id: "ratechange=" + video.playbackRate,
|
|
269
|
+
time: performance.now() - currentTime
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
video.addEventListener("ratechange", video._devSequenceRateChangeHandler);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (video && !video._devSequencePlayingHandler) {
|
|
276
|
+
video._devSequencePlayingHandler = () => {
|
|
277
|
+
items.push({
|
|
278
|
+
component: "localPlayer",
|
|
279
|
+
id: "playing event",
|
|
280
|
+
time: performance.now() - currentTime
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
video.addEventListener("playing", video._devSequencePlayingHandler);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
components.remotePlayer.addEventListener("playing", () => {
|
|
287
|
+
items.push({
|
|
288
|
+
component: "remotePlayer",
|
|
289
|
+
id: "playing event",
|
|
290
|
+
time: performance.now() - currentTime
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
import { sdkLogger, noop } from "./utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* @event DeviceManager#wifiInfoUpdated
|
|
4
|
+
* @deprecated Instead, call deviceManager.getWifiInfo() periodically
|
|
5
|
+
* @example
|
|
6
|
+
* deviceManager.addEventListener("wifiInfoUpdated", () => {
|
|
7
|
+
* console.info("Wifi info has been updated to", deviceManager.wifiInfo);
|
|
8
|
+
* });
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
2
11
|
|
|
3
|
-
const wifiInfo = {
|
|
12
|
+
const wifiInfo = {
|
|
13
|
+
level: 0,
|
|
14
|
+
quality: 0,
|
|
15
|
+
ssid: "unknown",
|
|
16
|
+
bssid: "unknown"
|
|
17
|
+
};
|
|
4
18
|
|
|
5
19
|
/**
|
|
6
|
-
* @class DeviceManager
|
|
7
20
|
* DeviceManager is a singleton class that manages the device
|
|
8
21
|
*/
|
|
9
22
|
export class DeviceManager extends EventTarget {
|
|
10
|
-
|
|
11
|
-
constructor() {
|
|
12
|
-
super();
|
|
13
|
-
wifiInfo.level = 0;
|
|
14
|
-
wifiInfo.quality = 0;
|
|
15
|
-
wifiInfo.ssid = "unknown";
|
|
16
|
-
wifiInfo.bssid = "unknown";
|
|
17
|
-
/**
|
|
18
|
-
* @deprecated Instead, call deviceManager.getWifiInfo() periodically
|
|
19
|
-
* @event DeviceManager#wifiInfoUpdated
|
|
20
|
-
* @example
|
|
21
|
-
* deviceManager.addEventListener("wifiInfoUpdated", () => {
|
|
22
|
-
* console.info("Wifi info has been updated to", deviceManager.wifiInfo);
|
|
23
|
-
* });
|
|
24
|
-
*
|
|
25
|
-
*/
|
|
26
|
-
}
|
|
27
|
-
|
|
28
23
|
/**
|
|
29
24
|
* @property {object} DeviceInfo
|
|
30
25
|
* @property {string} DeviceInfo.deviceId
|
|
@@ -131,3 +126,18 @@ export class DeviceManager extends EventTarget {
|
|
|
131
126
|
return Promise.resolve({});
|
|
132
127
|
}
|
|
133
128
|
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @module
|
|
133
|
+
* @type {DeviceManager}
|
|
134
|
+
* @example
|
|
135
|
+
* import { deviceManager } from "senza-sdk";
|
|
136
|
+
* const wifiInfo = await deviceManager.getWifiInfo();
|
|
137
|
+
* console.info(wifiInfo.ssid);
|
|
138
|
+
* await deviceManager.clearWifi();
|
|
139
|
+
* deviceManager.reboot();
|
|
140
|
+
*
|
|
141
|
+
* @return {DeviceManager} pointer to the DeviceManager singleton
|
|
142
|
+
*/
|
|
143
|
+
"needed for the module doc comment to be recognized";
|