URI:
       Directory listing for: icecast
   DIR Parent directory (..)
       
  TEXT README.txt (5.3KB, 2026-05-12):
       
        Icecast relay -- any HTTP/Icecast stream via gopher
       =============================================================
       
       This applet relays HTTP/Icecast audio streams over a long-lived
       gopher TCP connection. Every station -- the default one or any
       URL you paste in -- has a per-station menu page with metadata
       (name, genre, bitrate, current StreamTitle when available), a
       Listen link (audio passthrough), a Watch link (144p MPEG-TS
       showcqt visualization, ~38 kbps total), and a copy-pasteable
       curl command after each. A "Radio menu URI:" info-line at the
       foot of every per-station menu is the page's stable permalink.
       
       NOTE: the bare URL /applets/icecast/icecast.lhs returns a
       gophermap landing menu, not audio. To play the default station,
       pipe the bytes at /applets/icecast/icecast.lhs/default instead:
       
           curl gopher://gopher.someodd.zip/9/applets/icecast/icecast.lhs/default | mpv -
       
       ------------------------------------------------------------
        Endpoints
       ------------------------------------------------------------
       
         /applets/icecast/icecast.lhs
               landing menu (gophermap)
       
         /applets/icecast/icecast.lhs/menu
               "paste a URL" prompt; type-7 query lands on the per-
               station menu for the submitted URL.
       
         /applets/icecast/icecast.lhs<TAB><URL>
               type-7 query against the landing: same as /menu + URL,
               produces the per-station menu.
       
         /applets/icecast/icecast.lhs/default
               default station, audio passthrough.
       
         /applets/icecast/icecast.lhs/default/audio
               default station, audio passthrough (alias of /default).
       
         /applets/icecast/icecast.lhs/default/with_visualization
               default station, 144p MPEG-TS showcqt visualization.
       
         /applets/icecast/icecast.lhs/default/menu
               per-station menu for the default station --- metadata,
               Listen + Watch links with curl recipes, permalink.
       
         /applets/icecast/icecast.lhs/url/<b64>
         /applets/icecast/icecast.lhs/url/<b64>/audio
         /applets/icecast/icecast.lhs/url/<b64>/with_visualization
         /applets/icecast/icecast.lhs/url/<b64>/menu
               arbitrary-URL station: <b64> is a base64url-encoded
               upstream URL with padding stripped. Hit any of these
               directly to bookmark a station; the encoded URLs are
               produced automatically when you submit a URL via the
               type-7 box, and printed inside the per-station menu's
               "Radio menu URI:" line.
       
       ------------------------------------------------------------
        From the command line
       ------------------------------------------------------------
       
       Default station (audio):
       
           curl gopher://gopher.someodd.zip/9/applets/icecast/icecast.lhs/default | mpv -
       
       Default station (visualization):
       
           curl gopher://gopher.someodd.zip/9/applets/icecast/icecast.lhs/default/with_visualization | mpv -
       
       Default station's menu page (gophermap with live metadata,
       curl recipes, permalink):
       
           curl gopher://gopher.someodd.zip/1/applets/icecast/icecast.lhs/default/menu
       
       Open a per-station menu for an arbitrary URL (selector + TAB + URL):
       
           printf '/applets/icecast/icecast.lhs/menu\thttp://ice1.somafm.com/groovesalad-128-mp3\r\n' \
             | nc gopher.someodd.zip 70
       
       The returned menu's Listen / Watch rows include base64url-encoded
       selectors you can curl directly:
       
           curl gopher://gopher.someodd.zip/9/applets/icecast/icecast.lhs/url/aHR0cDovL2ljZTEuc29tYWZtLmNvbS9ncm9vdmVzYWxhZC0xMjgtbXAz/audio | mpv -
       
       (equivalent to the Listen row in that menu; bookmark the
       "Radio menu URI" to come back to the menu later.)
       
       ------------------------------------------------------------
        How this works
       ------------------------------------------------------------
       
       Audio passthrough opens a TLS/HTTP connection to the upstream
       and copies the response body straight to stdout. Constant
       memory; nothing buffered through Haskell.
       
       Visualization spawns ffmpeg with the upstream URL as the input
       argument and showcqt as the filter; ffmpeg's stdout inherits
       the gopher socket directly.
       
       Menu pages do a brief one-shot fetch with `Icy-MetaData: 1` and
       a 4-second timeout to populate the metadata block. If the
       upstream is slow or offline the menu still renders --- just
       without the optional fields.
       
       Permalinks: per-station menus carry a "Radio menu URI:" line at
       the foot. For the default station it points at
       /applets/icecast/icecast.lhs/default/menu. For URL stations it
       points at /applets/icecast/icecast.lhs/url/<b64>/menu, where
       <b64> is base64url(upstream) with padding stripped --- so the
       same URL always produces the same selector.
       
       When you disconnect mid-stream (Ctrl-C the nc), stdout becomes
       a broken pipe; the exception unwinds the script (or SIGPIPE
       kills ffmpeg); the upstream connection closes; the daemon reaps
       the process. No leaks.
       
       ------------------------------------------------------------
        Limits
       ------------------------------------------------------------
       
       The server caps concurrent connections at 256, so this is not
       a CDN. Disconnect when you're done.
       
       Invalid URLs in the type-7 boxes (anything that isn't http://
       or https://) come back as a type-3 error row plus a "back to
       landing" link. URLs are length-capped at 2 KiB; that's the cap
       for the upstream URL before base64url encoding.
       
       If the upstream is offline you'll get an immediate EOF or a
       TLS handshake error on the streaming endpoints --- there's no
       graceful "the radio is offline" message at the audio-byte
       level. Menu endpoints emit a type-3 row when something throws,
       and skip metadata fields that couldn't be fetched.
       
   DIR icecast.lhs                                 29.1KB  2026-05-12
  TEXT stations.txt                                  259B  2026-05-13