TITLE: Shell script for internet radio
DATE: 2020-03-25
AUTHOR: John L. Godlee
====================================================================


I've been feeling nostalgic for a holiday I took last year to New
Mexico in the USA. We spent a lot of time listening to country
radio stations and driving through the beautiful scenery. While I
am confined to home I thought it would be nice to listen to those
radio stations again, but I was finding it laborious to listen to
the radio through my web browser.

Most internet radio streams have a URL, which can be scraped
usually by looking at the HTML of the webpage, or rarely if the
radio provider is feeling public spirited, in plain text on the
streaming page. These URLs are mostly readable by VLC if they are
mp3, .ogg, m3u, .pls and probably many more. The backend of VLC's
streaming capabilities is an in-built plugin called Icecast,
previously Shoutcast. I made a simple text file of these URLs along
with the names of the stations:

 [VLC]: https://www.videolan.org/vlc/index.en-GB.html


https://radiostationusa.fm/apii.php?url=https://stream.revma.ihrhls.
com/zc1385,Big I 107.9 Albuquerque New Country
   http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p,BBC
Radio 1

http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/n
onuk/sbr_vlow/llnw/bbc_radio_fourlw.m3u8,BBC Radio 4 LW

Then I wrote a shell script which uses fzf to neatly display the
radio station names, then uses sed and grep to send the URL to the
ncurses version of VLC, which on macOS at least is stored in
/Applications/VLC.app/Contents/MacOS/VLC -I ncurses when VLC is
installed using Homebrew.

 [fzf]: https://github.com/junegunn/fzf

   #!/bin/sh

   stations="$HOME/.radio.txt"

   sel=$(sed 's/^.*,//' ${stations} | fzf)

   url=$(grep "${sel}" ${stations} | sed 's/,.*$//')

   vlc "${url}"

Update 2021-04-18

The BBC changed their radio streaming URLs which prompted me to
also change how this script worked a bit. The radio streaming URLs
are now stored in a .pls file, which makes it more compatible with
other music players. I've included the full .pls file here because
these URLs are hard to come by online:

   playlist
   NumberOfEntries=10

   Title1=BBC Radio 4 FM
   File1=http://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourfm

   Title2=BBC Radio 4 LW - non UK

File2=http://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourlw_online_n
onuk

   Title3=BBC Radio 6
   File3=http://stream.live.vc.bbcmedia.co.uk/bbc_6music

   Title4=BBC Radio London
   File4=http://stream.live.vc.bbcmedia.co.uk/bbc_london

   Title5=BBC World Service
   File5=http://stream.live.vc.bbcmedia.co.uk/bbc_world_service

   Title6=WQXR
   File6=http://stream.wqxr.org/wqxr

   Title7=LBC
   File7=http://media-ice.musicradio.com:80/LBCNewsUK

   Title9=BBC Radio Scotland

File9=http://stream.live.vc.bbcmedia.co.uk/bbc_radio_scotland_fm

   Title10=NTS
   File10=http://stream-relay-geo.ntslive.net/stream

The script looks like this:

   #!/usr/bin/env sh

   rfile=~/.radio.pls

   station=$(grep '^Title' ${rfile} | sed
's/^Title\([0-9]\+\)=\(.*\)/\1 - \2/' | fzf | sed
's/\(^[0-9]\+\).*/\1/')

   url=$(grep "File${station}=" $rfile | sed 's/.*=//')

   /Applications/VLC.app/Contents/MacOS/VLC -I rc --no-color $url

Update 2021-06-03

I was getting annoyed having to quit out of FZF and relaunch the
script every time I wanted to change the radio station, so I
re-wrote it to use mpv, using the --bind flag in fzf to run a
never-ending loop. I tried to do similar using VLC, but it kept
quitting back to FZF immediately, rather than keeping VLC open
until I wanted to quit.

   #!/usr/bin/env sh

   rfile=~/.radio.pls

   grep '^Title' ${rfile} |\
       sed 's/^Title\([0-9]\+\)=\(.*\)/\1 - \2/' |\
       fzf --bind="enter:execute;echo {} | sed
's/\(^[0-9]\+\).*/\1/' |
       sed 's/\(.*\)/File\1=/' |
       grep -f - ${rfile} |
       sed 's/.*=//' |
       mpv --playlist=- ;"