Revert "feat(web): gapless audio handoff to fix desktop media-tile flicker"
This reverts commit 98d7c84269.
This commit is contained in:
1 parent
98d7c84269
commit
420c84d191
4 files changed
+48
-92
No files matched your search
+12
-46
@@ -276,19 +276,10 @@ function _setAudioSession() {
|
||||
try { if(navigator.audioSession) navigator.audioSession.type = 'playback'; } catch {}
|
||||
}
|
||||
|
||||
// ─── PRELOAD — the standby audio element buffers the next track ──────────────
|
||||
// Buffering into the *standby* element (not a throwaway) lets playCurrent() hand
|
||||
// playback over to it gaplessly: the active element never empties, so the OS media
|
||||
// tile doesn't flicker on skip. Falls back to a source-swap when not preloaded.
|
||||
// ─── PRELOAD — shadow Audio element actually buffers the next track ──────────
|
||||
let _preUrl = '';
|
||||
let _preId = '';
|
||||
|
||||
/** The audio element that is NOT currently active (or null if there's only one). */
|
||||
function _standbyEl() {
|
||||
const els = S._audioEls;
|
||||
if (!els || els.length < 2) return null;
|
||||
return els.find(e => e !== S.audio) || null;
|
||||
}
|
||||
let _preAudio = null;
|
||||
|
||||
function _nextIdx() {
|
||||
if(S.repeat === 'one') return S.qIdx;
|
||||
@@ -303,12 +294,13 @@ function _preloadNext() {
|
||||
if(ni < 0) return;
|
||||
const next = S.queue[ni];
|
||||
if(!next || _preId === next.id) return;
|
||||
const standby = _standbyEl();
|
||||
if(!standby) return;
|
||||
_preId = next.id;
|
||||
_preUrl = streamUrl(next.id);
|
||||
standby.src = _preUrl; // preload="auto" → the element buffers it for a gapless handoff
|
||||
try { standby.load(); } catch {}
|
||||
// Real Audio preload — actually buffers the stream so canplay fires instantly
|
||||
if(_preAudio) { _preAudio.src = ''; _preAudio = null; }
|
||||
_preAudio = new Audio();
|
||||
_preAudio.preload = 'auto';
|
||||
_preAudio.src = _preUrl;
|
||||
if(next.coverArt) {
|
||||
[256, 512, 1024].forEach(size => {
|
||||
const img = new Image();
|
||||
@@ -319,8 +311,7 @@ function _preloadNext() {
|
||||
|
||||
function _clearPreload() {
|
||||
_preId = ''; _preUrl = '';
|
||||
const standby = _standbyEl();
|
||||
if(standby) { try { standby.pause(); standby.removeAttribute('src'); standby.load(); } catch {} }
|
||||
if(_preAudio) { _preAudio.src = ''; _preAudio = null; }
|
||||
}
|
||||
|
||||
// ─── PLAY HISTORY (for prev-in-shuffle) ──────────────────────────────────────
|
||||
@@ -406,6 +397,10 @@ export function playCurrent() {
|
||||
renderQueue();
|
||||
_scheduleScrobble(s.id, s.duration);
|
||||
|
||||
const src = (_preId === s.id && _preUrl) ? _preUrl : streamUrl(s.id);
|
||||
_clearPreload();
|
||||
S.audio.src = src;
|
||||
|
||||
const _resetFlag = () => { if (_playGen === gen) S._trackChanging = false; };
|
||||
|
||||
const _applySession = () => {
|
||||
@@ -414,35 +409,6 @@ export function playCurrent() {
|
||||
setTimeout(_preloadNext, 2000);
|
||||
};
|
||||
|
||||
// ── Gapless handoff: if the standby element already buffered THIS track, switch
|
||||
// playback to it instead of reloading the source. The active element never empties,
|
||||
// so the OS media tile stays put (and the skip is instant). ──
|
||||
const standby = _standbyEl();
|
||||
if (standby && _preId === s.id && standby.readyState >= 2) {
|
||||
const old = S.audio;
|
||||
standby.currentTime = 0;
|
||||
standby.volume = old.volume; standby.muted = old.muted; standby.playbackRate = old.playbackRate || 1;
|
||||
S.audio = standby; // the active element is now the preloaded one
|
||||
_preId = ''; _preUrl = '';
|
||||
try { old.pause(); } catch {} // 'pause' is ignored for the now-inactive element
|
||||
_setAudioSession();
|
||||
S.audio.play()
|
||||
.then(() => { S._trackChanging = false; _applySession(); })
|
||||
.catch(() => {
|
||||
// Handoff playback failed — recover with a fresh source load on this element.
|
||||
if (_playGen !== gen) return;
|
||||
S.audio.src = streamUrl(s.id);
|
||||
try { S.audio.load(); } catch {}
|
||||
S.audio.play().then(() => { S._trackChanging = false; _applySession(); }).catch(_resetFlag);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Fallback: classic source swap on the current element (unchanged) ──
|
||||
const src = (_preId === s.id && _preUrl) ? _preUrl : streamUrl(s.id);
|
||||
_clearPreload();
|
||||
S.audio.src = src;
|
||||
|
||||
let _guardTimer = null;
|
||||
let _canplayFn = null;
|
||||
|
||||
|
||||
Reference in new issue
Block a user