Using Ruby to Process m3u Playlists
Written By: Nathan Baker
- 06 Apr 2006 -
Description: Programming in Ruby is fun! In this tutorial, we will use Ruby to process the m3u playlists used by a number of media players.
- Introduction
- Part 1: Getting our feet wet
- Part 2: Slowly getting there
- Part 3: I/O, I/O, it's off to work we go
- Part 4: Cleaning up our mess
- Part 5: The extra mile
Part 1: Getting our feet wet
Winamp, WMP, Musicmatch, and other popular media players are all capable of reading and writing .m3u playlists. This is probably because their content is so easy to parse, given that they're plain text. We're going to take advantage of this to do something shocking: read a playlist and display it. Yeah, you're probably muttering in your beard (if you do indeed have one of those) about the spiffy text editor that was your first real C project and took 10,000 lines of code. Patience! Baby steps!
The format of the playlist file is really simple. It starts with the text #EXTM3U followed by an EOL character. After that, you generally have alternating lines, the first one being #EXTINF: (track length in seconds),(formatted title of song) and the second one being the relative path to the song. Every file written by Winamp uses this format, though deviations are permitted. We will assume that your file follows this format.
Open up a text file and call it something like m3uParser.rb. In Ruby, everything is a class. So we're going to make one of our own. Type in this code:
class Playlist def [](idx) @playlist[idx] end end
OK, so that's not going to change the world. But it does get us started with Ruby! But what does it do? It's pretty obvious that we create a class named Playlist. Inside this class, we define a function (the def keyword marks the start of a function definition) that is invoked with the brackets operator. But before I go any further, a bit about variables:
If you ever programmed in an early version of BASIC, you probably remember using the $ to denote a string variable (due to the BASIC team's strict devotion to backwards computability, every version of BASIC up to Visual Basic 6 retained this notational convenience). Similarly, Ruby uses certain characteristics in identifiers to determine information about those identifiers.
- Constants and class names start with a capital letter
- Class instance variables start with an @
- Static class variables start with two @@
- Globals start with a $
- Everything else (lower-case and _) is local
I think it's really interesting that a language designed by a Japanese person uses case like this, since Japanese itself does not have the notion of upper- and lower-case letters. Anyway, armed with this knowledge we will continue to examine the tiny code fragment above.
What does a playlist need? Well, it needs to know the name of the song, maybe some other information...oh, wait. A playlist also needs a list (this is the benefit of a college education). The best abstraction of a playlist is a class that behaves like a list, so we are using Ruby's extremely easy operator overloading facility to make the playlist class act like an array.
If you are from a C background, you're probably thinking "wait, we reference the class variable @playlist, but where is it declared?" while those of you who are more familiar with scripting languages see nothing amiss. The truth is, variables don't really need to be declared. They don't need to be typed, either, so you can assign a number to a variable that used to hold a string. Merely by referencing @playlist, we are implicitly willing it into being.