What if your Pi waked you up every morning with your favorite radio station? Wouldn’t it be cool if it stopped playing when you leave home? And what about not bothering you on holidays?

I have a pair of speakers connected to my Pi, and I keep them on 247. This opens a lot of possibilities. One is to make my Pi stream some radio always at a fixed time.

Having set up the speakers, configured a player such as MPD, and obtained the streaming URL, that becomes fairly easy to do. Only a matter of placing a couple of commands on your crontab.

I wanted, however, to make something more robust and take care of some details. For that, I wrote a small Bash script. On this post, I will walk you through my fairly simple, but convenient setup.

Requirements

I’ll assume you have:

  • MPD installed, running and properly configured
  • Some speakers connected to your Pi, and configured on MPD
  • MPC installed
  • Cron installed

First of all, set the volume!

As much as you like a station, you probably don’t want to listen to them on a random volume first thing in the morning. Neither your neighbours.

So let’s set it to a good level.

On ALSA

If your Pi uses ALSA, doing it is as simple as this command, replacing 20 for the desired level:

$ mpc volume 20

On PulseAudio

For PulseAudio, things get a bit trickier. In this case, the volume command adjusts the volume of the MPD sink-input, which is closed whenever MPD stops the playback. This means that, if you issue the same command before anything is playing, you’ll get an error.

A solution for that is setting always_on = true for the PulseAudio output in /etc/mpd.conf. However, doing this made me experience some delays and weird behaviours on MPD. So I did another thing.

My hacky workaround is to create a silent track and ask MPD to play it. In the meanwhile, I can set the volume. Like this:

set_volume() {
  mpc clear
  mpc add http://localhost/silence.ogg
  mpc play
  sleep 10
  mpc volume $1
  mpc clear
}

Notice that I placed the silent file on my web server. This is another workaround, since MPD - at least the version on Raspbian Stretch - won’t play local files outside of the library.

Did you unmute?

This step may sound silly, but for someone as me who mutes the Pi to do some VNC work, it actually can be a lifesaver.

My script makes sure my Pi is not muted and it also assures the general volume to be at 100%.

For PulseAudio:

pactl set-sink-mute sink_name false
pactl set-sink-volume sink_name 100%

Where sink_name will be something like alsa_output.pci-0000_00_1f.3.analog-stereo. You can get it issuing:

$ pactl list sinks short

For ALSA, you should run something similar to this:

$ amixer -c 0 set Master unmute

Check alsamixer and replace 0 and Master with the values for your setup. We don’t set anything to 100% here, because on ALSA you only have one volume per output (the one we set on the previous step).

Holidays!

On cron, we’ll make sure that our radio alarm only plays on weekdays. But what about holidays? You probably don’t want to be woken up at 6 am!

I solved that in a simple way. In a text file I placed all the holidays, one per line. Then, I made the script look on that file for the current day, and to abort if it is found.

So we got a function like this:

check_holiday() {
  if grep -q "$(date +%Y-%m-%d)" "$HOLIDAYS_FILE"; then
    printf "Today is a holiday. Not doing anything.\n" >&2
    exit 0
  fi
}

Let’s play!

Now that we checked the day is not a holiday, and properly set the volume, it’s time to play our radio!

For this, I’d also recommend to have a backup station, in case the streaming URL of your favorite radio gets broken. You could also add a song from your library, in case there are any network problems. This way, you make sure something will always play.

One possible way:

mpc clear
mpc add https://example.com/preferred_stream
mpc add https://example.com/backup_stream
mpc add "A song.ogg"
mpc random off
mpc play

This will play your preferred stream if available, and fallback to a backup radio when not. As a latest precaution, it will also have a local song to play, for example when your Internet connection is down, or both streams decided to hate you.

You can get creative here. For example, you could add many radios, maybe using a playlist, and turn random on. So each day a different station would wake you up.

My actual script is a bit different on that part, because instead of passing some URLs through MPC, I call the PiFi Radio (a MPD web client to listen to radio that I wrote) API with the radio names. This is more convenient to me, since I can store all the streaming URLs in a single place.

What about stopping?

The same way I wanted my Pi to play radio automatically every morning, it would be nice that would stop playing it without human intervention.

While we could get fancy here and try to detect when we leave home, I decided to just schedule a reasonable time for the playback to stop.

At the given time, cron calls the necessary steps to do it, which are simply:

mpc stop
set_volume 50

Where set_volume is the function we’ve written before.

Let’s schedule it

Now that our script is done, we need to make it run at the desired time. For that, we’ll use cron. Alternatively, you could use systemd timers. I’ll do it old school.

You can add the script to your personal crontab, running:

$ crontab -e

I dropped it under /etc/cron.d:

# /etc/cron.d/radioauto

# Play radio automagically in week days
00 06 * * 1-5 pi /opt/rc/pi-scripts/radioauto start
00 08 * * 1-5 pi /opt/rc/pi-scripts/radioauto stop

This will run the script from Monday to Friday at 6 and 8 am. First it start argument, than with stop.

If you copy and paste those lines in a user crontab, remember the columns are a bit different. So be sure to remove the user column (the one which says pi).

The result

And we are done. Our Pi will wake us up every day with our favourite radio. It will stop playing at a given time automatically. And we won’t be bothered on holidays.

You can check my full script here.