@gcorevideo/player 2.22.27 → 2.22.29
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/assets/media-control/media-control.scss +2 -6
- package/assets/seek-time/seek-time.html +2 -2
- package/assets/seek-time/seek-time.scss +4 -4
- package/dist/core.js +1 -1
- package/dist/index.css +1408 -1411
- package/dist/index.js +100 -135
- package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/NerdStats.js +3 -7
- package/lib/plugins/clappr-nerd-stats/speedtest/Speedtest.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/speedtest/Speedtest.js +2 -3
- package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/speedtest/index.js +1 -8
- package/lib/plugins/clappr-stats/ClapprStats.d.ts.map +1 -1
- package/lib/plugins/clappr-stats/ClapprStats.js +8 -2
- package/lib/plugins/media-control/MediaControl.d.ts +0 -1
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +9 -23
- package/lib/plugins/seek-time/SeekTime.d.ts +15 -6
- package/lib/plugins/seek-time/SeekTime.d.ts.map +1 -1
- package/lib/plugins/seek-time/SeekTime.js +17 -32
- package/lib/testUtils.d.ts +1 -0
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +1 -0
- package/package.json +1 -1
- package/src/plugins/clappr-nerd-stats/NerdStats.ts +3 -7
- package/src/plugins/clappr-nerd-stats/speedtest/Speedtest.ts +2 -3
- package/src/plugins/clappr-nerd-stats/speedtest/index.ts +1 -9
- package/src/plugins/clappr-stats/ClapprStats.ts +10 -4
- package/src/plugins/media-control/MediaControl.ts +14 -25
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +16 -0
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +70 -0
- package/src/plugins/seek-time/SeekTime.ts +37 -50
- package/src/testUtils.ts +1 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/index.js
CHANGED
|
@@ -12680,7 +12680,7 @@ var PlaybackEvents;
|
|
|
12680
12680
|
// https://github.com/clappr/clappr/blob/8752995ea439321ac7ca3cd35e8c64de7a3c3d17/LICENSE
|
|
12681
12681
|
const AUTO$1 = -1;
|
|
12682
12682
|
const { now: now$2 } = Utils;
|
|
12683
|
-
const T$
|
|
12683
|
+
const T$m = 'playback.dash';
|
|
12684
12684
|
class DashPlayback extends BasePlayback {
|
|
12685
12685
|
_levels = null;
|
|
12686
12686
|
_currentLevel = null;
|
|
@@ -12955,10 +12955,10 @@ class DashPlayback extends BasePlayback {
|
|
|
12955
12955
|
}
|
|
12956
12956
|
_onPlaybackError = (event) => {
|
|
12957
12957
|
// TODO
|
|
12958
|
-
trace(`${T$
|
|
12958
|
+
trace(`${T$m} _onPlaybackError`, { event });
|
|
12959
12959
|
};
|
|
12960
12960
|
_onDASHJSSError = (event) => {
|
|
12961
|
-
trace(`${T$
|
|
12961
|
+
trace(`${T$m} _onDASHJSSError`, { event });
|
|
12962
12962
|
this._stopTimeUpdateTimer();
|
|
12963
12963
|
// Note that the other error types are deprecated
|
|
12964
12964
|
const e = event.error;
|
|
@@ -12993,7 +12993,7 @@ class DashPlayback extends BasePlayback {
|
|
|
12993
12993
|
}
|
|
12994
12994
|
};
|
|
12995
12995
|
triggerError(error) {
|
|
12996
|
-
trace(`${T$
|
|
12996
|
+
trace(`${T$m} triggerError`, { error });
|
|
12997
12997
|
// this triggers Events.ERROR to be handled by the UI
|
|
12998
12998
|
this.trigger(Events$1.PLAYBACK_ERROR, this.createError(error, {
|
|
12999
12999
|
useCodePrefix: false,
|
|
@@ -13032,10 +13032,10 @@ class DashPlayback extends BasePlayback {
|
|
|
13032
13032
|
}
|
|
13033
13033
|
get dvrEnabled() {
|
|
13034
13034
|
if (!this._dash) {
|
|
13035
|
-
trace(`${T$
|
|
13035
|
+
trace(`${T$m} dvrEnable no dash player instance`);
|
|
13036
13036
|
return false;
|
|
13037
13037
|
}
|
|
13038
|
-
trace(`${T$
|
|
13038
|
+
trace(`${T$m} get.dvrEnabled`, {
|
|
13039
13039
|
dvrWindowSize: this._dash?.getDVRWindowSize(),
|
|
13040
13040
|
minDvrSize: this._minDvrSize,
|
|
13041
13041
|
playbackType: this.getPlaybackType(),
|
|
@@ -13057,7 +13057,7 @@ class DashPlayback extends BasePlayback {
|
|
|
13057
13057
|
this.trigger(Events$1.PLAYBACK_PROGRESS, progress, {});
|
|
13058
13058
|
}
|
|
13059
13059
|
play() {
|
|
13060
|
-
trace(`${T$
|
|
13060
|
+
trace(`${T$m} play`, { dash: !!this._dash });
|
|
13061
13061
|
if (!this._dash) {
|
|
13062
13062
|
this._setup();
|
|
13063
13063
|
}
|
|
@@ -13143,7 +13143,7 @@ class DashPlayback extends BasePlayback {
|
|
|
13143
13143
|
}
|
|
13144
13144
|
// @ts-expect-error
|
|
13145
13145
|
get currentAudioTrack() {
|
|
13146
|
-
trace(`${T$
|
|
13146
|
+
trace(`${T$m} get currentAudioTrack`);
|
|
13147
13147
|
assert.ok(this._dash, 'DASH.js MediaPlayer is not initialized');
|
|
13148
13148
|
const t = this._dash.getCurrentTrackFor('audio');
|
|
13149
13149
|
if (!t) {
|
|
@@ -41844,7 +41844,7 @@ const AUTO = -1;
|
|
|
41844
41844
|
const DEFAULT_RECOVER_ATTEMPTS = 16;
|
|
41845
41845
|
Events$1.register('PLAYBACK_FRAGMENT_CHANGED');
|
|
41846
41846
|
Events$1.register('PLAYBACK_FRAGMENT_PARSING_METADATA');
|
|
41847
|
-
const T$
|
|
41847
|
+
const T$l = 'playback.hls';
|
|
41848
41848
|
class HlsPlayback extends BasePlayback {
|
|
41849
41849
|
_ccIsSetup = false;
|
|
41850
41850
|
_ccTracksUpdated = false;
|
|
@@ -42073,7 +42073,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42073
42073
|
maxBufferLength: 2,
|
|
42074
42074
|
maxMaxBufferLength: 4,
|
|
42075
42075
|
}, this.options.playback.hlsjsConfig);
|
|
42076
|
-
trace(`${T$
|
|
42076
|
+
trace(`${T$l} _createHLSInstance`, { config });
|
|
42077
42077
|
this._hls = new Hls(config);
|
|
42078
42078
|
}
|
|
42079
42079
|
_attachHLSMedia() {
|
|
@@ -42164,7 +42164,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42164
42164
|
}
|
|
42165
42165
|
else {
|
|
42166
42166
|
Log.error('hlsjs: failed to recover', { evt, data });
|
|
42167
|
-
trace(`${T$
|
|
42167
|
+
trace(`${T$l} _recover failed to recover`, {
|
|
42168
42168
|
type: data.type,
|
|
42169
42169
|
details: data.details,
|
|
42170
42170
|
});
|
|
@@ -42250,7 +42250,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42250
42250
|
this.trigger(Events$1.PLAYBACK_SETTINGSUPDATE);
|
|
42251
42251
|
}
|
|
42252
42252
|
_onHLSJSError(evt, data) {
|
|
42253
|
-
trace(`${T$
|
|
42253
|
+
trace(`${T$l} _onHLSJSError`, {
|
|
42254
42254
|
fatal: data.fatal,
|
|
42255
42255
|
type: data.type,
|
|
42256
42256
|
details: data.details,
|
|
@@ -42298,7 +42298,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42298
42298
|
evt,
|
|
42299
42299
|
data,
|
|
42300
42300
|
});
|
|
42301
|
-
trace(`${T$
|
|
42301
|
+
trace(`${T$l} _onHLSJSError trying to recover from network error`, {
|
|
42302
42302
|
details: data.details,
|
|
42303
42303
|
});
|
|
42304
42304
|
error.level = PlayerError.Levels.WARN;
|
|
@@ -42311,7 +42311,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42311
42311
|
evt,
|
|
42312
42312
|
data,
|
|
42313
42313
|
});
|
|
42314
|
-
trace(`${T$
|
|
42314
|
+
trace(`${T$l} _onHLSJSError trying to recover from media error`, {
|
|
42315
42315
|
details: data.details,
|
|
42316
42316
|
});
|
|
42317
42317
|
error.level = PlayerError.Levels.WARN;
|
|
@@ -42341,7 +42341,7 @@ class HlsPlayback extends BasePlayback {
|
|
|
42341
42341
|
return;
|
|
42342
42342
|
}
|
|
42343
42343
|
Log.warn('hlsjs: non-fatal error occurred', { evt, data });
|
|
42344
|
-
trace(`${T$
|
|
42344
|
+
trace(`${T$l} _onHLSJSError non-fatal error occurred`, {
|
|
42345
42345
|
type: data.type,
|
|
42346
42346
|
details: data.details,
|
|
42347
42347
|
});
|
|
@@ -42675,11 +42675,11 @@ class HlsPlayback extends BasePlayback {
|
|
|
42675
42675
|
this._hls.audioTrack = Number(id); // TODO or find index by .id == id?
|
|
42676
42676
|
}
|
|
42677
42677
|
_onAudioTracksUpdated(_, data) {
|
|
42678
|
-
trace(`${T$
|
|
42678
|
+
trace(`${T$l} onAudioTracksUpdated`);
|
|
42679
42679
|
this.trigger(Events$1.PLAYBACK_AUDIO_AVAILABLE, data.audioTracks.map(toClapprTrack));
|
|
42680
42680
|
}
|
|
42681
42681
|
_onAudioTrackSwitched(_, data) {
|
|
42682
|
-
trace(`${T$
|
|
42682
|
+
trace(`${T$l} onAudioTrackSwitched`);
|
|
42683
42683
|
// @ts-ignore
|
|
42684
42684
|
const track = this._hls.audioTracks[data.id];
|
|
42685
42685
|
this.trigger(Events$1.PLAYBACK_AUDIO_CHANGED, toClapprTrack(track));
|
|
@@ -42700,7 +42700,7 @@ function toClapprTrack(t) {
|
|
|
42700
42700
|
};
|
|
42701
42701
|
}
|
|
42702
42702
|
|
|
42703
|
-
const T$
|
|
42703
|
+
const T$k = 'playback.html5_video';
|
|
42704
42704
|
const STALL_TIMEOUT = 15000;
|
|
42705
42705
|
class HTML5Video extends BasePlayback {
|
|
42706
42706
|
stallTimerId = null;
|
|
@@ -42708,7 +42708,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42708
42708
|
* @internal
|
|
42709
42709
|
*/
|
|
42710
42710
|
createError(errorData, options) {
|
|
42711
|
-
trace(`${T$
|
|
42711
|
+
trace(`${T$k} createError`, {
|
|
42712
42712
|
errorData: { ...errorData },
|
|
42713
42713
|
});
|
|
42714
42714
|
const i18n = this.i18n ||
|
|
@@ -42724,11 +42724,11 @@ class HTML5Video extends BasePlayback {
|
|
|
42724
42724
|
return super.createError(errorData, { ...options, useCodePrefix: false });
|
|
42725
42725
|
}
|
|
42726
42726
|
_onWaiting() {
|
|
42727
|
-
trace(`${T$
|
|
42727
|
+
trace(`${T$k} _onWaiting`);
|
|
42728
42728
|
super._onWaiting();
|
|
42729
42729
|
}
|
|
42730
42730
|
_onEnded() {
|
|
42731
|
-
trace(`${T$
|
|
42731
|
+
trace(`${T$k} _onEnded`);
|
|
42732
42732
|
if (this.stallTimerId) {
|
|
42733
42733
|
clearTimeout(this.stallTimerId);
|
|
42734
42734
|
this.stallTimerId = null;
|
|
@@ -42736,12 +42736,12 @@ class HTML5Video extends BasePlayback {
|
|
|
42736
42736
|
super._onEnded();
|
|
42737
42737
|
}
|
|
42738
42738
|
_handleBufferingEvents() {
|
|
42739
|
-
trace(`${T$
|
|
42739
|
+
trace(`${T$k} _handleBufferingEvents`, {
|
|
42740
42740
|
networkState: this.el.networkState,
|
|
42741
42741
|
});
|
|
42742
42742
|
if (!this.stallTimerId) {
|
|
42743
42743
|
this.stallTimerId = setTimeout(() => {
|
|
42744
|
-
trace(`${T$
|
|
42744
|
+
trace(`${T$k} _handleBufferingEvents stall timeout`, {
|
|
42745
42745
|
buffering: this.buffering,
|
|
42746
42746
|
ended: this.ended,
|
|
42747
42747
|
});
|
|
@@ -42759,7 +42759,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42759
42759
|
super._handleBufferingEvents();
|
|
42760
42760
|
}
|
|
42761
42761
|
_onPlaying() {
|
|
42762
|
-
trace(`${T$
|
|
42762
|
+
trace(`${T$k} _onPlaying`);
|
|
42763
42763
|
if (this.stallTimerId) {
|
|
42764
42764
|
clearTimeout(this.stallTimerId);
|
|
42765
42765
|
this.stallTimerId = null;
|
|
@@ -42767,7 +42767,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42767
42767
|
super._onPlaying();
|
|
42768
42768
|
}
|
|
42769
42769
|
_onPause() {
|
|
42770
|
-
trace(`${T$
|
|
42770
|
+
trace(`${T$k} _onPause`);
|
|
42771
42771
|
super._onPause();
|
|
42772
42772
|
if (this.stallTimerId) {
|
|
42773
42773
|
clearTimeout(this.stallTimerId);
|
|
@@ -42777,7 +42777,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42777
42777
|
get audioTracks() {
|
|
42778
42778
|
const tracks = this.el.audioTracks;
|
|
42779
42779
|
const supported = !!tracks;
|
|
42780
|
-
trace(`${T$
|
|
42780
|
+
trace(`${T$k} get audioTracks`, { supported });
|
|
42781
42781
|
const retval = [];
|
|
42782
42782
|
if (supported) {
|
|
42783
42783
|
for (let i = 0; i < tracks.length; i++) {
|
|
@@ -42796,7 +42796,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42796
42796
|
get currentAudioTrack() {
|
|
42797
42797
|
const tracks = this.el.audioTracks;
|
|
42798
42798
|
const supported = !!tracks;
|
|
42799
|
-
trace(`${T$
|
|
42799
|
+
trace(`${T$k} get currentAudioTrack`, {
|
|
42800
42800
|
supported,
|
|
42801
42801
|
});
|
|
42802
42802
|
if (supported) {
|
|
@@ -42817,7 +42817,7 @@ class HTML5Video extends BasePlayback {
|
|
|
42817
42817
|
switchAudioTrack(id) {
|
|
42818
42818
|
const tracks = this.el.audioTracks;
|
|
42819
42819
|
const supported = !!tracks;
|
|
42820
|
-
trace(`${T$
|
|
42820
|
+
trace(`${T$k} switchAudioTrack`, {
|
|
42821
42821
|
supported,
|
|
42822
42822
|
});
|
|
42823
42823
|
if (supported) {
|
|
@@ -42836,7 +42836,7 @@ function registerPlaybacks() {
|
|
|
42836
42836
|
Loader.registerPlayback(DashPlayback);
|
|
42837
42837
|
}
|
|
42838
42838
|
|
|
42839
|
-
const T$
|
|
42839
|
+
const T$j = 'GPlayer';
|
|
42840
42840
|
const DEFAULT_OPTIONS = {
|
|
42841
42841
|
autoPlay: false,
|
|
42842
42842
|
debug: 'none',
|
|
@@ -42924,7 +42924,7 @@ class Player {
|
|
|
42924
42924
|
* ```
|
|
42925
42925
|
*/
|
|
42926
42926
|
attachTo(playerElement) {
|
|
42927
|
-
trace(`${T$
|
|
42927
|
+
trace(`${T$j} attachTo`, {
|
|
42928
42928
|
player: !!this.player,
|
|
42929
42929
|
});
|
|
42930
42930
|
assert.ok(!this.player, 'Player already initialized');
|
|
@@ -42934,7 +42934,7 @@ class Player {
|
|
|
42934
42934
|
}
|
|
42935
42935
|
const coreOpts = this.buildCoreOptions(playerElement);
|
|
42936
42936
|
const { core, container } = Player.getRegisteredPlugins();
|
|
42937
|
-
trace(`${T$
|
|
42937
|
+
trace(`${T$j} init`, {
|
|
42938
42938
|
registeredPlaybacks: Loader.registeredPlaybacks.map((p) => p.prototype.name),
|
|
42939
42939
|
});
|
|
42940
42940
|
coreOpts.plugins = {
|
|
@@ -42948,7 +42948,7 @@ class Player {
|
|
|
42948
42948
|
* Destroys the player, releasing all resources and unmounting its UI from the DOM.
|
|
42949
42949
|
*/
|
|
42950
42950
|
destroy() {
|
|
42951
|
-
trace(`${T$
|
|
42951
|
+
trace(`${T$j} destroy`, {
|
|
42952
42952
|
player: !!this.player,
|
|
42953
42953
|
});
|
|
42954
42954
|
if (this.player) {
|
|
@@ -43135,7 +43135,7 @@ class Player {
|
|
|
43135
43135
|
this.config = $.extend(true, this.config, config);
|
|
43136
43136
|
}
|
|
43137
43137
|
initPlayer(coreOptions) {
|
|
43138
|
-
trace(`${T$
|
|
43138
|
+
trace(`${T$j} initPlayer`, {
|
|
43139
43139
|
autoPlay: coreOptions.autoPlay,
|
|
43140
43140
|
sources: coreOptions.sources,
|
|
43141
43141
|
player: !!this.player,
|
|
@@ -43160,7 +43160,7 @@ class Player {
|
|
|
43160
43160
|
}
|
|
43161
43161
|
}
|
|
43162
43162
|
triggerAutoPlay() {
|
|
43163
|
-
trace(`${T$
|
|
43163
|
+
trace(`${T$j} triggerAutoPlay`);
|
|
43164
43164
|
setTimeout(() => {
|
|
43165
43165
|
this.player?.play({
|
|
43166
43166
|
autoPlay: true,
|
|
@@ -43178,7 +43178,7 @@ class Player {
|
|
|
43178
43178
|
// TODO test
|
|
43179
43179
|
events = {
|
|
43180
43180
|
onReady: () => {
|
|
43181
|
-
trace(`${T$
|
|
43181
|
+
trace(`${T$j} onReady`, {
|
|
43182
43182
|
ready: this.ready,
|
|
43183
43183
|
});
|
|
43184
43184
|
if (this.ready) {
|
|
@@ -43212,7 +43212,7 @@ class Player {
|
|
|
43212
43212
|
buildCoreOptions(rootNode) {
|
|
43213
43213
|
const sources = this.buildMediaSourcesList();
|
|
43214
43214
|
const source = sources[0];
|
|
43215
|
-
trace(`${T$
|
|
43215
|
+
trace(`${T$j} buildCoreOptions`, {
|
|
43216
43216
|
source,
|
|
43217
43217
|
sources,
|
|
43218
43218
|
});
|
|
@@ -43273,7 +43273,7 @@ class Player {
|
|
|
43273
43273
|
assert.ok(this.player, 'Player is not initialized');
|
|
43274
43274
|
const core = this.player.core;
|
|
43275
43275
|
core.on(Events$1.CORE_SCREEN_ORIENTATION_CHANGED, ({ orientation }) => {
|
|
43276
|
-
trace(`${T$
|
|
43276
|
+
trace(`${T$j} on CORE_SCREEN_ORIENTATION_CHANGED`, {
|
|
43277
43277
|
orientation,
|
|
43278
43278
|
rootNode: {
|
|
43279
43279
|
width: this.rootNode?.clientWidth,
|
|
@@ -43288,14 +43288,14 @@ class Player {
|
|
|
43288
43288
|
}
|
|
43289
43289
|
}, null);
|
|
43290
43290
|
core.on(Events$1.CORE_RESIZE, ({ width, height }) => {
|
|
43291
|
-
trace(`${T$
|
|
43291
|
+
trace(`${T$j} on CORE_RESIZE`, {
|
|
43292
43292
|
width,
|
|
43293
43293
|
height,
|
|
43294
43294
|
});
|
|
43295
43295
|
this.safeTriggerEvent(PlayerEvent.Resize, { width, height });
|
|
43296
43296
|
}, null);
|
|
43297
43297
|
core.on(Events$1.CORE_FULLSCREEN, (isFullscreen) => {
|
|
43298
|
-
trace(`${T$
|
|
43298
|
+
trace(`${T$j} CORE_FULLSCREEN`, {
|
|
43299
43299
|
isFullscreen,
|
|
43300
43300
|
});
|
|
43301
43301
|
this.safeTriggerEvent(PlayerEvent.Fullscreen, isFullscreen);
|
|
@@ -43303,7 +43303,7 @@ class Player {
|
|
|
43303
43303
|
}
|
|
43304
43304
|
}
|
|
43305
43305
|
|
|
43306
|
-
var version$1 = "2.22.
|
|
43306
|
+
var version$1 = "2.22.29";
|
|
43307
43307
|
|
|
43308
43308
|
var packages = {
|
|
43309
43309
|
"node_modules/@clappr/core": {
|
|
@@ -43627,7 +43627,7 @@ const INITIAL_SETTINGS = {
|
|
|
43627
43627
|
default: [],
|
|
43628
43628
|
seekEnabled: false,
|
|
43629
43629
|
};
|
|
43630
|
-
const T$
|
|
43630
|
+
const T$i = 'plugins.media_control';
|
|
43631
43631
|
const LEFT_ORDER = [
|
|
43632
43632
|
'playpause',
|
|
43633
43633
|
'playstop',
|
|
@@ -43760,7 +43760,7 @@ class MediaControl extends UICorePlugin {
|
|
|
43760
43760
|
'click [data-stop]': 'stop',
|
|
43761
43761
|
'click [data-playstop]': 'togglePlayStop',
|
|
43762
43762
|
'click [data-fullscreen]': 'handleFullScreenOnBtn',
|
|
43763
|
-
'click .bar-container[data-seekbar]': 'seek',
|
|
43763
|
+
// 'click .bar-container[data-seekbar]': 'seek', // This together with global window.bind causes duplicate seeks events
|
|
43764
43764
|
'click .bar-container[data-volume]': 'onVolumeClick',
|
|
43765
43765
|
'click .drawer-icon[data-volume]': 'toggleMute',
|
|
43766
43766
|
'mouseenter .drawer-container[data-volume]': 'showVolumeBar',
|
|
@@ -43878,7 +43878,7 @@ class MediaControl extends UICorePlugin {
|
|
|
43878
43878
|
* Hides the media control UI
|
|
43879
43879
|
*/
|
|
43880
43880
|
disable() {
|
|
43881
|
-
trace(`${T$
|
|
43881
|
+
trace(`${T$i} disable`);
|
|
43882
43882
|
this.userDisabled = true; // TODO distinguish between user and system (e.g., unplayable) disabled?
|
|
43883
43883
|
this.hide();
|
|
43884
43884
|
this.unbindKeyEvents();
|
|
@@ -43888,7 +43888,7 @@ class MediaControl extends UICorePlugin {
|
|
|
43888
43888
|
* Reenables the plugin disabled earlier with the {@link MediaControl.disable} method
|
|
43889
43889
|
*/
|
|
43890
43890
|
enable() {
|
|
43891
|
-
trace(`${T$
|
|
43891
|
+
trace(`${T$i} enable`);
|
|
43892
43892
|
if (this.options.chromeless) {
|
|
43893
43893
|
return;
|
|
43894
43894
|
}
|
|
@@ -44067,12 +44067,14 @@ class MediaControl extends UICorePlugin {
|
|
|
44067
44067
|
event && event.preventDefault();
|
|
44068
44068
|
}
|
|
44069
44069
|
stopDrag = (event) => {
|
|
44070
|
-
this.draggingSeekBar
|
|
44070
|
+
if (this.draggingSeekBar) {
|
|
44071
|
+
this.draggingSeekBar = false;
|
|
44072
|
+
this.seek(event);
|
|
44073
|
+
}
|
|
44071
44074
|
this.$el.removeClass('dragging');
|
|
44072
44075
|
this.$seekBarLoaded?.removeClass('media-control-notransition');
|
|
44073
44076
|
this.$seekBarPosition?.removeClass('media-control-notransition');
|
|
44074
44077
|
this.$seekBarScrubber?.removeClass('media-control-notransition dragging');
|
|
44075
|
-
this.draggingSeekBar = false;
|
|
44076
44078
|
this.draggingVolumeBar = false;
|
|
44077
44079
|
};
|
|
44078
44080
|
updateDrag = (event) => {
|
|
@@ -44084,8 +44086,9 @@ class MediaControl extends UICorePlugin {
|
|
|
44084
44086
|
let pos = (offsetX / this.$seekBarContainer.width()) * 100;
|
|
44085
44087
|
pos = Math.min(100, Math.max(pos, 0));
|
|
44086
44088
|
this.setSeekPercentage(pos);
|
|
44089
|
+
return;
|
|
44087
44090
|
}
|
|
44088
|
-
|
|
44091
|
+
if (this.draggingVolumeBar) {
|
|
44089
44092
|
event.preventDefault();
|
|
44090
44093
|
this.setVolume(this.getVolumeFromUIEvent(event));
|
|
44091
44094
|
}
|
|
@@ -44255,13 +44258,13 @@ class MediaControl extends UICorePlugin {
|
|
|
44255
44258
|
if (!this.settings.seekEnabled) {
|
|
44256
44259
|
return;
|
|
44257
44260
|
}
|
|
44261
|
+
// TODO prevent double seek
|
|
44258
44262
|
assert.ok(this.$seekBarContainer, 'seek bar container must be present');
|
|
44259
44263
|
const offsetX = MediaControl.getPageX(event) - this.$seekBarContainer.offset().left;
|
|
44260
44264
|
let pos = (offsetX / this.$seekBarContainer.width()) * 100;
|
|
44261
44265
|
pos = Math.min(100, Math.max(pos, 0));
|
|
44262
44266
|
this.core.activeContainer && this.core.activeContainer.seekPercentage(pos);
|
|
44263
44267
|
this.setSeekPercentage(pos);
|
|
44264
|
-
return false;
|
|
44265
44268
|
}
|
|
44266
44269
|
setUserKeepVisible() {
|
|
44267
44270
|
this.userKeepVisible = true;
|
|
@@ -44334,13 +44337,11 @@ class MediaControl extends UICorePlugin {
|
|
|
44334
44337
|
}
|
|
44335
44338
|
}
|
|
44336
44339
|
updateSettings() {
|
|
44337
|
-
trace(`${T$k} updateSettings`, { settings: this.settings });
|
|
44338
44340
|
const newSettings = $.extend(true, {
|
|
44339
44341
|
left: [],
|
|
44340
44342
|
default: [],
|
|
44341
44343
|
right: [],
|
|
44342
44344
|
}, this.core.activeContainer.settings);
|
|
44343
|
-
trace(`${T$k} updateSettings`, { newSettings });
|
|
44344
44345
|
newSettings.left.push('clips'); // TODO settings
|
|
44345
44346
|
// TODO make order controlled via CSS
|
|
44346
44347
|
newSettings.left = orderByOrderPattern([...newSettings.left, 'volume', 'clips'], LEFT_ORDER);
|
|
@@ -44352,11 +44353,6 @@ class MediaControl extends UICorePlugin {
|
|
|
44352
44353
|
newSettings.right = DEFAULT_SETTINGS.right; // TODO get from the options
|
|
44353
44354
|
if ((!this.fullScreenOnVideoTagSupported && !fullscreenEnabled()) ||
|
|
44354
44355
|
this.options.fullscreenDisable) {
|
|
44355
|
-
trace(`${T$k} updateSettings removing fullscreen`, {
|
|
44356
|
-
supported: this.fullScreenOnVideoTagSupported,
|
|
44357
|
-
enabled: Fullscreen.fullscreenEnabled(),
|
|
44358
|
-
optionsDisable: this.options.fullscreenDisable,
|
|
44359
|
-
});
|
|
44360
44356
|
// remove fullscreen from settings if it is not available
|
|
44361
44357
|
removeArrayItem(newSettings.default, 'fullscreen');
|
|
44362
44358
|
removeArrayItem(newSettings.left, 'fullscreen');
|
|
@@ -44419,7 +44415,6 @@ class MediaControl extends UICorePlugin {
|
|
|
44419
44415
|
*/
|
|
44420
44416
|
mount(name, element) {
|
|
44421
44417
|
const panel = this.getElementLocation(name);
|
|
44422
|
-
trace(`${T$k} mount`, { name, panel: !!panel });
|
|
44423
44418
|
if (panel) {
|
|
44424
44419
|
const current = panel.find(`[data-${name}]`);
|
|
44425
44420
|
element.attr(`data-${name}`, '');
|
|
@@ -44615,14 +44610,11 @@ class MediaControl extends UICorePlugin {
|
|
|
44615
44610
|
* @internal
|
|
44616
44611
|
*/
|
|
44617
44612
|
render() {
|
|
44618
|
-
trace(`${T$k} render`, {
|
|
44619
|
-
needsUpdate: this.hasUpdate,
|
|
44620
|
-
metadataLoaded: this.metadataLoaded,
|
|
44621
|
-
});
|
|
44622
44613
|
if (!this.hasUpdate || !this.metadataLoaded) {
|
|
44623
44614
|
return this;
|
|
44624
44615
|
}
|
|
44625
44616
|
const timeout = this.options.hideMediaControlDelay || 2000;
|
|
44617
|
+
trace(`${T$i} render`, { settings: this.settings });
|
|
44626
44618
|
this.$el.html(MediaControl.template({ settings: this.settings }));
|
|
44627
44619
|
// const style = Styler.getStyleFor(mediaControlStyle, { baseUrl: this.options.baseUrl });
|
|
44628
44620
|
// this.$el.append(style[0]);
|
|
@@ -44745,12 +44737,6 @@ class MediaControl extends UICorePlugin {
|
|
|
44745
44737
|
return isFinite(this.core.activePlayback.getDuration());
|
|
44746
44738
|
}
|
|
44747
44739
|
getElementLocation(name) {
|
|
44748
|
-
trace(`${T$k} getElementLocation`, {
|
|
44749
|
-
name,
|
|
44750
|
-
right: this.settings.right,
|
|
44751
|
-
left: this.settings.left,
|
|
44752
|
-
default: this.settings.default,
|
|
44753
|
-
});
|
|
44754
44740
|
if (this.settings.right?.includes(name)) {
|
|
44755
44741
|
return this.getRightPanel();
|
|
44756
44742
|
}
|
|
@@ -44784,7 +44770,7 @@ function serializeSettings(s) {
|
|
|
44784
44770
|
}
|
|
44785
44771
|
|
|
44786
44772
|
const VERSION$7 = '2.22.4';
|
|
44787
|
-
const T$
|
|
44773
|
+
const T$h = 'plugins.audiotracks';
|
|
44788
44774
|
/**
|
|
44789
44775
|
* `PLUGIN` that makes possible to switch audio tracks via the media control UI.
|
|
44790
44776
|
* @beta
|
|
@@ -44906,7 +44892,7 @@ class AudioTracks extends UICorePlugin {
|
|
|
44906
44892
|
this.updateText();
|
|
44907
44893
|
}
|
|
44908
44894
|
hideMenu() {
|
|
44909
|
-
trace(`${T$
|
|
44895
|
+
trace(`${T$h} hideMenu`);
|
|
44910
44896
|
this.$el.find('#audiotracks-select').addClass('hidden');
|
|
44911
44897
|
this.$el.find('#audiotracks-button').attr('aria-expanded', 'false');
|
|
44912
44898
|
}
|
|
@@ -44959,7 +44945,7 @@ class AudioTracks extends UICorePlugin {
|
|
|
44959
44945
|
|
|
44960
44946
|
const pluginHtml$6 = "<div class=\"big-mute-icon-wrapper\" data-big-mute>\n <div class=\"big-mute-icon gcore-skin-border-color\" data-big-mute-icon></div>\n</div>\n";
|
|
44961
44947
|
|
|
44962
|
-
const T$
|
|
44948
|
+
const T$g = 'plugins.big_mute_button';
|
|
44963
44949
|
// TODO rewrite as a container plugin
|
|
44964
44950
|
/**
|
|
44965
44951
|
* `PLUGIN` that displays a big mute button over the video when it's muted.
|
|
@@ -45000,7 +44986,7 @@ class BigMuteButton extends UICorePlugin {
|
|
|
45000
44986
|
this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
|
|
45001
44987
|
this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
|
|
45002
44988
|
this.listenTo(this.core, 'core:advertisement:finish', this.onFinishAd);
|
|
45003
|
-
trace(`${T$
|
|
44989
|
+
trace(`${T$g} bindEvents`, {
|
|
45004
44990
|
mediacontrol: !!this.core.mediaControl,
|
|
45005
44991
|
});
|
|
45006
44992
|
this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mediaControlRendered);
|
|
@@ -45025,12 +45011,12 @@ class BigMuteButton extends UICorePlugin {
|
|
|
45025
45011
|
}
|
|
45026
45012
|
mediaControlRendered() {
|
|
45027
45013
|
const container = this.core.activeContainer;
|
|
45028
|
-
trace(`${T$
|
|
45014
|
+
trace(`${T$g} mediaControlRendered`, {
|
|
45029
45015
|
container: !!container,
|
|
45030
45016
|
});
|
|
45031
45017
|
if (container) {
|
|
45032
45018
|
this.listenTo(container.playback, Events$1.PLAYBACK_PLAY, () => {
|
|
45033
|
-
trace(`${T$
|
|
45019
|
+
trace(`${T$g} PLAYBACK_PLAY`);
|
|
45034
45020
|
this.render();
|
|
45035
45021
|
});
|
|
45036
45022
|
}
|
|
@@ -45054,7 +45040,7 @@ class BigMuteButton extends UICorePlugin {
|
|
|
45054
45040
|
}
|
|
45055
45041
|
const { autoPlay, wasMuted } = this.options;
|
|
45056
45042
|
const volume = container.volume;
|
|
45057
|
-
trace(`${T$
|
|
45043
|
+
trace(`${T$g} shouldRender`, {
|
|
45058
45044
|
autoPlay,
|
|
45059
45045
|
wasMuted,
|
|
45060
45046
|
volume,
|
|
@@ -45066,7 +45052,7 @@ class BigMuteButton extends UICorePlugin {
|
|
|
45066
45052
|
*/
|
|
45067
45053
|
render() {
|
|
45068
45054
|
if (this.shouldRender()) {
|
|
45069
|
-
trace(`${T$
|
|
45055
|
+
trace(`${T$g} render`, {
|
|
45070
45056
|
el: !!this.$el,
|
|
45071
45057
|
});
|
|
45072
45058
|
this.$el.html(BigMuteButton.template());
|
|
@@ -45112,7 +45098,7 @@ const gearIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"n
|
|
|
45112
45098
|
const gearHdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_28_1567)\">\n <path\n d=\"M19.14 12.94C19.18 12.64 19.2 12.33 19.2 12C19.2 11.68 19.18 11.36 19.13 11.06L21.16 9.47999C21.34 9.33999 21.39 9.06999 21.28 8.86999L19.36 5.54999C19.24 5.32999 18.99 5.25999 18.77 5.32999L16.38 6.28999C15.88 5.90999 15.35 5.58999 14.76 5.34999L14.4 2.80999C14.36 2.56999 14.16 2.39999 13.92 2.39999H10.08C9.83999 2.39999 9.64999 2.56999 9.60999 2.80999L9.24999 5.34999C8.65999 5.58999 8.11999 5.91999 7.62999 6.28999L5.23999 5.32999C5.01999 5.24999 4.76999 5.32999 4.64999 5.54999L2.73999 8.86999C2.61999 9.07999 2.65999 9.33999 2.85999 9.47999L4.88999 11.06C4.83999 11.36 4.79999 11.69 4.79999 12C4.79999 12.31 4.81999 12.64 4.86999 12.94L2.83999 14.52C2.65999 14.66 2.60999 14.93 2.71999 15.13L4.63999 18.45C4.75999 18.67 5.00999 18.74 5.22999 18.67L7.61999 17.71C8.11999 18.09 8.64999 18.41 9.23999 18.65L9.59999 21.19C9.64999 21.43 9.83999 21.6 10.08 21.6H13.92C14.16 21.6 14.36 21.43 14.39 21.19L14.75 18.65C15.34 18.41 15.88 18.09 16.37 17.71L18.76 18.67C18.98 18.75 19.23 18.67 19.35 18.45L21.27 15.13C21.39 14.91 21.34 14.66 21.15 14.52L19.14 12.94ZM12 15.6C10.02 15.6 8.39999 13.98 8.39999 12C8.39999 10.02 10.02 8.39999 12 8.39999C13.98 8.39999 15.6 10.02 15.6 12C15.6 13.98 13.98 15.6 12 15.6Z\"\n fill=\"#C9C9C9\"/>\n <rect x=\"13\" width=\"11\" height=\"7\" rx=\"1\" fill=\"#F6413B\"/>\n <path\n d=\"M14.6962 6V1.63636H15.3546V3.53267H17.53V1.63636H18.1905V6H17.53V4.0973H15.3546V6H14.6962ZM20.562 6H19.1493V1.63636H20.6067C21.0343 1.63636 21.4015 1.72372 21.7083 1.89844C22.0151 2.07173 22.2502 2.32102 22.4135 2.64631C22.5783 2.97017 22.6607 3.35866 22.6607 3.81179C22.6607 4.26634 22.5776 4.65696 22.4114 4.98366C22.2466 5.31037 22.008 5.56179 21.6955 5.73793C21.383 5.91264 21.0051 6 20.562 6ZM19.8077 5.42472H20.5257C20.8581 5.42472 21.1344 5.36222 21.3546 5.23722C21.5748 5.1108 21.7395 4.92827 21.8489 4.68963C21.9583 4.44957 22.013 4.15696 22.013 3.81179C22.013 3.46946 21.9583 3.17898 21.8489 2.94034C21.7409 2.7017 21.5797 2.5206 21.3652 2.39702C21.1507 2.27344 20.8844 2.21165 20.5662 2.21165H19.8077V5.42472Z\"\n fill=\"#C9C9C9\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_28_1567\">\n <rect width=\"24\" height=\"24\" fill=\"white\"/>\n </clipPath>\n </defs>\n</svg>\n";
|
|
45113
45099
|
|
|
45114
45100
|
const VERSION$6 = '2.19.12';
|
|
45115
|
-
const T$
|
|
45101
|
+
const T$f = 'plugins.bottom_gear';
|
|
45116
45102
|
/**
|
|
45117
45103
|
* Events triggered by the plugin
|
|
45118
45104
|
* @beta
|
|
@@ -45262,20 +45248,20 @@ class BottomGear extends UICorePlugin {
|
|
|
45262
45248
|
addItem(name, $subMenu) {
|
|
45263
45249
|
const $existingItem = this.$el.find(`#gear-options li[data-${name}`);
|
|
45264
45250
|
if ($existingItem.length) {
|
|
45265
|
-
trace(`${T$
|
|
45251
|
+
trace(`${T$f} addItem already exists`, { name });
|
|
45266
45252
|
return $existingItem;
|
|
45267
45253
|
}
|
|
45268
45254
|
const $item = $('<li></li>')
|
|
45269
45255
|
.attr(`data-${name}`, '')
|
|
45270
45256
|
.appendTo(this.$el.find('#gear-options'));
|
|
45271
45257
|
if ($subMenu) {
|
|
45272
|
-
trace(`${T$
|
|
45258
|
+
trace(`${T$f} addItem adding submenu`, { name });
|
|
45273
45259
|
$subMenu
|
|
45274
45260
|
.addClass('gear-sub-menu-wrapper')
|
|
45275
45261
|
.hide()
|
|
45276
45262
|
.appendTo(this.$el.find('#gear-options-wrapper'));
|
|
45277
45263
|
$item.on('click', (e) => {
|
|
45278
|
-
trace(`${T$
|
|
45264
|
+
trace(`${T$f} addItem submenu clicked`, { name });
|
|
45279
45265
|
e.stopPropagation();
|
|
45280
45266
|
$subMenu.show();
|
|
45281
45267
|
this.$el.find('#gear-options').hide();
|
|
@@ -45284,15 +45270,15 @@ class BottomGear extends UICorePlugin {
|
|
|
45284
45270
|
return $item;
|
|
45285
45271
|
}
|
|
45286
45272
|
onActiveContainerChanged() {
|
|
45287
|
-
trace(`${T$
|
|
45273
|
+
trace(`${T$f} onActiveContainerChanged`);
|
|
45288
45274
|
this.bindContainerEvents();
|
|
45289
45275
|
}
|
|
45290
45276
|
bindContainerEvents() {
|
|
45291
|
-
trace(`${T$
|
|
45277
|
+
trace(`${T$f} bindContainerEvents`);
|
|
45292
45278
|
this.listenTo(this.core.activeContainer, Events$1.CONTAINER_HIGHDEFINITIONUPDATE, this.highDefinitionUpdate);
|
|
45293
45279
|
}
|
|
45294
45280
|
highDefinitionUpdate(isHd) {
|
|
45295
|
-
trace(`${T$
|
|
45281
|
+
trace(`${T$f} highDefinitionUpdate`, { isHd });
|
|
45296
45282
|
this.hd = isHd;
|
|
45297
45283
|
this.$el.find('.gear-icon').html(isHd ? gearHdIcon : gearIcon);
|
|
45298
45284
|
}
|
|
@@ -45300,7 +45286,7 @@ class BottomGear extends UICorePlugin {
|
|
|
45300
45286
|
* @internal
|
|
45301
45287
|
*/
|
|
45302
45288
|
render() {
|
|
45303
|
-
trace(`${T$
|
|
45289
|
+
trace(`${T$f} render`);
|
|
45304
45290
|
const mediaControl = this.core.getPlugin('media_control');
|
|
45305
45291
|
if (!mediaControl) {
|
|
45306
45292
|
return this; // TODO test
|
|
@@ -45332,11 +45318,11 @@ class BottomGear extends UICorePlugin {
|
|
|
45332
45318
|
this.$el.find('#gear-options-wrapper').toggle();
|
|
45333
45319
|
}
|
|
45334
45320
|
hide() {
|
|
45335
|
-
trace(`${T$
|
|
45321
|
+
trace(`${T$f} hide`);
|
|
45336
45322
|
this.$el.find('#gear-options-wrapper').hide();
|
|
45337
45323
|
}
|
|
45338
45324
|
onCoreReady() {
|
|
45339
|
-
trace(`${T$
|
|
45325
|
+
trace(`${T$f} onCoreReady`);
|
|
45340
45326
|
const mediaControl = this.core.getPlugin('media_control');
|
|
45341
45327
|
assert(mediaControl, 'media_control plugin is required');
|
|
45342
45328
|
this.listenTo(mediaControl, Events$1.MEDIACONTROL_RENDERED, this.onMediaControlRendered);
|
|
@@ -45348,7 +45334,7 @@ class BottomGear extends UICorePlugin {
|
|
|
45348
45334
|
});
|
|
45349
45335
|
}
|
|
45350
45336
|
onMediaControlRendered() {
|
|
45351
|
-
trace(`${T$
|
|
45337
|
+
trace(`${T$f} onMediaControlRendered`);
|
|
45352
45338
|
const mediaControl = this.core.getPlugin('media_control');
|
|
45353
45339
|
mediaControl.mount('gear', this.$el);
|
|
45354
45340
|
}
|
|
@@ -45512,7 +45498,11 @@ class ClapprStats extends ContainerPlugin {
|
|
|
45512
45498
|
this.listenToOnce(this.container, Events$1.CONTAINER_STATE_BUFFERING, this.onBuffering);
|
|
45513
45499
|
this.listenTo(this.container, Events$1.CONTAINER_SEEK, this.onSeek);
|
|
45514
45500
|
this.listenTo(this.container, Events$1.CONTAINER_ERROR, () => this.inc(ClapprStatsCounter.Error));
|
|
45515
|
-
this.listenTo(this.container, Events$1.CONTAINER_FULLSCREEN, () =>
|
|
45501
|
+
this.listenTo(this.container, Events$1.CONTAINER_FULLSCREEN, () => {
|
|
45502
|
+
if (isFullscreen(this.container.el)) {
|
|
45503
|
+
this.inc(ClapprStatsCounter.Fullscreen);
|
|
45504
|
+
}
|
|
45505
|
+
});
|
|
45516
45506
|
this.listenTo(this.container, Events$1.CONTAINER_PLAYBACKDVRSTATECHANGED, (dvrInUse) => {
|
|
45517
45507
|
dvrInUse && this.inc(ClapprStatsCounter.DvrUsage);
|
|
45518
45508
|
});
|
|
@@ -45580,8 +45570,9 @@ class ClapprStats extends ContainerPlugin {
|
|
|
45580
45570
|
this.stopListening(this.container, Events$1.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
45581
45571
|
}
|
|
45582
45572
|
onSeek(e) {
|
|
45573
|
+
const ms = e * 1000;
|
|
45583
45574
|
this.inc(ClapprStatsCounter.Seek);
|
|
45584
|
-
this.metrics.extra.watchHistory.push([
|
|
45575
|
+
this.metrics.extra.watchHistory.push([ms, ms]);
|
|
45585
45576
|
}
|
|
45586
45577
|
onTimeUpdate(e) {
|
|
45587
45578
|
const current = e.current * 1000, total = e.total * 1000, l = this.metrics.extra.watchHistory.length;
|
|
@@ -47248,7 +47239,7 @@ class Formatter {
|
|
|
47248
47239
|
|
|
47249
47240
|
const SpeedtestWorkerModule = "// data reported to main thread\n\n// -1=not started, 0=starting, 1=download test, 2=ping+jitter test, 3=upload test, 4=finished, 5=abort\nlet testState = -1;\n// download speed in megabit/s with 2 decimal digits\nlet dlStatus = 0;\n// upload speed in megabit/s with 2 decimal digits\nlet ulStatus = '';\n// ping in milliseconds with 2 decimal digits\nlet pingStatus = '';\n// jitter in milliseconds with 2 decimal digits\nlet jitterStatus = '';\n// client's IP address as reported by getIP.php\nlet clientIp = '';\nlet serverHostName = '';\n//progress of download test 0-1\nlet dlProgress = 0;\n//progress of upload test 0-1\nlet ulProgress = 0;\n//progress of ping+jitter test 0-1\nlet pingProgress = 0;\n//test ID (sent back by telemetry if used, null otherwise)\nlet testId = null;\n\nlet log = ''; //telemetry log\n\nfunction tlog(s) {\n if (settings.telemetry_level >= 2) {\n log += Date.now() + ': ' + s + '\\n';\n }\n}\n\nfunction tverb(s) {\n if (settings.telemetry_level >= 3) {\n log += Date.now() + ': ' + s + '\\n';\n }\n}\n\nfunction twarn(s) {\n if (settings.telemetry_level >= 2) {\n log += Date.now() + ' WARN: ' + s + '\\n';\n }\n\n console.warn(s);\n}\n\n// test settings. can be overridden by sending specific values with the start command\nconst settings = {\n //set to true when in MPOT mode\n mpot: false,\n //order in which tests will be performed as a string. D=Download, U=Upload, P=Ping+Jitter, I=IP, _=1 second delay\n test_order: 'P_D',\n // max duration of upload test in seconds\n time_ul_max: 0,\n // max duration of download test in seconds\n time_dl_max: 15,\n // if set to true, tests will take less time on faster connections\n time_auto: true,\n //time to wait in seconds before actually measuring ul speed (wait for buffers to fill)\n time_ulGraceTime: 3,\n //time to wait in seconds before actually measuring dl speed (wait for TCP window to increase)\n time_dlGraceTime: 1.5,\n // number of pings to perform in ping test\n count_ping: 10,\n // path to a large file or garbage.php, used for download test. must be relative to this js file\n url_dl: 'backend/garbage.php',\n // path to an empty file, used for upload test. must be relative to this js file\n url_ul: 'backend/empty.php',\n // path to an empty file, used for ping test. must be relative to this js file\n url_ping: 'backend/empty.php',\n // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip\n url_getIp: 'backend/getIP.php',\n // if set to true, the server will include ISP info with the IP address\n getIp_ispInfo: true,\n // km or mi=estimate distance from server in km/mi; set to false to disable distance estimation.\n // getIp_ispInfo must be enabled in order for this to work\n getIp_ispInfo_distance: false,\n // number of download streams to use (can be different if enable_quirks is active)\n xhr_dlMultistream: 6,\n // number of upload streams to use (can be different if enable_quirks is active)\n xhr_ulMultistream: 3,\n // how much concurrent requests should be delayed\n xhr_multistreamDelay: 300,\n // 0=fail on errors, 1=attempt to restart a stream if it fails, 2=ignore all errors\n xhr_ignoreErrors: 1,\n // if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize\n // and/or high xhr_dlMultistream)\n xhr_dlUseBlob: false,\n // size in megabytes of the upload blobs sent in the upload test (forced to 4 on chrome mobile)\n xhr_ul_blob_megabytes: 20,\n // size of chunks sent by garbage.php (can be different if enable_quirks is active)\n garbagePhp_chunkSize: 100,\n // enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers,\n // unless they are already being overridden with the start command\n enable_quirks: true,\n // if enabled, the ping test will attempt to calculate the ping more precisely using the Performance API.\n // Currently works perfectly in Chrome, badly in Edge, and not at all in Firefox.\n // If Performance API is not supported or the result is obviously wrong, a fallback is provided.\n ping_allowPerformanceApi: true,\n // can be changed to compensatie for transport overhead. (see doc.md for some other values)\n overheadCompensationFactor: 1.06,\n //if set to true, speed will be reported in mebibits/s instead of megabits/s\n useMebibits: false,\n // 0=disabled, 1=basic (results only), 2=full (results and timing) 3=debug (results+log)\n telemetry_level: 0,\n // path to the script that adds telemetry data to the database\n url_telemetry: 'results/telemetry.php',\n //extra data that can be passed to the telemetry through the settings\n telemetry_extra: ''\n};\n\nlet xhr = null; // array of currently active xhr requests\nlet interval = null; // timer used in tests\nlet test_pointer = 0; //pointer to the next test to run inside settings.test_order\n\n/*\n this function is used on URLs passed in the settings to determine whether we need a ? or an & as a separator\n*/\nfunction url_sep(url) {\n return url.match(/\\?/) ? '&' : '?';\n}\n\n/*\n listener for commands from main thread to this worker.\n commands:\n -status: returns the current status as a JSON string containing testState,\n dlStatus, ulStatus, pingStatus, clientIp, jitterStatus, dlProgress, ulProgress, pingProgress\n -abort: aborts the current test\n -start: starts the test. optionally, settings can be passed as JSON.\n example: start {\"time_ul_max\":\"10\", \"time_dl_max\":\"10\", \"count_ping\":\"50\"}\n*/\nself.addEventListener('message', function (e) {\n const params = e.data.split(' ');\n\n if (params[0] === 'status') {\n // return status\n postMessage(\n {\n testState: testState,\n dlStatus: dlStatus,\n ulStatus: ulStatus,\n pingStatus: pingStatus,\n clientIp: clientIp,\n serverHostName: serverHostName,\n jitterStatus: jitterStatus,\n dlProgress: dlProgress,\n ulProgress: ulProgress,\n pingProgress: pingProgress,\n testId: testId\n }\n );\n }\n if (params[0] === 'start' && testState === -1) {\n const ua = navigator.userAgent;\n\n // start new test\n testState = 0;\n try {\n // parse settings, if present\n let s = {};\n\n try {\n const ss = e.data.substring(5);\n\n if (ss) {\n s = JSON.parse(ss);\n }\n } catch (e) {\n twarn('Error parsing custom settings JSON. Please check your syntax');\n }\n //copy custom settings\n for (const key in s) {\n if (typeof settings[key] !== 'undefined') {\n settings[key] = s[key];\n } else {\n twarn('Unknown setting ignored: ' + key);\n }\n }\n // quirks for specific browsers. apply only if not overridden. more may be added in future releases\n if (settings.enable_quirks || (typeof s.enable_quirks !== 'undefined' && s.enable_quirks)) {\n if (/Firefox.(\\d+\\.\\d+)/i.test(ua)) {\n if (typeof s.ping_allowPerformanceApi === 'undefined') {\n // ff performance API sucks\n settings.ping_allowPerformanceApi = false;\n }\n }\n if (/Edge.(\\d+\\.\\d+)/i.test(ua)) {\n if (typeof s.xhr_dlMultistream === 'undefined') {\n // edge more precise with 3 download streams\n settings.xhr_dlMultistream = 3;\n }\n }\n if (/Chrome.(\\d+)/i.test(ua) && !!self.fetch) {\n if (typeof s.xhr_dlMultistream === 'undefined') {\n // chrome more precise with 5 streams\n settings.xhr_dlMultistream = 5;\n }\n }\n }\n if (/Edge.(\\d+\\.\\d+)/i.test(ua)) {\n //Edge 15 introduced a bug that causes onprogress events to not get fired,\n // we have to use the \"small chunks\" workaround that reduces accuracy\n settings.forceIE11Workaround = true;\n }\n if (/PlayStation 4.(\\d+\\.\\d+)/i.test(ua)) {\n //PS4 browser has the same bug as IE11/Edge\n settings.forceIE11Workaround = true;\n }\n if (/Chrome.(\\d+)/i.test(ua) && /Android|iPhone|iPad|iPod|Windows Phone/i.test(ua)) {\n // cheap af\n // Chrome mobile introduced a limitation somewhere around version 65,\n // we have to limit XHR upload size to 4 megabytes\n settings.xhr_ul_blob_megabytes = 4;\n }\n if (/^((?!chrome|android|crios|fxios).)*safari/i.test(ua)) {\n //Safari also needs the IE11 workaround but only for the MPOT version\n settings.forceIE11Workaround = true;\n }\n // telemetry_level has to be parsed and not just copied\n if (typeof s.telemetry_level !== 'undefined') {\n const telemetryLevels = {\n 'basic': 1,\n 'full': 2,\n 'debug': 3\n };\n\n settings.telemetry_level = telemetryLevels[s.telemetry_level] || 0;\n } // telemetry level\n // transform test_order to uppercase, just in case\n settings.test_order = settings.test_order.toUpperCase();\n } catch (e) {\n twarn('Possible error in custom test settings. Some settings might not have been applied. Exception: ' + e);\n }\n // run the tests\n tverb(JSON.stringify(settings));\n test_pointer = 0;\n let iRun = false,\n dRun = false,\n // uRun = false,\n pRun = false;\n // eslint-disable-next-line no-var\n var runNextTest = function () {\n if (testState === 5) {\n return;\n }\n if (test_pointer >= settings.test_order.length) {\n //test is finished\n if (settings.telemetry_level > 0) {\n sendTelemetry(function (id) {\n testState = 4;\n if (id !== null || id !== undefined) {\n testId = id;\n }\n });\n } else {\n testState = 4;\n }\n\n return;\n }\n switch (settings.test_order.charAt(test_pointer)) {\n case 'I': {\n test_pointer++;\n if (iRun) {\n runNextTest();\n\n return;\n } else {\n iRun = true;\n }\n getIp(runNextTest);\n }\n break;\n case 'D': {\n test_pointer++;\n if (dRun) {\n runNextTest();\n\n return;\n } else {\n dRun = true;\n }\n testState = 1;\n dlTest(runNextTest);\n }\n break;\n case 'U': {\n // test_pointer++;\n // if (uRun) {\n // runNextTest();\n // return;\n // } else uRun = true;\n // testState = 3;\n // ulTest(runNextTest);\n }\n break;\n case 'P': {\n test_pointer++;\n if (pRun) {\n runNextTest();\n\n return;\n } else {\n pRun = true;\n }\n testState = 2;\n pingTest(runNextTest);\n }\n break;\n case '_': {\n test_pointer++;\n setTimeout(runNextTest, 1000);\n }\n break;\n default:\n test_pointer++;\n }\n };\n\n runNextTest();\n }\n if (params[0] === 'abort') {\n // abort command\n if (testState >= 4) {\n return;\n }\n tlog('manually aborted');\n clearRequests(); // stop all xhr activity\n runNextTest = null;\n if (interval) {\n clearInterval(interval);\n } // clear timer if present\n if (settings.telemetry_level > 1) {\n sendTelemetry(function () {\n });\n }\n testState = 5; //set test as aborted\n dlStatus = 0;\n ulStatus = '';\n pingStatus = '';\n jitterStatus = '';\n clientIp = '';\n serverHostName = '';\n dlProgress = 0;\n ulProgress = 0;\n pingProgress = 0;\n }\n});\n\n// stops all XHR activity, aggressively\nfunction clearRequests() {\n tverb('stopping pending XHRs');\n if (xhr) {\n for (let i = 0; i < xhr.length; i++) {\n try {\n xhr[i].onprogress = null;\n xhr[i].onload = null;\n xhr[i].onerror = null;\n } catch (e) {\n console.warn(e);\n }\n try {\n xhr[i].upload.onprogress = null;\n xhr[i].upload.onload = null;\n xhr[i].upload.onerror = null;\n } catch (e) {\n console.warn(e);\n }\n try {\n xhr[i].abort();\n } catch (e) {\n console.warn(e);\n }\n try {\n delete xhr[i];\n } catch (e) {\n console.warn(e);\n }\n }\n xhr = null;\n }\n}\n\n// gets client's IP using url_getIp, then calls the done function\nlet ipCalled = false; // used to prevent multiple accidental calls to getIp\nlet ispInfo = ''; //used for telemetry\n\nfunction getIp(done) {\n tverb('getIp');\n if (ipCalled) {\n return;\n } else {\n ipCalled = true;\n } // getIp already called?\n const startT = new Date().getTime();\n\n xhr = new XMLHttpRequest();\n xhr.onload = function () {\n tlog('IP: ' + xhr.responseText + ', took ' + (new Date().getTime() - startT) + 'ms');\n try {\n const data = JSON.parse(xhr.responseText);\n\n clientIp = data.processedString;\n serverHostName = data.serverHostName;\n ispInfo = data.rawIspInfo;\n } catch (e) {\n clientIp = xhr.responseText;\n ispInfo = '';\n }\n done();\n };\n xhr.onerror = function () {\n tlog('getIp failed, took ' + (new Date().getTime() - startT) + 'ms');\n done();\n };\n const queryParams = [\n settings.mpot ? 'cors=true' : '',\n settings.getIp_ispInfo ?\n `isp=true${settings.getIp_ispInfo_distance ? '&distance=' + settings.getIp_ispInfo_distance : ''}` :\n '',\n 'r=' + Math.random()\n ].filter(Boolean).join('&');\n\n const url = `${settings.url_getIp}${url_sep(settings.url_getIp)}${queryParams}`;\n\n xhr.open(\n 'GET',\n url,\n true\n );\n xhr.send();\n}\n\n// download test, calls done function when it's over\nlet dlCalled = false; // used to prevent multiple accidental calls to dlTest\n\nfunction dlTest(done) {\n tverb('dlTest');\n if (dlCalled) {\n return;\n } else {\n dlCalled = true;\n } // dlTest already called?\n let totLoaded = 0.0, // total number of loaded bytes\n startT = new Date().getTime(), // timestamp when test was started\n bonusT = 0, //how many milliseconds the test has been shortened by (higher on faster connections)\n graceTimeDone = false, //set to true after the grace time is past\n failed = false; // set to true if a stream fails\n\n xhr = [];\n // function to create a download stream. streams are slightly delayed so that they will not end at the same time\n const testStream = function (i, delay) {\n setTimeout(\n function () {\n if (testState !== 1) {\n return;\n } // delayed stream ended up starting after the end of the download test\n tverb('dl test stream started ' + i + ' ' + delay);\n let prevLoaded = 0; // number of bytes loaded last time onprogress was called\n const x = new XMLHttpRequest();\n\n xhr[i] = x;\n xhr[i].onprogress = function (event) {\n tverb('dl stream progress event ' + i + ' ' + event.loaded);\n if (testState !== 1) {\n try {\n x.abort();\n } catch (e) {\n console.warn(e);\n }\n } // just in case this XHR is still running after the download test\n // progress event, add number of new loaded bytes to totLoaded\n const loadDiff = event.loaded <= 0 ? 0 : event.loaded - prevLoaded;\n\n if (isNaN(loadDiff) || !isFinite(loadDiff) || loadDiff < 0) {\n return;\n } // just in case\n totLoaded += loadDiff;\n prevLoaded = event.loaded;\n }.bind(this);\n xhr[i].onload = function () {\n // the large file has been loaded entirely, start again\n tverb('dl stream finished ' + i);\n try {\n xhr[i].abort();\n } catch (e) {\n console.warn(e);\n } // reset the stream data to empty ram\n testStream(i, 0);\n }.bind(this);\n xhr[i].onerror = function () {\n // error\n tverb('dl stream failed ' + i);\n if (settings.xhr_ignoreErrors === 0) {\n failed = true;\n } //abort\n try {\n xhr[i].abort();\n } catch (e) {\n console.warn(e);\n }\n delete xhr[i];\n if (settings.xhr_ignoreErrors === 1) {\n testStream(i, 0);\n } //restart stream\n }.bind(this);\n // send xhr\n try {\n if (settings.xhr_dlUseBlob) {\n xhr[i].responseType = 'blob';\n } else {\n xhr[i].responseType = 'arraybuffer';\n }\n } catch (e) {\n console.warn(e);\n }\n\n const queryParams = [\n settings.mpot ? 'cors=true' : '',\n 'r=' + Math.random(),\n 'ckSize=' + settings.garbagePhp_chunkSize\n ].join('&');\n\n const url = `${settings.url_dl}${url_sep(settings.url_dl)}${queryParams}`;\n\n // random string to prevent caching\n xhr[i].open('GET', url, true);\n xhr[i].send();\n }.bind(this),\n 1 + delay\n );\n }.bind(this);\n\n // open streams\n for (let i = 0; i < settings.xhr_dlMultistream; i++) {\n testStream(i, settings.xhr_multistreamDelay * i);\n }\n // every 200ms, update dlStatus\n interval = setInterval(\n function () {\n tverb('DL: ' + dlStatus + (graceTimeDone ? '' : ' (in grace time)'));\n const t = new Date().getTime() - startT;\n\n if (graceTimeDone) {\n dlProgress = (t + bonusT) / (settings.time_dl_max * 1000);\n }\n if (t < 200) {\n return;\n }\n if (!graceTimeDone) {\n if (t > 1000 * settings.time_dlGraceTime) {\n if (totLoaded > 0) {\n // if the connection is so slow that we didn't get a single chunk yet, do not reset\n startT = new Date().getTime();\n bonusT = 0;\n totLoaded = 0.0;\n }\n graceTimeDone = true;\n }\n } else {\n const speed = totLoaded / (t / 1000.0);\n\n if (settings.time_auto) {\n //decide how much to shorten the test. Every 200ms, the test is shortened by the bonusT calculated here\n const bonus = (6.4 * speed) / 100000;\n\n bonusT += bonus > 800 ? 800 : bonus;\n }\n // update status\n // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied,\n // then everything is divided by 1048576 or 1000000 to go to megabits/mebibits\n dlStatus = ((speed * 8 * settings.overheadCompensationFactor) / (settings.useMebibits ? 1048576 : 1000000));\n if ((t + bonusT) / 1000.0 > settings.time_dl_max || failed) {\n // test is over, stop streams and timer\n if (failed || isNaN(dlStatus)) {\n dlStatus = 'Fail';\n }\n clearRequests();\n clearInterval(interval);\n dlProgress = 1;\n tlog('dlTest: ' + dlStatus + ', took ' + (new Date().getTime() - startT) + 'ms');\n done();\n }\n }\n }.bind(this),\n 200\n );\n}\n\n// ping+jitter test, function done is called when it's over\nlet ptCalled = false; // used to prevent multiple accidental calls to pingTest\n\nfunction pingTest(done) {\n tverb('pingTest');\n if (ptCalled) {\n return;\n } else {\n ptCalled = true;\n } // pingTest already called?\n const startT = new Date().getTime(); //when the test was started\n let prevT = null; // last time a pong was received\n let ping = 0.0; // current ping value\n let jitter = 0.0; // current jitter value\n let i = 0; // counter of pongs received\n let prevInstspd = 0; // last ping time, used for jitter calculation\n\n xhr = [];\n // ping function\n const doPing = function () {\n tverb('ping');\n pingProgress = i / settings.count_ping;\n prevT = new Date().getTime();\n xhr[0] = new XMLHttpRequest();\n xhr[0].onload = function () {\n // pong\n tverb('pong');\n if (i === 0) {\n prevT = new Date().getTime(); // first pong\n } else {\n let instspd = new Date().getTime() - prevT;\n\n if (settings.ping_allowPerformanceApi) {\n try {\n //try to get accurate performance timing using performance api\n let p = performance.getEntries();\n\n p = p[p.length - 1];\n let d = p.responseStart - p.requestStart;\n\n if (d <= 0) {\n d = p.duration;\n }\n if (d > 0 && d < instspd) {\n instspd = d;\n }\n } catch (e) {\n //if not possible, keep the estimate\n tverb('Performance API not supported, using estimate');\n }\n }\n //noticed that some browsers randomly have 0ms ping\n if (instspd < 1) {\n instspd = prevInstspd;\n }\n if (instspd < 1) {\n instspd = 1;\n }\n const instjitter = Math.abs(instspd - prevInstspd);\n\n if (i === 1) {\n ping = instspd;\n }/* first ping, can't tell jitter yet*/ else {\n if (instspd < ping) {\n ping = instspd;\n } // update ping, if the instant ping is lower\n if (i === 2) {\n jitter = instjitter;\n } else {\n //discard the first jitter measurement because it might be much higher than it should be\n jitter = instjitter > jitter ? jitter * 0.3 + instjitter * 0.7 : jitter * 0.8 + instjitter * 0.2;\n } // update jitter, weighted average. spikes in ping values are given more weight.\n }\n prevInstspd = instspd;\n }\n pingStatus = ping.toFixed(2);\n jitterStatus = jitter.toFixed(2);\n i++;\n tverb('ping: ' + pingStatus + ' jitter: ' + jitterStatus);\n if (i < settings.count_ping) {\n doPing();\n } else {\n // more pings to do?\n pingProgress = 1;\n tlog('ping: ' + pingStatus + ' jitter: ' + jitterStatus + ', took ' + (new Date().getTime() - startT) + 'ms');\n done();\n }\n }.bind(this);\n xhr[0].onerror = function () {\n // a ping failed, cancel test\n tverb('ping failed');\n if (settings.xhr_ignoreErrors === 0) {\n //abort\n pingStatus = 'Fail';\n jitterStatus = 'Fail';\n clearRequests();\n tlog('ping test failed, took ' + (new Date().getTime() - startT) + 'ms');\n pingProgress = 1;\n done();\n }\n if (settings.xhr_ignoreErrors === 1) {\n doPing();\n } //retry ping\n if (settings.xhr_ignoreErrors === 2) {\n //ignore failed ping\n i++;\n if (i < settings.count_ping) {\n doPing();\n } else {\n // more pings to do?\n pingProgress = 1;\n tlog('ping: ' + pingStatus + ' jitter: ' + jitterStatus + ', took ' + (new Date().getTime() - startT) + 'ms');\n done();\n }\n }\n }.bind(this);\n // send xhr\n const queryString = [\n settings.mpot ? 'cors=true' : '',\n `r=${Math.random()}`\n ].filter(part => part !== '').join('&');\n\n const url = `${settings.url_ping}${url_sep(settings.url_ping)}${queryString}`;\n\n // random string to prevent caching\n xhr[0].open('GET', url, true);\n xhr[0].send();\n }.bind(this);\n\n doPing(); // start first ping\n}\n\n// telemetry\nfunction sendTelemetry(done) {\n if (settings.telemetry_level < 1) {\n return;\n }\n xhr = new XMLHttpRequest();\n xhr.onload = function () {\n try {\n const parts = xhr.responseText.split(' ');\n\n if (parts[0] === 'id') {\n try {\n const id = parts[1];\n\n done(id);\n } catch (e) {\n done(null);\n }\n } else {\n done(null);\n }\n } catch (e) {\n done(null);\n }\n };\n xhr.onerror = function () {\n console.warn('TELEMETRY ERROR ' + xhr.status);\n done(null);\n };\n xhr.open('POST', settings.url_telemetry + url_sep(settings.url_telemetry) + (settings.mpot ? 'cors=true&' : '') + 'r=' + Math.random(), true);\n const telemetryIspInfo = {\n processedString: clientIp,\n serverHostName: serverHostName,\n rawIspInfo: typeof ispInfo === 'object' ? ispInfo : ''\n };\n\n try {\n const fd = new FormData();\n\n fd.append('ispinfo', JSON.stringify(telemetryIspInfo));\n fd.append('dl', dlStatus);\n fd.append('ul', ulStatus);\n fd.append('ping', pingStatus);\n fd.append('jitter', jitterStatus);\n fd.append('log', settings.telemetry_level > 1 ? log : '');\n fd.append('extra', settings.telemetry_extra);\n xhr.send(fd);\n } catch (ex) {\n const postData = 'extra=' + encodeURIComponent(settings.telemetry_extra) + '&ispinfo=' + encodeURIComponent(JSON.stringify(telemetryIspInfo)) + '&dl=' + encodeURIComponent(dlStatus) + '&ul=' + encodeURIComponent(ulStatus) + '&ping=' + encodeURIComponent(pingStatus) + '&jitter=' + encodeURIComponent(jitterStatus) + '&log=' + encodeURIComponent(settings.telemetry_level > 1 ? log : '');\n\n xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n xhr.send(postData);\n }\n}\n";
|
|
47250
47241
|
|
|
47251
|
-
const T
|
|
47242
|
+
// const T = 'plugins.clappr_nerd_stats.speedtest.Speedtest';
|
|
47252
47243
|
class Speedtest {
|
|
47253
47244
|
worker = null;
|
|
47254
47245
|
workerUrl = null;
|
|
@@ -47559,7 +47550,6 @@ class Speedtest {
|
|
|
47559
47550
|
}
|
|
47560
47551
|
}
|
|
47561
47552
|
this._state = 3;
|
|
47562
|
-
trace(`${T$g} start`, { state: this._state, server: this._selectedServer, settings: this._settings });
|
|
47563
47553
|
// TODO don't run until properly initialized (url_ping, etc)
|
|
47564
47554
|
this.worker.postMessage('start ' + JSON.stringify(this._settings));
|
|
47565
47555
|
// ... [rest of the logic remains unchanged] ...
|
|
@@ -47585,7 +47575,7 @@ class Speedtest {
|
|
|
47585
47575
|
const DIGITS_THRESHOLD = 99999;
|
|
47586
47576
|
const DEFAULT_DOWNLOAD_SPEED = '0.00';
|
|
47587
47577
|
const DRAW_SIZE = 5;
|
|
47588
|
-
const T
|
|
47578
|
+
// const T = 'plugins.clappr_nerd_stats.speedtest';
|
|
47589
47579
|
function limitDigits(value) {
|
|
47590
47580
|
return value > DIGITS_THRESHOLD ? '> ' + DIGITS_THRESHOLD : value.toFixed(2);
|
|
47591
47581
|
}
|
|
@@ -47613,7 +47603,6 @@ const getColor = (speedValue) => {
|
|
|
47613
47603
|
}
|
|
47614
47604
|
};
|
|
47615
47605
|
function drawSpeedTestResults() {
|
|
47616
|
-
trace(`${T$f} drawSpeedTestResults`);
|
|
47617
47606
|
const canvas = document.getElementById('nerd-stats-speed-test-canvas');
|
|
47618
47607
|
if (!canvas) {
|
|
47619
47608
|
return;
|
|
@@ -47636,7 +47625,6 @@ const initSpeedTest = (customMetrics) => {
|
|
|
47636
47625
|
return inited;
|
|
47637
47626
|
}
|
|
47638
47627
|
inited = (async () => {
|
|
47639
|
-
trace(`${T$f} initSpeedTest run`);
|
|
47640
47628
|
// TODO: fix server selection
|
|
47641
47629
|
// const response = await fetch('https://iam.gcdn.co/info/json');
|
|
47642
47630
|
// const data = await response.json();
|
|
@@ -47691,7 +47679,6 @@ const initSpeedTest = (customMetrics) => {
|
|
|
47691
47679
|
await fetch('https://iam.gcdn.co/info/json')
|
|
47692
47680
|
.then(r => r.json())
|
|
47693
47681
|
.then(data => {
|
|
47694
|
-
trace(`${T$f} initSpeedTest fetched`);
|
|
47695
47682
|
const country = data['Server Country code'].toLowerCase();
|
|
47696
47683
|
const server = serversList.find(s => s.country === country) || serversList[0];
|
|
47697
47684
|
if (!server) {
|
|
@@ -47699,7 +47686,6 @@ const initSpeedTest = (customMetrics) => {
|
|
|
47699
47686
|
}
|
|
47700
47687
|
speedTest.addTestPoint(server);
|
|
47701
47688
|
speedTest.setSelectedServer(server);
|
|
47702
|
-
trace(`${T$f} initSpeedTest done`);
|
|
47703
47689
|
});
|
|
47704
47690
|
})();
|
|
47705
47691
|
return inited;
|
|
@@ -47710,13 +47696,11 @@ const stopSpeedtest = () => {
|
|
|
47710
47696
|
}
|
|
47711
47697
|
};
|
|
47712
47698
|
const startSpeedtest = () => {
|
|
47713
|
-
trace(`${T$f} startSpeedtest`);
|
|
47714
47699
|
if (speedTest.getState() !== 3) {
|
|
47715
47700
|
speedTest.start();
|
|
47716
47701
|
}
|
|
47717
47702
|
};
|
|
47718
47703
|
const clearSpeedTestResults = () => {
|
|
47719
|
-
trace(`${T$f} clearSpeedTestResults`);
|
|
47720
47704
|
speedtestResults.splice(0, speedtestResults.length);
|
|
47721
47705
|
};
|
|
47722
47706
|
function configureSpeedTest(servers) {
|
|
@@ -47968,10 +47952,8 @@ class NerdStats extends UICorePlugin {
|
|
|
47968
47952
|
this.$el.show();
|
|
47969
47953
|
this.statsBoxElem.scrollTop(this.statsBoxElem.scrollTop());
|
|
47970
47954
|
this.open = true;
|
|
47971
|
-
this.refreshSpeedTest();
|
|
47972
47955
|
initSpeedTest(this.speedtestMetrics)
|
|
47973
47956
|
.then(() => {
|
|
47974
|
-
trace(`${T$e} show initSpeedTest ready`);
|
|
47975
47957
|
startSpeedtest();
|
|
47976
47958
|
})
|
|
47977
47959
|
.catch((e) => {
|
|
@@ -48001,7 +47983,6 @@ class NerdStats extends UICorePlugin {
|
|
|
48001
47983
|
.text(this.metrics.general.resolution.height);
|
|
48002
47984
|
}
|
|
48003
47985
|
estimateQuality() {
|
|
48004
|
-
trace(`${T$e} estimateQuality`);
|
|
48005
47986
|
const videoQualityNames = [
|
|
48006
47987
|
'SD (480p)',
|
|
48007
47988
|
'HD (720p)',
|
|
@@ -48026,7 +48007,6 @@ class NerdStats extends UICorePlugin {
|
|
|
48026
48007
|
prefix + videoQualityNames[liveQuality - 1];
|
|
48027
48008
|
}
|
|
48028
48009
|
updateMetrics(metrics) {
|
|
48029
|
-
trace(`${T$e} updateMetrics`, { custom: this.speedtestMetrics });
|
|
48030
48010
|
Object.assign(this.metrics, metrics);
|
|
48031
48011
|
this.metrics.custom = {
|
|
48032
48012
|
...this.speedtestMetrics,
|
|
@@ -48174,9 +48154,9 @@ class NerdStats extends UICorePlugin {
|
|
|
48174
48154
|
clearSpeedTestResults();
|
|
48175
48155
|
drawSpeedTestResults();
|
|
48176
48156
|
}, 200);
|
|
48177
|
-
|
|
48178
|
-
|
|
48179
|
-
|
|
48157
|
+
setTimeout(() => {
|
|
48158
|
+
startSpeedtest();
|
|
48159
|
+
}, 800);
|
|
48180
48160
|
}
|
|
48181
48161
|
formatPlaybackName(playbackType) {
|
|
48182
48162
|
switch (playbackType) {
|
|
@@ -50572,15 +50552,18 @@ function formatLevelLabel(level) {
|
|
|
50572
50552
|
return `${h}p`;
|
|
50573
50553
|
}
|
|
50574
50554
|
|
|
50575
|
-
const seekTimeHTML = "<span
|
|
50555
|
+
const seekTimeHTML = "<span id=\"mc-seek-time\" class=\"seek-time__pos\"></span>\n<span id=\"mc-duration\" class=\"seek-time__duration\"></span>\n\n";
|
|
50576
50556
|
|
|
50577
50557
|
// Copyright 2014 Globo.com Player authors. All rights reserved.
|
|
50578
50558
|
// Use of this source code is governed by a BSD-style
|
|
50579
50559
|
// license that can be found at https://github.com/clappr/clappr-plugins/blob/master/LICENSE
|
|
50580
50560
|
const { formatTime } = Utils;
|
|
50561
|
+
// const T = 'plugins.seek_time'
|
|
50581
50562
|
/**
|
|
50582
|
-
* `PLUGIN` that adds a seek time indicator
|
|
50563
|
+
* `PLUGIN` that adds a seek time indicator when the mouse pointer is over the seek bar.
|
|
50583
50564
|
* @beta
|
|
50565
|
+
* @remarks
|
|
50566
|
+
* Configuration options - {@link SeekTimeSettings}
|
|
50584
50567
|
*/
|
|
50585
50568
|
class SeekTime extends UICorePlugin {
|
|
50586
50569
|
get name() {
|
|
@@ -50593,7 +50576,6 @@ class SeekTime extends UICorePlugin {
|
|
|
50593
50576
|
get attributes() {
|
|
50594
50577
|
return {
|
|
50595
50578
|
class: 'seek-time',
|
|
50596
|
-
'data-seek-time': '',
|
|
50597
50579
|
};
|
|
50598
50580
|
}
|
|
50599
50581
|
get isLiveStreamWithDvr() {
|
|
@@ -50601,23 +50583,21 @@ class SeekTime extends UICorePlugin {
|
|
|
50601
50583
|
this.core.activeContainer.getPlaybackType() === Playback.LIVE &&
|
|
50602
50584
|
this.core.activeContainer.isDvrEnabled());
|
|
50603
50585
|
}
|
|
50604
|
-
get
|
|
50605
|
-
return
|
|
50586
|
+
get showDuration() {
|
|
50587
|
+
return (this.core.options.seekTime?.duration === true &&
|
|
50588
|
+
this.core.activeContainer?.getPlaybackType() !== Playback.LIVE);
|
|
50606
50589
|
}
|
|
50607
50590
|
hoveringOverSeekBar = false;
|
|
50608
50591
|
hoverPosition = 0;
|
|
50609
50592
|
displayedDuration = null;
|
|
50610
50593
|
displayedSeekTime = null;
|
|
50611
50594
|
duration = 0;
|
|
50612
|
-
// private firstFragDateTime = 0;
|
|
50613
|
-
rendered = false;
|
|
50614
|
-
$durationEl = null;
|
|
50615
|
-
$seekTimeEl = null;
|
|
50616
50595
|
/**
|
|
50617
50596
|
* @internal
|
|
50618
50597
|
*/
|
|
50619
50598
|
bindEvents() {
|
|
50620
50599
|
this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
|
|
50600
|
+
this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
|
|
50621
50601
|
}
|
|
50622
50602
|
onCoreReady() {
|
|
50623
50603
|
const mediaControl = this.core.getPlugin('media_control');
|
|
@@ -50625,11 +50605,6 @@ class SeekTime extends UICorePlugin {
|
|
|
50625
50605
|
this.listenTo(mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mount);
|
|
50626
50606
|
this.listenTo(mediaControl, Events$1.MEDIACONTROL_MOUSEMOVE_SEEKBAR, this.showTime);
|
|
50627
50607
|
this.listenTo(mediaControl, Events$1.MEDIACONTROL_MOUSELEAVE_SEEKBAR, this.hideTime);
|
|
50628
|
-
this.listenTo(mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED, this.onContainerChanged);
|
|
50629
|
-
if (this.core.activeContainer) {
|
|
50630
|
-
this.listenTo(this.core.activeContainer, Events$1.CONTAINER_PLAYBACKDVRSTATECHANGED, this.update);
|
|
50631
|
-
this.listenTo(this.core.activeContainer, Events$1.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
50632
|
-
}
|
|
50633
50608
|
}
|
|
50634
50609
|
onContainerChanged() {
|
|
50635
50610
|
this.listenTo(this.core.activeContainer, Events$1.CONTAINER_PLAYBACKDVRSTATECHANGED, this.update);
|
|
@@ -50655,41 +50630,37 @@ class SeekTime extends UICorePlugin {
|
|
|
50655
50630
|
this.hoverPosition = Math.min(1, Math.max(offset / mediaControl.$seekBarContainer.width(), 0));
|
|
50656
50631
|
}
|
|
50657
50632
|
getSeekTime() {
|
|
50658
|
-
|
|
50633
|
+
return this.isLiveStreamWithDvr
|
|
50659
50634
|
? this.duration - this.hoverPosition * this.duration
|
|
50660
50635
|
: this.hoverPosition * this.duration;
|
|
50661
|
-
return { seekTime };
|
|
50662
50636
|
}
|
|
50663
50637
|
update() {
|
|
50664
|
-
if (!this.rendered) {
|
|
50665
|
-
// update() is always called after a render
|
|
50666
|
-
return;
|
|
50667
|
-
}
|
|
50668
50638
|
if (!this.shouldBeVisible()) {
|
|
50669
50639
|
this.$el.hide();
|
|
50670
50640
|
this.$el.css('left', '-100%');
|
|
50671
50641
|
return;
|
|
50672
50642
|
}
|
|
50673
50643
|
const seekTime = this.getSeekTime();
|
|
50674
|
-
let currentSeekTime = formatTime(seekTime
|
|
50644
|
+
let currentSeekTime = formatTime(seekTime, false);
|
|
50675
50645
|
if (this.isLiveStreamWithDvr) {
|
|
50676
50646
|
currentSeekTime = `-${currentSeekTime}`;
|
|
50677
50647
|
}
|
|
50678
50648
|
// only update dom if necessary, ie time actually changed
|
|
50679
50649
|
if (currentSeekTime !== this.displayedSeekTime) {
|
|
50680
|
-
this.$
|
|
50650
|
+
this.$el.find('#mc-seek-time').text(currentSeekTime);
|
|
50681
50651
|
this.displayedSeekTime = currentSeekTime;
|
|
50682
50652
|
}
|
|
50683
|
-
|
|
50684
|
-
|
|
50653
|
+
const $durationEl = this.$el.find('#mc-duration');
|
|
50654
|
+
if (this.showDuration) {
|
|
50655
|
+
$durationEl.show();
|
|
50685
50656
|
const currentDuration = formatTime(this.duration, false);
|
|
50686
50657
|
if (currentDuration !== this.displayedDuration) {
|
|
50687
|
-
|
|
50658
|
+
$durationEl.text(currentDuration);
|
|
50688
50659
|
this.displayedDuration = currentDuration;
|
|
50689
50660
|
}
|
|
50690
50661
|
}
|
|
50691
50662
|
else {
|
|
50692
|
-
|
|
50663
|
+
$durationEl.hide();
|
|
50693
50664
|
}
|
|
50694
50665
|
// the element must be unhidden before its width is requested, otherwise it's width will be reported as 0
|
|
50695
50666
|
this.$el.show();
|
|
@@ -50712,16 +50683,10 @@ class SeekTime extends UICorePlugin {
|
|
|
50712
50683
|
* @internal
|
|
50713
50684
|
*/
|
|
50714
50685
|
render() {
|
|
50715
|
-
this.rendered = true;
|
|
50716
50686
|
this.displayedDuration = null;
|
|
50717
50687
|
this.displayedSeekTime = null;
|
|
50718
50688
|
this.$el.html(SeekTime.template());
|
|
50719
50689
|
this.$el.hide();
|
|
50720
|
-
// this.mediaControl.$el.append(this.el);
|
|
50721
|
-
this.$seekTimeEl = this.$el.find('#mc-seek-time');
|
|
50722
|
-
this.$durationEl = this.$el.find('#mc-duration');
|
|
50723
|
-
this.$durationEl.hide();
|
|
50724
|
-
this.update();
|
|
50725
50690
|
return this;
|
|
50726
50691
|
}
|
|
50727
50692
|
mount() {
|