From a66379dc639f52cbde383c296a04ff10688cefba Mon Sep 17 00:00:00 2001 From: lelo Date: Thu, 29 May 2025 18:51:30 +0000 Subject: [PATCH] cleanup audio player --- static/app.js | 36 ------------- static/audioplayer.js | 122 +++++++++++++++++++++++++++++++++--------- 2 files changed, 97 insertions(+), 61 deletions(-) diff --git a/static/app.js b/static/app.js index 865ef21..c6a9fef 100644 --- a/static/app.js +++ b/static/app.js @@ -456,42 +456,6 @@ function reloadDirectory() { } - -if ('mediaSession' in navigator) { - - // Handler for the play action - navigator.mediaSession.setActionHandler('play', () => { - document.getElementById('globalAudio').play(); - }); - - // Handler for the pause action - navigator.mediaSession.setActionHandler('pause', () => { - document.getElementById('globalAudio').pause(); - }); - - // Handler for the previous track action - navigator.mediaSession.setActionHandler('previoustrack', () => { - if (currentMusicIndex > 0) { - const prevFile = currentMusicFiles[currentMusicIndex - 1]; - const prevLink = document.querySelector(`.play-file[data-url="${prevFile.path}"]`); - if (prevLink) { - prevLink.click(); - } - } - }); - - // Handler for the next track action - navigator.mediaSession.setActionHandler('nexttrack', () => { - if (currentMusicIndex >= 0 && currentMusicIndex < currentMusicFiles.length - 1) { - const nextFile = currentMusicFiles[currentMusicIndex + 1]; - const nextLink = document.querySelector(`.play-file[data-url="${nextFile.path}"]`); - if (nextLink) { - nextLink.click(); - } - } - }); -} - document.getElementById('globalAudio').addEventListener('ended', () => { reloadDirectory().then(() => { diff --git a/static/audioplayer.js b/static/audioplayer.js index 1834b18..6171f9c 100644 --- a/static/audioplayer.js +++ b/static/audioplayer.js @@ -3,11 +3,10 @@ const cssVar = getComputedStyle(document.documentElement).getPropertyValue('--da // player DOM elements const nowPlayingInfo = document.getElementById('nowPlayingInfo'); -const audioPlayer = document.getElementById('globalAudio'); +const audio = document.getElementById('globalAudio'); const audioPlayerContainer = document.getElementById('audioPlayerContainer'); const playerButton = document.querySelector('.player-button'), - audio = document.querySelector('audio'), timeline = document.querySelector('.timeline'), timeInfo = document.getElementById('timeInfo'), playIcon = ` @@ -61,6 +60,18 @@ audio.addEventListener('loadedmetadata', () => { +audio.addEventListener('play', () => { + if ('mediaSession' in navigator) + navigator.mediaSession.playbackState = 'playing'; +}); +audio.addEventListener('pause', () => { + if ('mediaSession' in navigator) + navigator.mediaSession.playbackState = 'paused'; +}); + + + + // --- Seek function: directly set audio.currentTime using slider's value (in seconds) --- function changeSeek() { audio.currentTime = timeline.value; @@ -75,28 +86,30 @@ function formatTime(seconds) { // --- Update timeline, time info, and media session on each time update --- -audio.ontimeupdate = function() { - - // --- Update the slider thumb position (in seconds) while playing --- +let lastPosCall = 0; +audio.ontimeupdate = () => { + // — your slider + time display update — if (!isSeeking) { timeline.value = audio.currentTime; - const percentagePosition = (audio.currentTime / audio.duration) * 100; - timeline.style.backgroundSize = `${percentagePosition}% 100%`; + timeline.style.backgroundSize = `${(audio.currentTime / audio.duration) * 100}% 100%`; } + timeInfo.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`; - // --- Update the time display --- - const currentTimeFormatted = formatTime(audio.currentTime); - const durationFormatted = isNaN(audio.duration) ? "00:00" : formatTime(audio.duration); - timeInfo.innerHTML = `${currentTimeFormatted} / ${durationFormatted}`; - - if ('mediaSession' in navigator && + // — throttled Media Session update — + if ( + 'mediaSession' in navigator && 'setPositionState' in navigator.mediaSession && - !isNaN(audio.duration)) { - navigator.mediaSession.setPositionState({ - duration: audio.duration, - playbackRate: audio.playbackRate, - position: audio.currentTime - }); + !isNaN(audio.duration) + ) { + const now = performance.now(); + if (now - lastPosCall > 1000) { + lastPosCall = now; + navigator.mediaSession.setPositionState({ + duration: audio.duration, + playbackRate: audio.playbackRate, + position: audio.currentTime + }); + } } }; @@ -107,7 +120,6 @@ audio.onended = function() { }; async function downloadAudio() { - const audio = document.getElementById('globalAudio'); const src = audio.currentSrc || audio.src; if (!src) return; @@ -132,8 +144,8 @@ let currentFetchController = null; async function startPlaying(relUrl) { // Pause the audio and clear its source. - audioPlayer.pause(); - audioPlayer.src = ''; + audio.pause(); + audio.src = ''; // Display the audio player container. audioPlayerContainer.style.display = "block"; @@ -171,9 +183,9 @@ async function startPlaying(relUrl) { } // Set the media URL, load, and play the audio. - audioPlayer.src = mediaUrl; - audioPlayer.load(); - await audioPlayer.play(); + audio.src = mediaUrl; + audio.load(); + await audio.play(); clearTimeout(spinnerTimer); hideSpinner(); currentTrackPath = relUrl; @@ -194,6 +206,12 @@ async function startPlaying(relUrl) { { src: '/icons/logo-192x192.png', sizes: '192x192', type: 'image/png' } ] }); + navigator.mediaSession.playbackState = 'playing'; + navigator.mediaSession.setPositionState({ + duration: audio.duration, + playbackRate: audio.playbackRate, + position: 0 + }); } nowPlayingInfo.innerHTML = pathStr.replace(/\//g, ' > ') + @@ -207,4 +225,58 @@ async function startPlaying(relUrl) { nowPlayingInfo.textContent = "Fehler: Netzwerkproblem oder ungültige URL."; } }; +} + + +if ('mediaSession' in navigator) { + + // Handler for the play action + navigator.mediaSession.setActionHandler('play', () => { + navigator.mediaSession.playbackState = 'playing' + document.getElementById('globalAudio').play(); + }); + + // Handler for the pause action + navigator.mediaSession.setActionHandler('pause', () => { + navigator.mediaSession.playbackState = 'paused' + document.getElementById('globalAudio').pause(); + }); + + // Handler for the previous track action + navigator.mediaSession.setActionHandler('previoustrack', () => { + if (currentMusicIndex > 0) { + const prevFile = currentMusicFiles[currentMusicIndex - 1]; + const prevLink = document.querySelector(`.play-file[data-url="${prevFile.path}"]`); + if (prevLink) { + prevLink.click(); + } + } + }); + + // Handler for the next track action + navigator.mediaSession.setActionHandler('nexttrack', () => { + if (currentMusicIndex >= 0 && currentMusicIndex < currentMusicFiles.length - 1) { + const nextFile = currentMusicFiles[currentMusicIndex + 1]; + const nextLink = document.querySelector(`.play-file[data-url="${nextFile.path}"]`); + if (nextLink) { + nextLink.click(); + } + } + }); + + // Handler for the seek backward action + navigator.mediaSession.setActionHandler('seekto', ({seekTime, fastSeek}) => { + if (fastSeek && 'fastSeek' in audio) { + audio.fastSeek(seekTime); + } else { + audio.currentTime = seekTime; + } + // immediately update the remote clock + navigator.mediaSession.setPositionState({ + duration: audio.duration, + playbackRate: audio.playbackRate, + position: audio.currentTime + }); + }); + } \ No newline at end of file