Recently, I've become a fan of MPD - "Music Player Daemon," which I have
running on a Pi on my local network. I use mpc
to control it from my
desktop. Starting a radio station requires several steps, so I wrapped
them in a script. This script is a bit brute force, in that it wipes the
MPD queue, but mostly this is about Bash completion and for now this method
works for me:
#!/usr/bin/env bash
# filename: ~/bin/radio
radioHost="pib.local"
export MPD_HOST="${radioHost}"
declare -A stations=(
["anima"]="http://yp.shoutcast.com/sbin/tunein-station.xspf?id=1679935"
["cbc-1to"]="https://cbcliveradio-lh.akamaihd.net/i/CBCR1_TOR@118420/master.m3u8"
["cbc-musiceast"]="https://cbcliveradio2-lh.akamaihd.net/i/CBCR2_TOR@382863/master.m3u8"
["jazz24"]="https://live.wostreaming.net/playlist/ppm-jazz24mp3-ibc1.m3u"
["soma-defcon"]="https://somafm.com/defcon.pls" # DEF CON year round, music for hacking
["soma-ds1"]="https://somafm.com/deepspaceone.pls"
["soma-dubstep"]="https://somafm.com/dubstep.pls"
["soma-dz"]="https://somafm.com/dronezone.pls"
["soma-goa"]="https://somafm.com/suburbsofgoa.pls"
["soma-groove"]="https://somafm.com/groovesalad.pls"
["soma-grooveclassic"]="https://somafm.com/gsclassic.pls"
["soma-n5md"]="https://somafm.com/n5md.pls"
["soma-poptron"]="https://somafm.com/poptron.pls"
["soma-secretagent"]="https://somafm.com/secretagent.pls"
["soma-thistle"]="https://somafm.com/thistle.pls" # Celtic
["soma-u80s"]="https://somafm.com/u80s.pls" # Underground 80s
)
help() {
cat << EOF
$(basename "${0}") [-h] [-s] <station-name>
Use 'mpc' to clear the MPD playlist and start playing the named station.
-h show this help and exit
-s show current station and track (display varies by station)
MPD host is set (in this script!) to "${MPD_HOST}"
Available stations:
EOF
# send them through 'sort' as this doesn't list them in the order above?
for stationName in "${!stations[@]}"
do
echo " ${stationName}"
done
}
if [ $# -eq 0 ]
then
help
exit 0
fi
while getopts :hs opt ; do
case $opt in
h) help
exit 0
;;
s) mpc current
exit 0
;;
*) echo "unknown option ... "
help
exit 1
;;
esac
done
mpc clear
mpc load "${stations["${1}"]}"
mpc play
A big thank you to Soma FM who have been providing commercial-free (listener-supported) music for ... a couple decades now. And doing it well.
But let's get on to the Bash completion portion of this discussion. I have to admit I find Bash completion somewhat daunting: with scripts that take multiple options, it can be very complicated to set up and I haven't got my head around it yet. But for simple commands, like this one, it can be fairly easy.
If you run radio -h
you get the help output:
radio [-h] [-s] <station-name> Use 'mpc' to clear the MPD playlist and start playing the named station. -h show this help and exit -s show current station and track (display varies by station) |2015 MPD host is set (in this script!) to "pib.local" Available stations: soma-groove soma-goa soma-dubstep soma-dz soma-secretagent soma-poptron jazz24 soma-ds1 cbc-musiceast anima soma-thistle soma-n5md soma-grooveclassic cbc-1to soma-defcon soma-u80s
To start a station, you would run radio soma-groove
. For Bash
completion to work, we would want radio <TAB><TAB>
to show us
potential radio station matches, like the list of "Available stations."
Bash completion has an option for word lists: this works great for me for a
couple reasons, the first being that it's easy to understand, the second
being that after decades of using Linux, if there's one thing I'm good at,
it's producing lists at the command line. And this is an easy one.
# ~/.bashcompletion.d/radio
complete -W "$(radio -h | sed -e '1,/Available stations:/d')" radio
That's it: one line, to get this to work exactly as expected. Your distro
may or may not auto-load stuff in the ~/.bashcompletion.d/ folder: if it
doesn't, the single command complete -W "$(radio -h | sed -e
'1,/Available stations:/d')" radio
is a standard Bash command that you can
run at the command line to test and/or add to your ~/.bashrc to make it
permanent.
Let's look at what that's doing: radio -h | sed -e '1,/Available
stations:/d'
tells sed
to search the output of radio -h
for
"Available stations:" and then delete line 1 through the matching line.
What that leaves us with is a list of station names: this is exactly what
we need for our completions.
Looking up help for the complete
command is a bit odd: one way is
help complete
which is the official Bash way, but the help available
is short and incomplete. This led me to find an interesting inconsistency
between Debian and Fedora: if you try man complete
on Debian, you get
"No manual entry for complete" - which, strictly speaking, is true. But
Fedora handles this better. Try man complete
on Fedora, and it opens
the BASH_BUILTINS man page. You'll have to search a bit to find the
section on "complete", but it's worth it: there's a lot more information.
On Debian, you can type man builtins
and do the same search.
What we're using here is complete
's -W
option, which takes as
input a "wordlist." This is by far the easiest way to load up Bash
completion, and probably the commonest. I hope to get into the other
methods soon.