Skip to content

Add internet radio as a source: paste a stream's address - #6

Merged
StopBanning merged 1 commit into
StopBanning:mainfrom
ljyjeffrey:radio
Oct 27, 2026
Merged

StopBanning merged 1 commit into
StopBanning:mainfrom
ljyjeffrey:radio

Conversation

@ljyjeffrey

Copy link
Copy Markdown
Contributor

Summary

  • The source menu (S) gets a fifth row: ∿ radio and a field for a stream's address (MP3 or AAC from an Icecast or Shoutcast server, over http or https). Enter or the button plays it; the last address that played is remembered with the other settings.
  • Toaster comes with no stations. A stream is its station's to offer, and many don't let apps come with theirs (SomaFM's terms, for one, refuse third-party apps outright), so the user brings the address. Nothing is bundled, fetched or listed by the app.
  • It plays through an audio element as a file does (playElement, now shared with useFile), read cross-origin so the analysis hears it. The app's page is a file, which may read any stream that way (checked on Electron 44.7.0 against a server sending no CORS header); on the web page a stream only plays if its server allows it, and an https page can't play an http stream, which the error says. The CSP's media-src gains http: https:.
  • A stream that ends or drops says so and brings back the source menu, as system audio does when it stops. Stream titles (ICY metadata) aren't read, so the radio is untitled, like an input.
  • README (keys, settings, privacy, good to know) and a short "The radio" section in docs/how-it-works.md.

One thing I couldn't check: toaster.locust.lol's page seems to carry its own CSP from a build step that isn't in this repo; if so, it needs the same media-src for the radio to play there.

Test plan

  • In a browser (node tools/serve.mjs, headless Chromium, muted): Radio Paradise and Radio Swiss Jazz play, the analysis hears them (level, label in the footer), the address comes back after a reload.
  • A stream whose server doesn't allow other sites (WFMU) fails with the browser explanation; a non-address and ftp:// get the plain message; the message box stays up after Enter.
  • Typing in the field fires no shortcuts; after it plays, V and the rest work again; demo beat and files still play (file loop unchanged).
  • Electron 44.7.0, file:// page: an audio element with crossOrigin reads a remote stream with no CORS header (analyser sees the signal).
  • npm start on Windows and on a Mac: S › radio, paste a stream, it plays and the code follows.
  • On an iPad: the field, the keyboard's Go, and the menu at phone width.

🤖 Generated with Claude Code

The source menu (S) gets a fifth row, a radio button and a field for a stream's address: the
stream itself, MP3 or AAC from an Icecast or Shoutcast server, over http or https. Toaster comes
with no stations: a stream is its station's to offer, and many don't let apps come with theirs.
The last address that played is remembered with the other settings.

It plays through an audio element as a file does (playElement, now shared with useFile), read
cross-origin so the analysis hears it. The app's page is a file, which may read any stream that
way; on the web page a stream only plays if its server allows it, and an https page can't play an
http stream, which the error says. The CSP's media-src allows http and https for it. A stream
that ends or drops says so and brings back the source menu, as system audio does when it stops.
Stream titles (ICY metadata) aren't read, so the radio is untitled, like an input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@StopBanning
StopBanning merged commit 262f901 into StopBanning:main Oct 27, 2026
StopBanning added a commit to ljyjeffrey/toaster that referenced this pull request Oct 27, 2026
# Conflicts:
#	README.md
#	docs/how-it-works.md
@StopBanning

Copy link
Copy Markdown
Owner

this is sick, thank you!! 🙏 both are merged and will ship in 0.4.22, and you're in the notes. tested here: radio paradise locks in at 109 in about 25 seconds, and WFMU plays in the app even with its server blocking other sites.

re your question: the site picks up the media-src change on its own (its build copies the page's CSP and only adds the GitHub API).

(#7 hit a one-line README conflict after #6's squash, so I merged main into your branch to clear it.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants