Commit graph

20 commits

Author SHA1 Message Date
d30f687185 stream: switch queue and history with glossy tabs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 11:18:00 +08:00
62302ac21d stream: show the queue of upcoming tracks (/queue)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 11:18:00 +08:00
126cb8f8ac stream: show "Connexion en cours" until prefetch is known
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 11:18:00 +08:00
bfa7cc1046 stream: show the source provider of the current track
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 11:18:00 +08:00
96a1ba89e6 stream: add a whole-station restart of the current track
All checks were successful
continuous-integration/drone/push Build is passing
Wire the Media Session previous-track control to a new POST /restart-track
route that requeues the current song from the start for every listener, and
keep next-track as skip. Exposing both handlers also makes Android (Chrome)
show the skip button, which it hides when only nexttrack is set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 10:50:53 +08:00
622210197f stream: expose OS media controls via the Media Session API
All checks were successful
continuous-integration/drone/push Build is passing
Wire the web player into system media controls (MPRIS, Control Center,
lock screen) and keyboard media keys: push track metadata and handle
play/pause/next, with seek neutralized on the live stream.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:17:20 +08:00
85cd5d1b74 stream: show a random Navidrome-style background image
All checks were successful
continuous-integration/drone/push Build is passing
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:42:51 +08:00
534ade0ba5 stream: add a synthwave favicon
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:42:51 +08:00
1648030eba stream: surface ingest prefetch progress in the player
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:22:53 +08:00
c12e522fee stream: link the now-playing title to its source page
For yt-dlp tracks the locator is the original web page, so pass it as a
url annotation, carry it through the stream metadata and history, and
turn the track title into a link back to that page (both live and in the
history). Subsonic ids are opaque and stay plain text.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:14:50 +08:00
fa1be6df77 stream: make the station name a single configurable variable
Default it to "Nemu FM" and derive the tab title, logo, and dynamic
document title from one STATION_NAME constant for easy renaming.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:12:48 +08:00
6b52795ae1 stream: auto-reconnect to the live stream with exponential backoff
If the stream drops (server restart, network loss), the player now retries
goLive() on error/ended/stalled with a delay that doubles each failure, capped
at 30s, and resets once audio flows again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:09:39 +08:00
155a13d50e stream: remember the listener's volume via localStorage
Defaults to 40% on first visit, then restores whatever the user last set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:00:55 +08:00
aad3c9d0f7 stream: let listeners download any track still in the cache
All checks were successful
continuous-integration/drone/push Build is passing
/download now accepts ?file=<name> to fetch any cached file, not just the
current track. History entries carry that filename token (via /history), so
the web UI renders each aired track as a download link. A shared
serve_attachment helper validates the request (basename-only, real audio file,
no hidden/.part files) before streaming it; LRU-evicted tracks return 404.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
1f6937f22c stream: let the listener download the current track (/download)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
7fc372f18d stream: show a history of aired tracks (/history)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
a468d78153 stream: add a skip-to-next button and /skip route
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
04ea54c03e stream: show a copyable stream URL for external players
Add a read-only field with the bare /radio.mp3 URL and a copy button
(clipboard API, with a select+execCommand fallback), so the stream can
easily be opened in VLC or another external player.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
c6d642a945 stream: reconnect the player to live instead of stale buffer
Firefox kept resuming the <audio> element from a stale buffer after a
pause, drifting behind the live point. Load the stream with an anti-cache
query parameter, and on resume-from-pause reconnect to live rather than
replaying the buffered audio.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:15:25 +08:00
f4eaf8e7d1 stream: web player with now-playing
Serve a small web page at http://<host>:8000/ (stream/index.html) from the
Liquidsoap harbor, alongside the /radio.mp3 stream. It shows the track
currently on air and refreshes it from a /nowplaying JSON endpoint, fed by the
broadcast source's live metadata — accurate even though the ingest daemon runs
a track ahead (prefetch).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:46:37 +08:00