LINUX GAZETTE
[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


Managing MP3 Playlists, The One UNIX Way

By zhaoway


Prelude

Many cool, flashy MP3 players for Linux have been around for quite some time, but none of them resemble the One True UNIX Touch-n-Feel. They are all submissive to the shabby concept of the so-called Gooey User Interface, and I refuse to mention their names in this article that is dedicated to the One True UNIX Way of doing things. After all, the listening experience usually does NOT involve the eyes, so why not purge those graphical players to give them a rest while we concentrate on our beautiful music?

But of course, we are dedicated Linux users. (Oh, I heard you ask why I say Linux instead of UNIX? Hmm, I appreciate careful readers--hehe). This doesn't mean that we are not as newbie-friendly as most of the other computer user groups. Absolutely not. So I will first tell the uninitiated among you what that One True UNIX Way is. Oh, wait! I heard some of you moaning about some other crappy, loony, self-assured philosophical nonsense now. Okay, let's kick those newbies, and I will show you the bread and butter of my article. Advice for newbies: just pretend you aren't one.

Sweet Instruments

First, we will look at a command-line MP3 player. Then I will introduce you to some flexible ways of managing MP3 playlists along with some very short shell script snippets and a small C program to aid in the task. A very useful rename utility that comes along with the standard Perl distribution is briefed also.

Command-Line MP3 Players

There are many command-line MP3 players on the market. Oops, I mean on the Internet. But I only will introduce my favorite one: alsaplayer-text, which is packaged for Debian GNU/Linux already. (The Debian package name for it is just alsaplayer-text.) The usage most interesting to us is, for example,

% alsaplayer-text -l 85 -n some.mp3 >/dev/null 2>&1;

The -l switch controls the volume, with possible values ranging from 0-100. The -n switch tells it to start in command-line mode. The ponytail >/dev/null 2>&1 is a common trick to suppress the rubbish output. And remember, man is your friend. The above is enough for us to play with it using shell scripts. And through shell scripts, we will gain maximum flexibility in the One True UNIX Way.

Next, we will look at a command-line ID3 tag editor. An ID3 tag is a bit of information tucked within an MP3 music file that says something about the MP3 song itself: its title, the artist who performed it, etc. The ID3 tag editor we will look at is named mp3info, which was packaged for Debian too. The Debian package name is just mp3info, which means you can apt-get install mp3info very easily. (That is, if you are fortunate enough to be on a Debian GNU/Linux system.) Now let's see a usage scenario to end our briefing on the command-line MP3 commanders:

zw@q ~/mp3/chopin % mp3info chopin:revolutionary_etude:robin_alciatore.mp3 
File: chopin:revolutionary_etude:robin_alciatore.mp3
Title:   CHOPIN: "REVOLUTIONARY" ETUDE  Track: 
Artist:  CHOPIN PIANO FAVORITES
Album:                                  Year:  
Comment: http://www.mp3.com/chopinpiano Genre: Blues [0]

zw@q ~/mp3/chopin % 

Admittedly, the display isn't very flashy, and the information presented isn't satisfying. (For example, for a classical piano work, we want to know more than can be presented in a poor ID3 tag.) Readers are invited to make their own improvements.

Prepare for Shell Scripts: Line Randomizer

One often wants to play songs in a random order. For this purpose, we need a line randomizer, presened here as rand.c, which can read some lines (filenames) from stdin and randomize the order of the lines, and then print them line by line on stdout like this:

zw@q ~/mp3/chopin % ls           
chopin:nocturne_in_c_minor:robin_alciatore.mp3
chopin:nocturne_in_db_major:elena_kuschnerova.mp3
chopin:nocturne_in_e_major:joerg_demus.mp3
chopin:nocturne_in_f#_major:john_bell_young.mp3
chopin:nocturne_in_g_minor:robin_alciatore.mp3
zw@q ~/mp3/chopin % ls|rand
chopin:nocturne_in_g_minor:robin_alciatore.mp3
chopin:nocturne_in_e_major:joerg_demus.mp3
chopin:nocturne_in_db_major:elena_kuschnerova.mp3
chopin:nocturne_in_f#_major:john_bell_young.mp3
chopin:nocturne_in_c_minor:robin_alciatore.mp3
zw@q ~/mp3/chopin % 

Prepare for Shell Scripts: Rename the MP3 File

When downloading MP3 files from the Internet, you get a lot of files with spaces in between the filenames, which is a disaster in shell scripts. Of course, we could fiddle with the magic shell variable $IFS but I will introduce a handy utility that comes with the standard Perl distribution to rename a bunch of files according to some Perl Regex (regular expressions). Ladies and gentlemen, let's welcome the charming /usr/bin/rename.

zw@q ~/mp3/u2 % ls
u2 all that you can't leave behind new york.mp3
u2 all that you can't leave behind peace on earth.mp3
u2 all that you can't leave behind stuck in a moment you can't get over.mp3
zw@q ~/mp3/u2 % rename 's/^(u2) /$1:/; s/(behind) /$1:/; s/ /_/g' *.mp3
zw@q ~/mp3/u2 % ls
u2:all_that_you_can't_leave_behind:new_york.mp3
u2:all_that_you_can't_leave_behind:peace_on_earth.mp3
u2:all_that_you_can't_leave_behind:stuck_in_a_moment_you_can't_get_over.mp3
zw@q ~/mp3/u2 % 

So you want to learn Perl now?

Use Hard/Symbolic Links to Simulate Playlists

If you happen to open an MP3 playlist file (filename postfix *.m3u) with a text editor, you will see that the contents of the file are no more than some lines of full pathnames to your MP3 music file. So, why don't we get over it and use directories and hard links or symbolic links to achieve the same effect as a playlist and to let shell scripts process it more easily (for example, by just using ls) than to parse a text playlist file?

In our arrangement, you just make a new directory as a playlist using mkdir, then link the MP3 files that you want to place in that playlist into that directory by using ln. If your MP3 file is not on the same filesystem as your playlist directory, then you have to use symbolic links (ln -s), but hard links have the advantage that when you move around your original MP3 file, symbolic links (and traditional playlists, i.e., those *.m3u files) go dead but hard links still would work like a charm. Believe me, this feature is very important. You just don't know how many times you'll want to move around you MP3 files after they are downloaded from the Internet or are ripped off a music CD!

zw@q ~/mp3 % ls
chopin  classical-all  debussy  fav  nightly  u2
zw@q ~/mp3 % find chopin                
chopin
chopin/chopin:nocturne_in_db_major:robin_alciatore.mp3
chopin/chopin:berceuse:robin_alciatore.mp3
chopin/chopin:nocturne_in_db_major:elena_kuschnerova.mp3
chopin/chopin:nocturne_in_c_minor:robin_alciatore.mp3
zw@q ~/mp3 % find nightly 
nightly
nightly/chopin:nocturne_in_db_major:robin_alciatore.mp3
nightly/chopin:berceuse:robin_alciatore.mp3
nightly/ravel:gaspard_de_la_nuit:elena_kuschnerova.mp3
nightly/chopin:nocturne_in_db_major:elena_kuschnerova.mp3
nightly/chopin:nocturne_in_c_minor:robin_alciatore.mp3

In Concert

With all of the preparations above, the following is a snippet from my ~/.zshrc. It should be very easy to adjust it to your own favorite shell. There is plenty of room for enhancements. One obvious thing to do is to use mp3info, as mentioned above, to get the information about an MP3 song instead of relying on a filename.

PLAYLISTS=$HOME/mp3

# 1st arg is the playlist to be played
# 2nd arg is the volume to play with

play() {
    # Install the ALSA song card driver.
    if [[ -z ` lsmod | grep snd-card-cmipci ` ]]; then
	sudo modprobe snd-card-cmipci;
    fi
    # Play our MP3 playlist.
    while true; do
	for i in ` find $PLAYLISTS/$1 -name '*.mp3' | rand `; do
	    j=` basename $i | sed -e 's/:/: /g; s/_/ /g; s/,/, /g; s/.mp3$//;' `;
	    echo -n "Playing $j ";
	    alsaplayer-text -l $2 -q -n "$i" >/dev/null 2>&1;
	    echo "DONE.";
	done
    done
}

In the above snippet, we first check if the ALSA sound card driver for Linux is already loaded. If not, we load it by calling modprobe. My sound card is a C-Media 8738, the ALSA driver name for it is snd-card-cmipci. This is probably different on your system. You may not even be using the ALSA (Advanced Linux Sound Architecture) at all. In this article, I cannot go much deeper on how to set up your sound system on Linux. If you have difficulty setting up your sound system, or if you are interested in ALSA, check the Linux Documentation Project and the ALSA Project web pages for help. (Or turn to your local guru.)

The snippet above keeps playing a playlist and plays all songs on it in a random order, like the following screenshot shows. While a song is playing, you even can skip to the end of the song if you don't like it and jump to the next song by pressing Ctrl-C. By pressing Ctrl-Z to kill the process, you can stop it (of course this is not a very elegant stop).

zw@q ~ % play chopin 75
Playing chopin: nocturne in e major: joerg demus DONE.
Playing chopin: nocturne in db major: robin alciatore DONE.
Playing chopin: nocturne for violin and piano: alexander skwortsow, violin DONE.

You easily can write your own scripts to achieve your own satisfaction, providing you use your imagination. Open sesame! Now it's your turn, dear reader; thanks for coming with me along the One UNIX Way! So long!

Have fun and good luck!

Zhaoway

Zhaoway lives in Nanjing, China. He divides his time among his beautiful girlfriend, his old Pentium computer, and pure mathematics. (He's teaching himself grad level math. If you have a few precious stamps to spare and some used grad level math books sleeping around, then feel free to send him a copy.) He is also a volunteer member of the Debian GNU/Linux project.


Copyright © 2001, zhaoway.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 73 of Linux Gazette, December 2001

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]