Attempt to reduce issues when loading the mediaplayer js code, ref #609
This commit is contained in:
+334
-334
@@ -1,126 +1,257 @@
|
|||||||
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
||||||
|
|
||||||
var LMS = LMS || {};
|
|
||||||
|
|
||||||
// Keep in sync with MediaPlayer::TranscodingMode cpp
|
// Keep in sync with MediaPlayer::TranscodingMode cpp
|
||||||
const TranscodingMode = {
|
LMSTranscodingMode = {
|
||||||
Never: 0,
|
Never: 0,
|
||||||
Always: 1,
|
Always: 1,
|
||||||
IfFormatNotSupported: 2,
|
IfFormatNotSupported: 2,
|
||||||
}
|
}
|
||||||
|
Object.freeze(LMSTranscodingMode);
|
||||||
|
|
||||||
const Mode = {
|
class LMSMediaPlayer {
|
||||||
|
// How much to increase / decrease volume when adjusting it with keyboard shortcuts
|
||||||
|
static #volumeStepAmount = 0.05;
|
||||||
|
|
||||||
|
// How much to seek back / forward (in seconds) with keyboard shortcuts
|
||||||
|
static #seekAmount = 5;
|
||||||
|
|
||||||
|
static #Mode = {
|
||||||
Transcoding: 1,
|
Transcoding: 1,
|
||||||
File: 2,
|
File: 2,
|
||||||
}
|
}
|
||||||
Object.freeze(Mode);
|
|
||||||
|
|
||||||
// How much to increase / decrease volume when adjusting it with keyboard shortcuts
|
#root;
|
||||||
const volumeStepAmount = 0.05;
|
#elems;
|
||||||
|
#offset;
|
||||||
|
#trackId;
|
||||||
|
#duration;
|
||||||
|
#audioNativeSrc;
|
||||||
|
#audioTranscodingSrc;
|
||||||
|
#settings;
|
||||||
|
#playedDuration;
|
||||||
|
#lastStartPlaying;
|
||||||
|
#audioIsInit;
|
||||||
|
#pendingTrackParameters;
|
||||||
|
#gainNode;
|
||||||
|
#audioCtx;
|
||||||
|
|
||||||
// How much to seek back / forward (in seconds) with keyboard shortcuts
|
constructor(root, defaultSettings) {
|
||||||
const seekAmount = 5;
|
this.#root = root;
|
||||||
|
this.#elems = {};
|
||||||
|
this.#offset = 0;
|
||||||
|
this.#trackId = null;
|
||||||
|
this.#duration = 0;
|
||||||
|
this.#audioNativeSrc;
|
||||||
|
this.#audioTranscodingSrc;
|
||||||
|
this.#settings = {};
|
||||||
|
this.#playedDuration = 0;
|
||||||
|
this.#lastStartPlaying = null;
|
||||||
|
this.#audioIsInit = false;
|
||||||
|
this.#pendingTrackParameters = null;
|
||||||
|
this.#gainNode = null;
|
||||||
|
this.#audioCtx = null;
|
||||||
|
|
||||||
LMS.mediaplayer = function () {
|
this.#elems.audio = document.getElementById("lms-mp-audio");
|
||||||
let _root = {};
|
this.#elems.playpause = document.getElementById("lms-mp-playpause");
|
||||||
let _elems = {};
|
this.#elems.previous = document.getElementById("lms-mp-previous");
|
||||||
let _offset = 0;
|
this.#elems.next = document.getElementById("lms-mp-next");
|
||||||
let _trackId = null;
|
this.#elems.progress = document.getElementById("lms-mp-progress");
|
||||||
let _duration = 0;
|
this.#elems.seek = document.getElementById("lms-mp-seek");
|
||||||
let _audioNativeSrc;
|
this.#elems.curtime = document.getElementById("lms-mp-curtime");
|
||||||
let _audioTranscodingSrc;
|
this.#elems.duration = document.getElementById("lms-mp-duration");
|
||||||
let _settings = {};
|
this.#elems.volume = document.getElementById("lms-mp-volume");
|
||||||
let _playedDuration = 0;
|
this.#elems.volumeslider = document.getElementById("lms-mp-volume-slider");
|
||||||
let _lastStartPlaying = null;
|
this.#elems.transcodingActive = document.getElementById("lms-transcoding-active");
|
||||||
let _audioIsInit = false;
|
|
||||||
let _pendingTrackParameters = null;
|
|
||||||
let _gainNode = null;
|
|
||||||
let _audioCtx = null;
|
|
||||||
|
|
||||||
let _unlock = function() {
|
this.#elems.playpause.addEventListener("click", () => {
|
||||||
document.removeEventListener("touchstart", _unlock);
|
this.#playPause();
|
||||||
document.removeEventListener("touchend", _unlock);
|
});
|
||||||
document.removeEventListener("click", _unlock);
|
|
||||||
_initAudioCtx();
|
this.#elems.previous.addEventListener("click", () => {
|
||||||
|
this.#playPrevious();
|
||||||
|
});
|
||||||
|
this.#elems.next.addEventListener("click", () => {
|
||||||
|
this.#playNext();
|
||||||
|
});
|
||||||
|
this.#elems.seek.addEventListener("change", () => {
|
||||||
|
this.#seekTo(parseInt(this.#elems.seek.value, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("play", this.#updateControls.bind(this));
|
||||||
|
this.#elems.audio.addEventListener("playing", this.#updateControls.bind(this));
|
||||||
|
this.#elems.audio.addEventListener("pause", this.#updateControls.bind(this));
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("play", this.#updateMediaSessionState.bind(this));
|
||||||
|
this.#elems.audio.addEventListener("playing", this.#updateMediaSessionState.bind(this));
|
||||||
|
this.#elems.audio.addEventListener("pause", this.#updateMediaSessionState.bind(this));
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("pause", this.#pauseTimer);
|
||||||
|
this.#elems.audio.addEventListener("playing", this.#startTimer.bind(this));
|
||||||
|
this.#elems.audio.addEventListener("waiting", this.#pauseTimer.bind(this));
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("timeupdate", () => {
|
||||||
|
this.#elems.progress.style.width = "" + ((this.#offset + this.#elems.audio.currentTime) / this.#duration) * 100 + "%";
|
||||||
|
this.#elems.curtime.innerHTML = this.#durationToString(this.#offset + this.#elems.audio.currentTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("ended", () => {
|
||||||
|
this.#resetTimer();
|
||||||
|
Wt.emit(this.#root, "playbackEnded");
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#elems.audio.addEventListener("canplay", () => {
|
||||||
|
if (this.#getAudioMode() == LMSMediaPlayer.#Mode.Transcoding) {
|
||||||
|
this.#elems.transcodingActive.style.display = "inline";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.#elems.transcodingActive.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#initVolume();
|
||||||
|
this.#initDefaultSettings(defaultSettings);
|
||||||
|
|
||||||
|
this.#elems.volumeslider.addEventListener("input", () => {
|
||||||
|
this.#setVolume(this.#elems.volumeslider.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#elems.volume.addEventListener("click", () => {
|
||||||
|
if (this.#elems.audio.volume != 0) {
|
||||||
|
this.#setVolume(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.#setVolume(this.#elems.lastvolume);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
let handled = false;
|
||||||
|
|
||||||
|
if (event.target instanceof HTMLInputElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.keyCode == 32) {
|
||||||
|
this.#playPause();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && !event.shiftKey && event.keyCode == 37) {
|
||||||
|
this.#playPrevious();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && !event.shiftKey && event.keyCode == 39) {
|
||||||
|
this.#playNext();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && event.keyCode == 40) {
|
||||||
|
this.#stepVolumeDown();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && event.keyCode == 38) {
|
||||||
|
this.#stepVolumeUp();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && event.shiftKey && event.keyCode == 37) {
|
||||||
|
this.#seekBack();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (event.ctrlKey && event.shiftKey && event.keyCode == 39) {
|
||||||
|
this.#seekForward();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled)
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("touchstart", this.#unlock.bind(this));
|
||||||
|
document.addEventListener("touchend", this.#unlock.bind(this));
|
||||||
|
document.addEventListener("click", this.#unlock.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
#unlock() {
|
||||||
|
document.removeEventListener("touchstart", this.#unlock.bind(this));
|
||||||
|
document.removeEventListener("touchend", this.#unlock.bind(this));
|
||||||
|
document.removeEventListener("click", this.#unlock.bind(this));
|
||||||
|
this.#initAudioCtx();
|
||||||
};
|
};
|
||||||
|
|
||||||
let _initAudioCtx = function() {
|
#initAudioCtx() {
|
||||||
if (_audioIsInit) {
|
if (this.#audioIsInit) {
|
||||||
_audioCtx.resume(); // not sure of this
|
this.#audioCtx.resume(); // not sure of this
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_audioIsInit = true;
|
this.#audioIsInit = true;
|
||||||
|
|
||||||
_audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
this.#audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
_gainNode = _audioCtx.createGain();
|
this.#gainNode = this.#audioCtx.createGain();
|
||||||
let source = _audioCtx.createMediaElementSource(_elems.audio);
|
let source = this.#audioCtx.createMediaElementSource(this.#elems.audio);
|
||||||
source.connect(_gainNode);
|
source.connect(this.#gainNode);
|
||||||
_gainNode.connect(_audioCtx.destination);
|
this.#gainNode.connect(this.#audioCtx.destination);
|
||||||
_audioCtx.resume(); // not sure of this
|
this.#audioCtx.resume(); // not sure of this
|
||||||
|
|
||||||
if ("mediaSession" in navigator) {
|
if ("mediaSession" in navigator) {
|
||||||
navigator.mediaSession.setActionHandler("play", function() {
|
navigator.mediaSession.setActionHandler("play", () => {
|
||||||
_playPause();
|
this.#playPause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("pause", function() {
|
navigator.mediaSession.setActionHandler("pause", () => {
|
||||||
_playPause();
|
this.#playPause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("previoustrack", function() {
|
navigator.mediaSession.setActionHandler("previoustrack", () => {
|
||||||
_playPrevious();
|
this.#playPrevious();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("nexttrack", function() {
|
navigator.mediaSession.setActionHandler("nexttrack", () => {
|
||||||
_playNext();
|
this.#playNext();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("seekto", function(e) {
|
navigator.mediaSession.setActionHandler("seekto", (e) => {
|
||||||
_seekTo(e.seekTime);
|
this.#seekTo(e.seekTime);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pendingTrackParameters != null) {
|
if (this.#pendingTrackParameters != null) {
|
||||||
_applyAudioTrackParameters(_pendingTrackParameters);
|
this.#applyAudioTrackParameters(this.#pendingTrackParameters);
|
||||||
_pendingTrackParameters = null;
|
this.#pendingTrackParameters = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _updateControls = function() {
|
#updateControls() {
|
||||||
const pauseClass = "fa-pause";
|
const pauseClass = "fa-pause";
|
||||||
const playClass = "fa-play";
|
const playClass = "fa-play";
|
||||||
|
|
||||||
if (_elems.audio.paused) {
|
if (this.#elems.audio.paused) {
|
||||||
_elems.playpause.firstElementChild.classList.remove(pauseClass);
|
this.#elems.playpause.firstElementChild.classList.remove(pauseClass);
|
||||||
_elems.playpause.firstElementChild.classList.add(playClass);
|
this.#elems.playpause.firstElementChild.classList.add(playClass);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_elems.playpause.firstElementChild.classList.remove(playClass);
|
this.#elems.playpause.firstElementChild.classList.remove(playClass);
|
||||||
_elems.playpause.firstElementChild.classList.add(pauseClass);
|
this.#elems.playpause.firstElementChild.classList.add(pauseClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _startTimer = function() {
|
#startTimer() {
|
||||||
if (_lastStartPlaying == null)
|
if (this.#lastStartPlaying == null)
|
||||||
Wt.emit(_root, "scrobbleListenNow", _trackId);
|
Wt.emit(this.#root, "scrobbleListenNow", this.#trackId);
|
||||||
_lastStartPlaying = Date.now();
|
this.#lastStartPlaying = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
let _pauseTimer = function() {
|
#pauseTimer() {
|
||||||
if (_lastStartPlaying != null) {
|
if (this.#lastStartPlaying != null) {
|
||||||
_playedDuration += Date.now() - _lastStartPlaying;
|
this.#playedDuration += Date.now() - this.#lastStartPlaying;
|
||||||
_lastStartPlaying = null;
|
this.#lastStartPlaying = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _resetTimer = function() {
|
#resetTimer() {
|
||||||
if (_lastStartPlaying != null)
|
if (this.#lastStartPlaying != null)
|
||||||
_pauseTimer();
|
this.#pauseTimer();
|
||||||
|
|
||||||
if (_playedDuration > 0) {
|
if (this.#playedDuration > 0) {
|
||||||
Wt.emit(_root, "scrobbleListenFinished", _trackId, _playedDuration);
|
Wt.emit(this.#root, "scrobbleListenFinished", this.#trackId, this.#playedDuration);
|
||||||
_playedDuration = 0;
|
this.#playedDuration = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _durationToString = function (duration) {
|
#durationToString(duration) {
|
||||||
const seconds = parseInt(duration, 10);
|
const seconds = parseInt(duration, 10);
|
||||||
const h = Math.floor(seconds / 3600);
|
const h = Math.floor(seconds / 3600);
|
||||||
const m = Math.floor((seconds % 3600) / 60);
|
const m = Math.floor((seconds % 3600) / 60);
|
||||||
@@ -132,332 +263,173 @@ LMS.mediaplayer = function () {
|
|||||||
].filter(Boolean).join(':');
|
].filter(Boolean).join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
let _playTrack = function() {
|
#playTrack() {
|
||||||
_elems.audio.play()
|
this.#elems.audio.play()
|
||||||
.then(_ => {})
|
.then(_ => { })
|
||||||
.catch(error => { console.log("Cannot play audio: " + error); });
|
.catch(error => { console.log("Cannot play audio: " + error); });
|
||||||
}
|
}
|
||||||
|
|
||||||
let _playPause = function() {
|
#playPause() {
|
||||||
_initAudioCtx();
|
this.#initAudioCtx();
|
||||||
|
|
||||||
if (_elems.audio.paused && _elems.audio.children.length > 0) {
|
if (this.#elems.audio.paused && this.#elems.audio.children.length > 0) {
|
||||||
_playTrack();
|
this.#playTrack();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_elems.audio.pause();
|
this.#elems.audio.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
let _playPrevious = function() {
|
#playPrevious() {
|
||||||
_initAudioCtx();
|
this.#initAudioCtx();
|
||||||
Wt.emit(_root, "playPrevious");
|
Wt.emit(this.#root, "playPrevious");
|
||||||
}
|
}
|
||||||
|
|
||||||
let _playNext = function() {
|
#playNext() {
|
||||||
_initAudioCtx();
|
this.#initAudioCtx();
|
||||||
Wt.emit(_root, "playNext");
|
Wt.emit(this.#root, "playNext");
|
||||||
}
|
}
|
||||||
|
|
||||||
let _initVolume = function() {
|
#initVolume() {
|
||||||
if (typeof(Storage) !== "undefined" && localStorage.volume) {
|
if (typeof (Storage) !== "undefined" && localStorage.volume) {
|
||||||
_elems.volumeslider.value = Number(localStorage.volume);
|
this.#elems.volumeslider.value = Number(localStorage.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setVolume(_elems.volumeslider.value);
|
this.#setVolume(this.#elems.volumeslider.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _initDefaultSettings = function(defaultSettings) {
|
#initDefaultSettings = function (defaultSettings) {
|
||||||
if (typeof(Storage) !== "undefined" && localStorage.settings) {
|
if (typeof (Storage) !== "undefined" && localStorage.settings) {
|
||||||
_settings = Object.assign(defaultSettings, JSON.parse(localStorage.settings));
|
this.#settings = Object.assign(defaultSettings, JSON.parse(localStorage.settings));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_settings = defaultSettings;
|
this.#settings = defaultSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wt.emit(_root, "settingsLoaded", JSON.stringify(_settings));
|
Wt.emit(this.#root, "settingsLoaded", JSON.stringify(this.#settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _setVolume = function(volume) {
|
#setVolume(volume) {
|
||||||
_elems.lastvolume = _elems.audio.volume;
|
this.#elems.lastvolume = this.#elems.audio.volume;
|
||||||
|
|
||||||
_elems.audio.volume = volume;
|
this.#elems.audio.volume = volume;
|
||||||
_elems.volumeslider.value = volume;
|
this.#elems.volumeslider.value = volume;
|
||||||
|
|
||||||
if (volume > 0.5) {
|
if (volume > 0.5) {
|
||||||
_elems.volume.classList.remove("fa-volume-off");
|
this.#elems.volume.classList.remove("fa-volume-off");
|
||||||
_elems.volume.classList.remove("fa-volume-down");
|
this.#elems.volume.classList.remove("fa-volume-down");
|
||||||
_elems.volume.classList.add("fa-volume-up");
|
this.#elems.volume.classList.add("fa-volume-up");
|
||||||
}
|
}
|
||||||
else if (volume > 0) {
|
else if (volume > 0) {
|
||||||
_elems.volume.classList.remove("fa-volume-off");
|
this.#elems.volume.classList.remove("fa-volume-off");
|
||||||
_elems.volume.classList.remove("fa-volume-up");
|
this.#elems.volume.classList.remove("fa-volume-up");
|
||||||
_elems.volume.classList.add("fa-volume-down");
|
this.#elems.volume.classList.add("fa-volume-down");
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_elems.volume.classList.remove("fa-volume-up");
|
this.#elems.volume.classList.remove("fa-volume-up");
|
||||||
_elems.volume.classList.remove("fa-volume-down");
|
this.#elems.volume.classList.remove("fa-volume-down");
|
||||||
_elems.volume.classList.add("fa-volume-off");
|
this.#elems.volume.classList.add("fa-volume-off");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(Storage) !== "undefined") {
|
if (typeof (Storage) !== "undefined") {
|
||||||
localStorage.volume = volume;
|
localStorage.volume = volume;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _stepVolumeDown = function() {
|
#stepVolumeDown() {
|
||||||
let currentVolume = _elems.audio.volume;
|
let currentVolume = this.#elems.audio.volume;
|
||||||
let remainder = (currentVolume * 10) % (volumeStepAmount * 10);
|
let remainder = (currentVolume * 10) % (LMSMediaPlayer.#volumeStepAmount * 10);
|
||||||
let newVolume = remainder === 0 ? currentVolume - volumeStepAmount : currentVolume - (remainder / 10);
|
let newVolume = remainder === 0 ? currentVolume - LMSMediaPlayer.#volumeStepAmount : currentVolume - (remainder / 10);
|
||||||
_setVolume(Math.max(newVolume, 0));
|
this.#setVolume(Math.max(newVolume, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _stepVolumeUp = function() {
|
#stepVolumeUp() {
|
||||||
let currentVolume = _elems.audio.volume;
|
let currentVolume = this.#elems.audio.volume;
|
||||||
let remainder = (currentVolume * 10) % (volumeStepAmount * 10);
|
let remainder = (currentVolume * 10) % (LMSMediaPlayer.#volumeStepAmount * 10);
|
||||||
let newVolume = remainder === 0 ? currentVolume + volumeStepAmount : currentVolume + (volumeStepAmount - (remainder / 10));
|
let newVolume = remainder === 0 ? currentVolume + LMSMediaPlayer.#volumeStepAmount : currentVolume + (LMSMediaPlayer.#volumeStepAmount - (remainder / 10));
|
||||||
_setVolume(Math.min(newVolume, 1));
|
this.#setVolume(Math.min(newVolume, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _setReplayGain = function (replayGain) {
|
#setReplayGain(replayGain) {
|
||||||
_gainNode.gain.value = Math.pow(10, (_settings.replayGain.preAmpGain + replayGain) / 20);
|
this.#gainNode.gain.value = Math.pow(10, (this.#settings.replayGain.preAmpGain + replayGain) / 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _seekTo = function(seekTime) {
|
#seekTo(seekTime) {
|
||||||
_initAudioCtx();
|
this.#initAudioCtx();
|
||||||
let mode = _getAudioMode();
|
let mode = this.#getAudioMode();
|
||||||
if (!mode)
|
if (!mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Mode.Transcoding:
|
case LMSMediaPlayer.#Mode.Transcoding:
|
||||||
_offset = seekTime;
|
this.#offset = seekTime;
|
||||||
_removeAudioSources();
|
this.#removeAudioSources();
|
||||||
_addAudioSource(_audioTranscodingSrc + "&offset=" + _offset);
|
this.#addAudioSource(this.#audioTranscodingSrc + "&offset=" + this.#offset);
|
||||||
_elems.audio.load();
|
this.#elems.audio.load();
|
||||||
_elems.audio.currentTime = 0;
|
this.#elems.audio.currentTime = 0;
|
||||||
_playTrack();
|
this.#playTrack();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mode.File:
|
case LMSMediaPlayer.#Mode.File:
|
||||||
_elems.audio.currentTime = seekTime;
|
this.#elems.audio.currentTime = seekTime;
|
||||||
_playTrack();
|
this.#playTrack();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateMediaSessionState();
|
this.#updateMediaSessionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
let _seekBack = function() {
|
#seekBack() {
|
||||||
let currentPosition = _offset + _elems.audio.currentTime;
|
let currentPosition = this.#offset + this.#elems.audio.currentTime;
|
||||||
let newPosition = currentPosition - seekAmount;
|
let newPosition = currentPosition - LMSMediaPlayer.#seekAmount;
|
||||||
_seekTo(Math.max(newPosition, 0));
|
this.#seekTo(Math.max(newPosition, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _seekForward = function() {
|
#seekForward() {
|
||||||
let currentPosition = _offset + _elems.audio.currentTime;
|
let currentPosition = this.#offset + this.#elems.audio.currentTime;
|
||||||
let newPosition = currentPosition + seekAmount;
|
let newPosition = currentPosition + LMSMediaPlayer.#seekAmount;
|
||||||
_seekTo(Math.min(newPosition, _duration));
|
this.#seekTo(Math.min(newPosition, this.#duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _updateMediaSessionState = function() {
|
#updateMediaSessionState() {
|
||||||
if ("mediaSession" in navigator) {
|
if ("mediaSession" in navigator) {
|
||||||
navigator.mediaSession.setPositionState({
|
navigator.mediaSession.setPositionState({
|
||||||
duration: _duration,
|
duration: this.#duration,
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
position: Math.min(_offset + _elems.audio.currentTime, _duration),
|
position: Math.min(this.#offset + this.#elems.audio.currentTime, this.#duration),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_elems.audio.paused)
|
if (this.#elems.audio.paused)
|
||||||
navigator.mediaSession.playbackState = "paused";
|
navigator.mediaSession.playbackState = "paused";
|
||||||
else
|
else
|
||||||
navigator.mediaSession.playbackState = "playing";
|
navigator.mediaSession.playbackState = "playing";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let init = function(root, defaultSettings) {
|
#removeAudioSources() {
|
||||||
_root = root;
|
while (this.#elems.audio.lastElementChild) {
|
||||||
|
this.#elems.audio.removeChild(this.#elems.audio.lastElementChild);
|
||||||
_elems.audio = document.getElementById("lms-mp-audio");
|
|
||||||
_elems.playpause = document.getElementById("lms-mp-playpause");
|
|
||||||
_elems.previous = document.getElementById("lms-mp-previous");
|
|
||||||
_elems.next = document.getElementById("lms-mp-next");
|
|
||||||
_elems.progress = document.getElementById("lms-mp-progress");
|
|
||||||
_elems.seek = document.getElementById("lms-mp-seek");
|
|
||||||
_elems.curtime = document.getElementById("lms-mp-curtime");
|
|
||||||
_elems.duration = document.getElementById("lms-mp-duration");
|
|
||||||
_elems.volume = document.getElementById("lms-mp-volume");
|
|
||||||
_elems.volumeslider = document.getElementById("lms-mp-volume-slider");
|
|
||||||
_elems.transcodingActive = document.getElementById("lms-transcoding-active");
|
|
||||||
|
|
||||||
_elems.playpause.addEventListener("click", function() {
|
|
||||||
_playPause();
|
|
||||||
});
|
|
||||||
|
|
||||||
_elems.previous.addEventListener("click", function() {
|
|
||||||
_playPrevious();
|
|
||||||
});
|
|
||||||
_elems.next.addEventListener("click", function() {
|
|
||||||
_playNext();
|
|
||||||
});
|
|
||||||
_elems.seek.addEventListener("change", function() {
|
|
||||||
_seekTo(parseInt(_elems.seek.value, 10));
|
|
||||||
});
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("play", _updateControls);
|
|
||||||
_elems.audio.addEventListener("playing", _updateControls);
|
|
||||||
_elems.audio.addEventListener("pause", _updateControls);
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("play", _updateMediaSessionState);
|
|
||||||
_elems.audio.addEventListener("playing", _updateMediaSessionState);
|
|
||||||
_elems.audio.addEventListener("pause", _updateMediaSessionState);
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("pause", _pauseTimer);
|
|
||||||
_elems.audio.addEventListener("playing", _startTimer);
|
|
||||||
_elems.audio.addEventListener("waiting", _pauseTimer);
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("timeupdate", function() {
|
|
||||||
_elems.progress.style.width = "" + ((_offset + _elems.audio.currentTime) / _duration) * 100 + "%";
|
|
||||||
_elems.curtime.innerHTML = _durationToString(_offset + _elems.audio.currentTime);
|
|
||||||
});
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("ended", function() {
|
|
||||||
_resetTimer();
|
|
||||||
Wt.emit(_root, "playbackEnded");
|
|
||||||
});
|
|
||||||
|
|
||||||
_elems.audio.addEventListener("canplay", function() {
|
|
||||||
if (_getAudioMode() == Mode.Transcoding) {
|
|
||||||
_elems.transcodingActive.style.display = "inline";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_elems.transcodingActive.style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_initVolume();
|
|
||||||
_initDefaultSettings(defaultSettings);
|
|
||||||
|
|
||||||
_elems.volumeslider.addEventListener("input", function() {
|
|
||||||
_setVolume(_elems.volumeslider.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
_elems.volume.addEventListener("click", function () {
|
|
||||||
if (_elems.audio.volume != 0) {
|
|
||||||
_setVolume(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_setVolume(_elems.lastvolume);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("keydown", function(event) {
|
|
||||||
let handled = false;
|
|
||||||
|
|
||||||
if (event.target instanceof HTMLInputElement)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (event.keyCode == 32) {
|
|
||||||
_playPause();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && !event.shiftKey && event.keyCode == 37) {
|
|
||||||
_playPrevious();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && !event.shiftKey && event.keyCode == 39) {
|
|
||||||
_playNext();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && event.keyCode == 40) {
|
|
||||||
_stepVolumeDown();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && event.keyCode == 38) {
|
|
||||||
_stepVolumeUp();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && event.shiftKey && event.keyCode == 37) {
|
|
||||||
_seekBack();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
else if (event.ctrlKey && event.shiftKey && event.keyCode == 39) {
|
|
||||||
_seekForward();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handled)
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("touchstart", _unlock);
|
|
||||||
document.addEventListener("touchend", _unlock);
|
|
||||||
document.addEventListener("click", _unlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _removeAudioSources = function() {
|
|
||||||
while ( _elems.audio.lastElementChild) {
|
|
||||||
_elems.audio.removeChild( _elems.audio.lastElementChild);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _addAudioSource = function(audioSrc) {
|
#addAudioSource(audioSrc) {
|
||||||
let source = document.createElement('source');
|
let source = document.createElement('source');
|
||||||
source.src = audioSrc;
|
source.src = audioSrc;
|
||||||
_elems.audio.appendChild(source);
|
this.#elems.audio.appendChild(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _getAudioMode = function() {
|
#getAudioMode() {
|
||||||
if (_elems.audio.currentSrc) {
|
if (this.#elems.audio.currentSrc) {
|
||||||
if (_elems.audio.currentSrc.includes("format"))
|
if (this.#elems.audio.currentSrc.includes("format"))
|
||||||
return Mode.Transcoding;
|
return LMSMediaPlayer.#Mode.Transcoding;
|
||||||
else
|
else
|
||||||
return Mode.File;
|
return LMSMediaPlayer.#Mode.File;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let loadTrack = function(params, autoplay) {
|
#applyAudioTrackParameters(params) {
|
||||||
_resetTimer();
|
this.#setReplayGain(params.replayGain);
|
||||||
|
|
||||||
_trackId = params.trackId;
|
|
||||||
_offset = 0;
|
|
||||||
_duration = params.duration;
|
|
||||||
_audioNativeSrc = params.nativeResource;
|
|
||||||
_audioTranscodingSrc = params.transcodingResource + "&bitrate=" + _settings.transcoding.bitrate + "&format=" + _settings.transcoding.format;
|
|
||||||
|
|
||||||
_elems.seek.max = _duration;
|
|
||||||
|
|
||||||
_removeAudioSources();
|
|
||||||
// ! order is important
|
|
||||||
if (_settings.transcoding.mode == TranscodingMode.Never || _settings.transcoding.mode == TranscodingMode.IfFormatNotSupported)
|
|
||||||
{
|
|
||||||
_addAudioSource(_audioNativeSrc);
|
|
||||||
}
|
|
||||||
if (_settings.transcoding.mode == TranscodingMode.Always || _settings.transcoding.mode == TranscodingMode.IfFormatNotSupported)
|
|
||||||
{
|
|
||||||
_addAudioSource(_audioTranscodingSrc);
|
|
||||||
}
|
|
||||||
_elems.audio.load();
|
|
||||||
|
|
||||||
_elems.curtime.innerHTML = _durationToString(_offset);
|
|
||||||
_elems.duration.innerHTML = _durationToString(_duration);
|
|
||||||
|
|
||||||
if (!_audioIsInit) {
|
|
||||||
_pendingTrackParameters = params;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_applyAudioTrackParameters(params);
|
|
||||||
|
|
||||||
if (autoplay && _audioCtx.state == "running")
|
|
||||||
_playTrack();
|
|
||||||
}
|
|
||||||
|
|
||||||
let _applyAudioTrackParameters = function(params)
|
|
||||||
{
|
|
||||||
_setReplayGain(params.replayGain);
|
|
||||||
if ("mediaSession" in navigator) {
|
if ("mediaSession" in navigator) {
|
||||||
navigator.mediaSession.metadata = new MediaMetadata({
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
title: params.title,
|
title: params.title,
|
||||||
@@ -468,24 +440,52 @@ LMS.mediaplayer = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let stop = function() {
|
loadTrack(params, autoplay) {
|
||||||
_elems.audio.pause();
|
this.#resetTimer();
|
||||||
|
|
||||||
|
this.#trackId = params.trackId;
|
||||||
|
this.#offset = 0;
|
||||||
|
this.#duration = params.duration;
|
||||||
|
this.#audioNativeSrc = params.nativeResource;
|
||||||
|
this.#audioTranscodingSrc = params.transcodingResource + "&bitrate=" + this.#settings.transcoding.bitrate + "&format=" + this.#settings.transcoding.format;
|
||||||
|
|
||||||
|
this.#elems.seek.max = this.#duration;
|
||||||
|
|
||||||
|
this.#removeAudioSources();
|
||||||
|
// ! order is important
|
||||||
|
if (this.#settings.transcoding.mode == LMSTranscodingMode.Never || this.#settings.transcoding.mode == LMSTranscodingMode.IfFormatNotSupported) {
|
||||||
|
this.#addAudioSource(this.#audioNativeSrc);
|
||||||
|
}
|
||||||
|
if (this.#settings.transcoding.mode == LMSTranscodingMode.Always || this.#settings.transcoding.mode == LMSTranscodingMode.IfFormatNotSupported) {
|
||||||
|
this.#addAudioSource(this.#audioTranscodingSrc);
|
||||||
|
}
|
||||||
|
this.#elems.audio.load();
|
||||||
|
|
||||||
|
this.#elems.curtime.innerHTML = this.#durationToString(this.#offset);
|
||||||
|
this.#elems.duration.innerHTML = this.#durationToString(this.#duration);
|
||||||
|
|
||||||
|
if (!this.#audioIsInit) {
|
||||||
|
this.#pendingTrackParameters = params;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let setSettings = function(settings) {
|
this.#applyAudioTrackParameters(params);
|
||||||
_settings = settings;
|
|
||||||
|
|
||||||
if (typeof(Storage) !== "undefined") {
|
if (autoplay && this.#audioCtx.state == "running")
|
||||||
localStorage.settings = JSON.stringify(_settings);
|
this.#playTrack();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
stop() {
|
||||||
init: init,
|
this.#elems.audio.pause();
|
||||||
loadTrack: loadTrack,
|
}
|
||||||
stop: stop,
|
|
||||||
setSettings: setSettings,
|
setSettings(settings) {
|
||||||
};
|
this.#settings = settings;
|
||||||
}();
|
|
||||||
|
if (typeof (Storage) !== "undefined") {
|
||||||
|
localStorage.settings = JSON.stringify(this.#settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ namespace lms::ui
|
|||||||
Settings defaultSettings;
|
Settings defaultSettings;
|
||||||
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "LMS.mediaplayer.init("
|
oss << jsRef() + ".mediaplayer = new LMSMediaPlayer("
|
||||||
<< jsRef()
|
<< jsRef()
|
||||||
<< ", defaultSettings = " << settingsToJSString(defaultSettings)
|
<< ", defaultSettings = " << settingsToJSString(defaultSettings)
|
||||||
<< ")";
|
<< ")";
|
||||||
@@ -260,7 +260,7 @@ namespace lms::ui
|
|||||||
// Update 'sizes' above to match this:
|
// Update 'sizes' above to match this:
|
||||||
static_assert(static_cast<std::underlying_type_t<ArtworkResource::Size>>(ArtworkResource::Size::Small) == 128);
|
static_assert(static_cast<std::underlying_type_t<ArtworkResource::Size>>(ArtworkResource::Size::Small) == 128);
|
||||||
static_assert(static_cast<std::underlying_type_t<ArtworkResource::Size>>(ArtworkResource::Size::Large) == 512);
|
static_assert(static_cast<std::underlying_type_t<ArtworkResource::Size>>(ArtworkResource::Size::Large) == 512);
|
||||||
oss << "LMS.mediaplayer.loadTrack(params, " << (play ? "true" : "false") << ")"; // true to autoplay
|
oss << jsRef() + ".mediaplayer.loadTrack(params, " << (play ? "true" : "false") << ")"; // true to autoplay
|
||||||
|
|
||||||
_title->setTextFormat(Wt::TextFormat::Plain);
|
_title->setTextFormat(Wt::TextFormat::Plain);
|
||||||
_title->setText(Wt::WString::fromUTF8(track->getName()));
|
_title->setText(Wt::WString::fromUTF8(track->getName()));
|
||||||
@@ -308,7 +308,7 @@ namespace lms::ui
|
|||||||
|
|
||||||
void MediaPlayer::stop()
|
void MediaPlayer::stop()
|
||||||
{
|
{
|
||||||
doJavaScript("LMS.mediaplayer.stop()");
|
doJavaScript(jsRef() + ".mediaplayer.stop()");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlayer::setSettings(const Settings& settings)
|
void MediaPlayer::setSettings(const Settings& settings)
|
||||||
@@ -317,7 +317,7 @@ namespace lms::ui
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "LMS.mediaplayer.setSettings(settings = " << settingsToJSString(settings) << ")";
|
oss << jsRef() + ".mediaplayer.setSettings(settings = " << settingsToJSString(settings) << ")";
|
||||||
|
|
||||||
LMS_LOG(UI, DEBUG, "Running js = '" << oss.str() << "'");
|
LMS_LOG(UI, DEBUG, "Running js = '" << oss.str() << "'");
|
||||||
doJavaScript(oss.str());
|
doJavaScript(oss.str());
|
||||||
|
|||||||
Reference in New Issue
Block a user