From 3fe635fcd60554027140d42f7dc495297e49a9e5 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Thu, 4 Jun 2026 14:36:06 -0700 Subject: [PATCH] no-sound fix: resume context on the 'play' event (covers all play paths) Harden the previous fix: setPlayingState(true) misses resume/play calls that bypass it (lines that just do 'if paused, play()'). Move the resume onto the audio element's 'play' event, which fires on every playback start regardless of code path. Keep the resume in npInitVisualizer for the first-play case (context is created suspended after the 'play' event already fired). Drop the now-redundant setPlayingState hook. --- webui/static/media-player.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/webui/static/media-player.js b/webui/static/media-player.js index 2f3a7d32..2408ed3f 100644 --- a/webui/static/media-player.js +++ b/webui/static/media-player.js @@ -23,6 +23,11 @@ function initializeMediaPlayer() { audioPlayer.addEventListener('error', onAudioError); audioPlayer.addEventListener('loadstart', onAudioLoadStart); audioPlayer.addEventListener('canplay', onAudioCanPlay); + // Universal: once the visualizer routes this element through + // npAudioContext, the element is silent while that context is + // suspended. The 'play' event fires on EVERY playback start (every + // code path, incl. ones that bypass setPlayingState), so resume here. + audioPlayer.addEventListener('play', npEnsureAudioContextRunning); // Set initial volume — restore the saved level (Spotify-style), else 70%. const _savedVol = npLoadSavedVolume(); @@ -304,10 +309,6 @@ function setPlayingState(playing) { // Sidebar audio visualizer if (playing) { npInitVisualizer(); - // npInitVisualizer only runs its setup once; the element stays routed - // through npAudioContext, so resume it on EVERY play start or playback - // is silent when the context has been suspended (autoplay / tab blur). - npEnsureAudioContextRunning(); startSidebarVisualizer(); } else { stopSidebarVisualizer();