Book Image

Raspberry Pi Blueprints

Book Image

Raspberry Pi Blueprints

Overview of this book

Table of Contents (17 chapters)
Raspberry Pi Blueprints
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Scripting a media player


Now that the FM transmitter is working, we can make it do something a little more useful; in this case, we will use it to broadcast a personalized radio station with a collection of your own music.

To do this, we will write a Python script that manages to search for MP3 files and calls PiFM to broadcast them.

Calling PiFM from Python

In the PiFM download and on the PiFM website, you may have noticed that there is a Python library that can be used to control PiFM. Although, looking at the source code for it, you can see that all the library can do is call the pifm executable with the minimum number of commands, and therefore will not allow us to play MP3 files.

However, it is a simple process to create our own function that will allow us to pass the filename of an MP3, a frequency, and that will allow Python to call ffmpeg and PiFM in order to broadcast the audio in the file for us:

def play_file(filename, frequency):
  command = 'ffmpeg -i "%s" -f s16le -ar 22.05k -ac 2 - | sudo ./pifm - %f 22050 stereo' % (filename, frequency)
  subprocess.call(command, shell=True)

This code is an extract from the player.py file; all we are doing here is taking the shell commands used to play an MP3 file and replacing the filename and broadcast frequency with values that are passed to the function as parameters. Then, we are using the Python subprocess module to execute the command as if it was typed into a shell.

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Searching for MP3 files

For our script to play any MP3 files, it needs to be able to find them first. Finding an MP3 file involves taking a look at each file in a starting directory to check whether a file is an MP3 file, and then repeating this process for every directory within the start directory. Thankfully, Python makes this very easy:

mp3_files = list()
for root, dirs, files in os.walk(directory):
  for filename in files:
    if filename.endswith(".mp3"):
      mp3_files.append(os.path.join(root, filename))

Here, directory is the directory we want to search for files media in. The os.walk function returns a tuple; the first element (root) is a string that contains the absolute path to the search directory, dirs is a list of directories within the search directory and its subdirectories, and files is a list of all the files within the search directory and its subdirectories.

The if statement is a simple way to check whether a file is an MP3 file based solely on its file extension. If it has the .mp3 extension, it is added to the mp3_files list, which is then passed to the playlist code.

Getting input from a command line

In order to set various settings for our player script, for example, the directory in which you can search for files, we need a way to get input from the user via a command line, and in this case, from the arguments passed to the script when it is started. To do this, we will use the argparse Python module:

parser = argparse.ArgumentParser(description='Broadcast a set of MP3s over FM')
parser.add_argument(
  '-f', '--frequency',
  default=101.1,
  type=float,
  help='Frequency on which to broadcast')
params = parser.parse_args()

The argparse Python module allows you to define a set of arguments that can be passed to a Python program, it allows you to parse the arguments when the script is run, and it automatically allows you to generate a help page (accessed by passing -h to the script).

In this case, we will add an argument for the broadcast frequency, which is set using either -f or --frequency; type is used to validate input from the user, default is what is read by the program if the user does not set a value, and help is what is shown for this argument on the help page.

Queuing the media files to be played

Our media player will also need a way to manage which file should be played next. We will implement this in two ways: linear playback in the order the files were discovered and randomized playback:

file_number = -1
while True:
  if params.random:
    file_number = random.randint(0, len(filenames) - 1)
  else:
    file_number += 1
    if file_number >= len(filenames):
      return
play_file(filenames[file_number], params.frequency)

Here, if the --random parameter has been passed to our script, whenever we are about to play a file, the file to be played will be selected at random using the randint function in the random Python module. This number is then used to get a certain file from the list of filenames that were previously discovered.

Using the media player script

The player.py script can be invoked using the following command:

python player.py -d music -f 99.9 --random

This will search for all MP3 files under the music directory and broadcast them at 99.9 MHz in a random order. A full list of commands will be available to you if you run:

python player.py -h

Since the radio is not much of use when you have to SSH into it to start playing the music, we will add a cron job that will start the player.py script when the Pi boots up.

To do this, we will use a shell script to start the Python script (start_player.sh):

#!/bin/bash
sleep 20
cd /home/pi
python player.py -d music --random -f 99.9 &

This will ensure that the player script is executed in the correct folder, in this case, /home/pi, as this is where our PiFM executables and music directories are.

Next, we will add an entry in the crontab, which is where cron jobs are defined. This can be edited with the following command:

sudo crontab -e

This command will open the default command-line text edit on the Pi, nano, which will allow you to add entries to the crontab. To start our media player script, we will need to add the following line to the end of the crontab that is opened:

@reboot /home/pi/start_player.sh

In our case, we will use the @reboot cron rule instead of specifying a time for the command to be run, and as the name suggests, this will run the given command when the OS starts.

Press Ctrl + X followed by Y and Enter to save the changes to the crontab, then use the following command to reboot the Pi, and if all goes as planned, start your personalized radio station:

sudo reboot