Pudsey Clough Radio
The technical aspects of Pudsey Clough Radio
Overview
Pudsey Clough Radio runs on a Raspberry Pi Pi400 (see footnote) in my external workshop here in Pudsey Clough.
The Pi400 runs Music Player
Daemon to manage the playback of Mp3 files held in the default
mpd
location: /var/lib/mpd/music
these files
are in turn managed by simple .m3u playlists in
/var/lib/mpd/playlists
.
mpd
itself is managed by clients and comes with its
own basic client mpc
. With mpc
you can load
different playlists. What mpd
doesn’t have is the ability
to schedule playlists so I needed to write something myself to manage
that.
The audio stream from mpd
is sent to Icecast and the resulting public
stream is proxied by a netradio provider, Streamerr - this means in the
unlikely even of more than a handful of listeners things should stay
stable, it only costs £3.99 a month.
scheduler.sh
In order to be able to schedule themed shows I need to be able to
load in a new playlist at a specified time, then when the show is
complete switch back to a randomised pool of Mp3s, cron
is the obvious solution with a script that loads a playlist using
mpc
.
Scheduler first validates the playlist argument to check it exists,
it currently only schedules a show to play at a specific time daily
(fixing that just needs to make use of $3
in the
cron
line):
#!/bin/bash
# Usage:
# scheduler.sh playlist time day where time is in 24hr format and day is a cron value
# eg. scheduler.sh playlist_name 16:00 *
echo --------------------------------
echo
echo Pudsey Clough Radio scheduler
echo
playlist="$1"
echo "Looking for: $playlist"
playlists=($(mpc lsplaylists))
foundMatch=false
for i in "${playlists[@]}"
do
echo " > $i"
if [ "$i" = "$playlist" ]; then
foundMatch=true
fi
done
if [ "$foundMatch" = true ] ; then
echo
echo Found $playlist
echo
else
echo
echo Playlist $playlist is not available
echo
exit 1
fi
After validating the playlist exists the script parses the input
time and creates the cron
entry pointing to a
play_playlist.sh
script (see below):
echo "Start time: $2"
startTime=$2
#This splits the time argument in the format HH:mm:
startHours="${startTime%:*}"
startMinutes="${startTime#*:}"
echo Start hours: $startHours
echo Start minute: $startMinutes
playlistPath="/var/lib/mpd/playlists/$1.m3u"
echo Playlist path: $playlistPath
cronStart="$startMinutes $startHours * * * /home/user/pcr/play_playlist.sh $1"
echo "Cron: $cronStart"
# Write cron entry:
(crontab -u $(whoami) -l; echo "$cronStart" ) | crontab -u $(whoami) -
That should take care of starting a show but after completion we
need to switch back to random Mp3 playback from the general pool (a
generic playlist with no theme), includes ffprobe
logic
found in a Stack Overflow post:
playlistSeconds=0.0
while read line; do
trackLength=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "/var/lib/mpd/music/$line")
echo "$line: $trackLength"
playlistSeconds=$(dc <<<"$playlistSeconds $trackLength + p")
done <$playlistPath
echo "total playlist seconds (float): $playlistSeconds"
playlistSecondsInt=${playlistSeconds%.*}
echo "total playlist seconds (int): $playlistSecondsInt"
playlistHours=$((playlistSecondsInt/3600))
playlistMinutes=$((playlistSecondsInt%3600/60))
playlistSeconds=$((playlistSecondsInt%60))
echo playlist hours: $playlistHours
echo playlist minutes: $playlistMinutes
echo playlist seconds: $playlistSeconds
We now have the hours, minutes, and seconds to add onto the start
time to create second cron
entry which calls another
script: play_general.sh
(that part of the script needs
more work so isn’t documented here yet)
play_playlist.sh
A relatively simple bash script to validate the playlist argument
then queue it to play. This should use mpc clear
instead of mpc crop
but I found that killed the stream
(mpc clear
removes all queued tracks while
mpc crop
removes everything except the currently
playing track), this means if a 20 minute track from the random pool
had just started playing the scheduled show would start 20 minutes
late. Some investigation needed. It also turns off random and repeat
which are used when playing from the general pool.
#!/bin/bash
echo
echo Playlist player
echo
playlist=$1
echo "Looking for: $playlist"
playlists=($(mpc lsplaylists))
foundMatch=false
for i in "${playlists[@]}"
do
echo " > $i"
if [ "$i" = "$playlist" ]; then
foundMatch=true
fi
done
if [ "$foundMatch" = true ] ; then
echo
echo Playing $playlist
echo
mpc random off
mpc repeat off
mpc crop
mpc load $playlist
else
echo
echo Playlist $playlist is not available
echo
fi
play_general.sh
A simplified version of play_playlist.sh
that loads
the default playlist back in and reenables random and repeat:
#!/bin/bash
echo
echo Pudsey Clough Radio play general track pool
echo
mpc crop
mpc load playlist_all
mpc random on
mpc repeat on
echo
echo
Footnote
Lots of people, myself included, do not endorse Raspberry Pi after they hired a former surveillance police offer and their reaction to the backlash (more details here) - they never apologised, instead hoping everyone would forget and move on. I’d bought the Pi400 before this happened and it would be a waste (as in e-waste) not to make good use of it and instead buy new hardware. All the software for Pudsey Clough Radio uses standard Linux tooling and will run on any cheap Linux box.