Introduction: Keeping It Stoopid Simple Internet Radio: KISSIR

Sometimes it just has to be tactile. No Interface of any kind. Just Buttons.

Raspberry Pi as an internet radio player is nothing new, and there are plenty of instructables on how to create an internet radio player using a raspberry pi with or without a monitor to stream internet stations from around the globe. If you were to choose to go headless (without a monitor), you would still need a means to interface the pi player, usually a web interface if not a direct means of communicating to the host, such as ssh. This instructable will be slightly different; we’ll use simple button presses to send commands to the pi, thus eliminating the need for a web interface and an LCD screen. Sounds easy enough, right (?)

We’ll start off with a very basic design using color coded buttons, each color will represent an internet radio station. We'll introduce some python code to handle the button press: The press will execute a command to play a pre-coded internet radio station using MPG123, a great command line tool for playing audio on our pi.

Your python skills do not need to be advanced. In fact I literally went from "Hello World" to writing this, and as you will see, I borrowed a lot of code - so if I can do it and have it somewhat documented, anyone else should have no problem.

Let's go!

Supplies

Needed Materials

  • Raspberry pi/ pi zero w with all the fixings: Power supply, SD card and Raspbian or Raspbian lite.
  • Wifi and internet access
  • Another PC to perform some web browsing and ability to SSH to the raspberry pi
  • Digital to Analog Converter (DAC) - optional but you'll be thankful.
  • Amplifier
  • Speakers
  • Hookup wire and Jumpers
  • Soldering iron and solder
  • Perf Board for the buttons
  • Tactile buttons: Normally Open- one for each genre of music, a power button, and an optional mute button (7 buttons recommended)
  • A housing unit for all the above (optional but tidy)

Step 1: Pre-requisites:

We'll start off assuming you have already setup your raspberry pi, DAC and amplifier, and will also assume you have access to the internet. Due to the amount of audio equipment choices, preferences, and options for audio listening, we will presume your setup is already complete: you should already have sound coming out of your speakers before you start this project. We will also need to ssh to the raspberry pi, so using pi configuration, ensure interfaces have ssh enabled. I'll be using Raspbian lite, and recommend that you have a fresh install of the latest copy on a fresh sd card dedicated for this project. If successful we will be building a stand alone fixture that can be left powered on 24/7 as a dedicated listening device.

Step 2: Install Python and Pip

I prefer to ssh to the pi using a different pc, and perform all the required functions using an ssh session, but I guess it is possible to initially setup the pi to a monitor, keyboard and mouse and work directly on the pi until it is working and then deploy as a standalone.

First lets do a routine maintenance check of our system and python version:

sudo apt-get update
sudo apt-get upgrade

Ensure Python is installed. In a terminal session type the following at the command prompt:

python --version

If you see python 2.7.13 (or earlier) let's install python 3.+:

sudo apt-get install python3
sudo apt-get install python-pip
sudo apt-get install python3-pip
sudo pip3 install --upgrade pip

Step 3: Install MPG123 and Adafruit Blinka

Now that the foundation has been laid, just a few more installs:

MPG123 is the audio software that will play our music. Installation is really simple:

sudo apt-get install mpg123

I did a lot of research, and found a great template on the Adafruit website about playing sound files using button presses, so rather than start from scratch, lets continue on the trail the folks at Adafruit have already blazed for us. Their program asks that we install Adafruit Blinka:

$ sudo pip3 install adafruit-blinka

Before we go further, let's perform a quick check to make sure we have Alsa setup:

aplay --version

our results should read: version 1.1.3 by Jaroslav Kysela

Step 4: Adjust Volume to 50% in Alsamixer

Now lets take a precautionary measure and adjust our volume to 50% to avoid any deafening surprises:

At the command prompt, type alsamixer:

alsamixer

If we looking at a screen of red white and green, or 100% max volume, it's a good idea to lower the volume to 50% to save our eardrums. We can always adjust later (up or down) if needed.

Step 5: Some Homework: Find 5 Radio Stations Worth Listening To

We'll need one station for each button. Actually, we will need the url for the station. The button press will call the url of the internet radio station in a simple, one line bit of code. However we're getting ahead of ourselves so we have some homework to do; find 5 radio stations and their urls. Finding 5 radio stations is not difficult, but finding their urls can be tricky. I'll explain why in a minute.

SomaFm * is a great source to start out with, especially if you don't have any idea on what you want to listen to just yet. They have a wide variety of eclectic music choices, none of which I find offensive, no commercials, and the best part: They openly share their url's. To grab the url, click on an image of the station you have interest in, and on the left side navigation bar, click "Direct Stream Links". From there, find the MP3 section, and scrape the url of the highest playback rate (ie 128 beats 64). Paste the url into a text editor or notepad for now.

As an example, to scrape Christmas Rocks, the url would be: (we don't need the server description)

http://ice4.somafm.com/xmasrocks-128-mp3

It gets a little dicier outside the world of SomaFm. Many stations use a middleman between the listener and the station, whether it be for advertising, marketing or possibly tracking - and I generally try to avoid these types of stations. Since the middlemen prefer that you listen to the station through them, usually it is pretty difficult to find the url; and that is where Vtuner comes in.

*I would be remiss if I didn't ask for you to consider making a donation to your favorite radio station, as many of the stations rely solely on listener support.

Step 6: Optional: Scrape URL's Using Vtuner

Now comes the fun part....At the Vtuner home page, check out their huge station list link in the upper right corner. Choose a genre of music you have an interest in, and then sort on fastest speed, where you will see a list of stations. Choose a station you think you may like, click on the link or play button and sample the music out. If it's not for you, no worries, repeat the process until we find one suitable for long term enjoyment. In my screen shot, I chose the digital impulse version of Country music and on the next screen, I noticed it is playing out of Croatia. Country Music from Croatia sounds rather interesting.

I like it. But how do i get the url? Simply perform a right click on the white space to the right of the station image, underneath the Station name, and select "View Page Source" and scroll down to about row 150. We're looking for the line that says "// Try to handle icecast". And the url is found immediately underneath!

http://orion.shoutca.st:8110/stream

Pretty slick!

Repeat this step until we have at least 5 stations on our list.

Double Optional: For extra measure, if you can find 5 genres of music that you have an interest in (as opposed to 5 stations), build a list of radio stations for each genre and save the lists as text files. We'll come back to this later.

Step 7: Setup Our Buttons

The most important part! Dust off the old soldering iron or at least plug it in and bake the dust off. It's time to Solder. I am using 4 prong momentary push buttons, normally opened. I'll build an array of buttons (left photo), and fasten them to some perf board. It's hard to tell on the photo, but the direction of the button prongs are all running North-South. On the right side, you can see where i ran a ground rail for my ground wires and attached some male ended jumper cables to the opposite side of each button. Rather than having 7 ground connections, the rail will allow us to share one ground connection to the pi for all. The end result is a delicate wafer board that will be under mounted to the top of the radio using some screws through the pilot holes provided. Only the button tops will appear through the groove I have cut out of the top. Since my top surface is only 1/4" thick, I want to be careful not to over screw. Glue may be helpful to keep the perf board attached to the radio.

Step 8: Identify Our GPIO Pins

In my only other instructable, I presented a new use for the old Google AIY version 1 voice hats. In this widely unpopular (or narrowly popular) instructable, I mentioned how impressed I was with the design of the hat itself. I have a few laying around, so I'll be building a prototype using the hat since it has both the dac and the amplifier onboard.

Let's now identify six pins that will host our button presses. I will ask you to focus on the left side of the Google AIY hat, where it says "servos". There are a column of 6 eyelets for the Pin where i will attach and solder my male button ends from our previous step. Should you be working without the google aiy voice hat, no worries, - the photo on the right will guide you. In either case we will be working with gpio (BCM)pins 26, 06, 13, 05, 12, and 24 from top to bottom (or 0-5). GPIO #24 will be reserved for an optional pause button.

Don't forget to also attach the ground connection.

Step 9: Code

I doubt the code will change much from here, however for the latest version of the python code, please visit my github. I have attached a copy as of 12/18/2019 called pytiful3.py.

It's not the most efficient code you'll ever see, and it's pretty verbose, but it gets the job done.

Let's start by creating a sandbox to play in. From our home directory, create a directory on our raspberry pi called kissir:

mkdir kissir/

and copy the pytiful3.py file contents into the directory by opening the sample file in a text editor, and using

sudo nano kissir/pytiful3.py

copy / paste the file contents into our newly created python script. Don't forget to save our work by using Ctrl-x, Y and enter.

If you want a quick tour of the script, we import the python modules we're going to need, and then we define our buttons and assign a gpio pin to each of the 7 buttons. There will be 5 radio stations (feel free to edit to your station preference), a halt button, and a shutdown button. The while true loop runs and runs until a button is pressed, which in most cases will stop any existing mpg123 playback and start playing the station assigned to the button that was pressed. The pause/halt button is not really a pause button but more of a kill switch since we can't pause internet radio. Internet radio waits for no one.

Step 10: Test in Our Sandbox

Before we deploy our radio, while still in our ssh session, navigate to kissir folder where our script is stored. We can simply run the script from the command line manually by typing:

python3 pytiful3.py

If you peeked at the code first, you probably noticed I left some print statements so we can tell what is happening. If everything worked out well, we will have a prompt that reads "Press a Button". That tells us our script is running and it passed a preliminary code check. My initial attempt had an infinite loop of "music paused - press button to continue", and I found out I had my pause button wired to be always closed, instead of normally open. Hopefully you had better luck with the soldering step.

Ctrl-C will stop the script if you need to abort.

So if you see "Press a button", what are we waiting for? Select any one of our five radio station buttons.

Chances are you will likely hear a speaker pop to initiate the music playback, and I can't help with that for the moment. Mpg123 allows for a "--preload 1" suffix after the station address in the os.system command, however I could not tell if it made a difference. It should allow a slight buffer.

Another bit of code you may have wondered about: there is a " -f 7000" flag after the mpg123 call. This reduces the volume to a far distance of max volume. Full Volume would be 32K. As I understand, the volume scale is not a linear scale, so I can't say it is only one fifth of max volume, but still plenty loud. I had to do this because my soundcard - the Google AIY voice soundcard, does not play nice with Alsamixer sometimes.

Continue to select buttons at your choosing, sit back, relax and enjoy the comfort of your listening for now.

Step 11: Setup Our Code to Run Automatically on Boot

So if everything is running well, and you've enjoyed our sandbox command prompt venture, now is a good time to automate the script load. Make sure you are still in the kissir directory, and place the script code in user bin:

sudo cp pytiful3.py /usr/local/bin/

Make it executable:

sudo chmod +x /usr/local/bin/pytiful3.py

Write a shell script to run it at startup:

sudo nano pytiful3.sh

And insert the following text:

#! /bin/sh<br>
### BEGIN INIT INFO
# Provides:          pytiful3.py
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO

# ensure volume level is not loud TODO

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting pytiful3.py"
    /usr/local/bin/pytiful3.py &
    ;;
  stop)
    echo "Stopping pytiful3.py"
    pkill -f /usr/local/bin/pytiful3.py
    ;;
  *)
    echo "Usage: /etc/init.d/pytiful3.sh {start|stop}"
    exit 1
    ;;
esac

exit 0

Move it to init.d:

sudo mv pytiful3.sh /etc/init.d/

Make it executable:

sudo chmod +x /etc/init.d/pytiful3.sh

Register the script to run on startup:

sudo update-rc.d pytiful3.sh defaults

Step 12: Test Again

Now that we have our script loaded to run on startup, just remember that any changes we make have to be brought over to the user bin, and our beautiful, kissir/pytiful3.py script is just an orphan now. But on the bright side, we still have a sandbox to play in. I'll probably continue to play with the script, make changes and save it as a new version in the near future. It's still a working project.

Let's do a reboot, wait for the pi to restart, and after about a minute, press a button again.

If your audio volume is very low, remember we have alsamixer volume at 50%, so we can raise it accordingly from the command prompt.

For starters, one thing that is needed is a global volume value, instead of having to change the volume level 5 different times.

Hey, what about that list of radio stations that we made in step #6? Well, it turns out MPG123 has a random selection command. It's as simple as building a list of station urls, and instead of calling for one radio station url, simply use

"btn1234_choice = random.choice(btn1234)", immediately after identifying our list of stations, where btn1234_choice is our list. Don't forget to use square brackets [ ] around our list of stations separated by commas. The subprocess command call then plays our random choice:

subprocess.call(['mpg123', '-q', btn1234_choice, " --preload 1"])

Step 13: Box It Up, and We're Done

If you've gotten to this step, the work is complete! Congratulations - you've just built a standalone internet radio player.

Depending on the equipment you have (speakers, dac and amplifier), you may be wondering how to hide some of the wires laying about. Perhaps another instructable for another day, but if you plan on making a housing unit to tuck some of the wires into, I recommend giving yourself plenty of extra room.

As you can see in the photos above - I actually made two kissirs, one using the remnants of a glue up mishap on my first attempt (from warped humor comes warped boards). The second unit uses sound exciters rather than conventional speakers, and if you picked up the name of the device on one of my screenshots, I named it slimbox.

I found this project to be quite fun. Both times. Certainly not a difficult project, perhaps a little time consuming but very rewarding. I hope you enjoy your listening as well.