The custom /radio/stream-player/ page is served over HTTPS, so the browser
still applies mixed-content restrictions and upgrades http:// audio to https://,
which fails for streams without TLS support.
Fix: window.open(url, '_blank') navigates the tab directly to the HTTP URL.
The tab itself is then HTTP, bypassing mixed-content restrictions entirely.
Browser plays the stream natively with its built-in audio player.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
window.open() doesn't transfer the user gesture to the new tab, so autoplay
is blocked. Previously play().catch(()=>{}) swallowed the error silently while
setting playing=true, leaving the UI in a broken state.
Now: if play() rejects, reset state and show "Click Play to start". The user's
click on the Play button IS a user gesture, so it succeeds on the second attempt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of trying a HTTPS upgrade (which fails for IP-based streams):
- playStation() detects http:// URL on https:// page, opens /radio/stream-player/
with url, name, vol as query params, then returns — main stream is already
stopped by the stopPlayback(false) call at the top of playStation()
- New view stream_player renders a standalone minimal player page
- Template: auto-plays on load, correct volume from URL param, volume changes
synced back to localStorage so main window picks it up next time,
live track metadata via SSE, tab title updates on track change,
close-tab button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>