Player: a song stuck on Buffering is reloaded after 10s, switched to the converted stream after 20s, and skipped after 30s; a play() that fails for any reason now recovers
build-container / build (push) Successful in 3m2s
build-container / build (push) Successful in 3m2s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e26bea455
commit
d173555398
1 file changed
+16
-2
+16
-2
@@ -58,11 +58,25 @@ addEventListener('online', () => { pl.retries = 0; tcKick(); recover(true); });
|
||||
addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && cur() && !pl.a.paused && (pl.a.readyState < 3 || pl.a.error)) { pl.retries = 0; recover(true); } }); // (back from sleep or another app)
|
||||
|
||||
let loadTok = 0, loadTimer = null, stallTimer = null;
|
||||
// Watchdog: a song that sits on "Buffering…" without moving is not left there. After 10 s it is reloaded, after 20 s it is switched to the copy Plex converts to MP3,
|
||||
// and after 30 s it is skipped. (This does not rely on the browser sending a "stalled" or "error" event, which a hung request may never do.)
|
||||
const wd = { tries: 0, at: 0, pos: -1, key: '' };
|
||||
if (typeof setInterval === 'function') setInterval(() => {
|
||||
const t = cur(), a = pl.a;
|
||||
if (!t || !pl.buf || /^radio:/.test(String(t.key)) || !navigator.onLine) { wd.at = Date.now(); wd.pos = -1; return; }
|
||||
if (wd.key !== t.key) { wd.key = t.key; wd.tries = 0; wd.at = Date.now(); }
|
||||
if (a.currentTime !== wd.pos) { wd.pos = a.currentTime; wd.at = Date.now(); return; }
|
||||
if (Date.now() - wd.at < 10000 || loadTimer && a.paused && Date.now() - wd.at < 12000) return;
|
||||
wd.at = Date.now(); wd.tries++;
|
||||
if (wd.tries === 1) { pl.forceRecover = true; pl.recovering = true; recover(true); }
|
||||
else if (wd.tries === 2) { pl.alt.add(t.key); loadCur(0); }
|
||||
else { wd.tries = 0; toast('"' + t.title + '" would not load. Skipping.'); advance(true); }
|
||||
}, 2000);
|
||||
pl.retries = 0; pl.buf = false;
|
||||
// Show the new track at once, but wait a moment before fetching it so quickly tapping Next several times only loads the last one.
|
||||
function loadCur(delay = 220) {
|
||||
const t = cur(); if (!t) return;
|
||||
clearTimeout(loadTimer); clearTimeout(stallTimer); pl.retries = 0; pl.scrobbled = false; pl.recovering = false;
|
||||
clearTimeout(loadTimer); clearTimeout(stallTimer); pl.retries = 0; pl.scrobbled = false; pl.recovering = false; wd.tries = 0; wd.at = Date.now();
|
||||
const tok = ++loadTok; pl.buf = true;
|
||||
if (delay) pl.a.pause();
|
||||
try { // (a bug in any screen's refresh must never stop the music from starting)
|
||||
@@ -76,7 +90,7 @@ function loadCur(delay = 220) {
|
||||
const hit = tc.m.get(t.src);
|
||||
pl.a.src = hit && !pl.alt.has(t.key) ? hit.url : srcOf(t);
|
||||
if (typeof actLog === 'function') actLog(/podcast|audiobook|\/ab\/|radio/.test(String(t.src || '')) ? 'listen' : 'play', (t.artist ? t.artist + ' - ' : '') + (t.title || ''));
|
||||
pl.a.play().catch(e => { if (e && e.name === 'NotAllowedError') { pl.buf = false; syncUI(); toast('Tap play to start'); } });
|
||||
pl.a.play().catch(e => { if (tok !== loadTok) return; if (e && e.name === 'NotAllowedError') { pl.buf = false; syncUI(); toast('Tap play to start'); } else if (!(e && e.name === 'AbortError')) { pl.forceRecover = true; pl.recovering = true; recover(true); } });
|
||||
tcKick();
|
||||
const n = pl.q[pl.i + 1]; if (n) new Image().src = px.art(n.thumb, 600);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user