On Sunday I wrote about Reading mp3 metadata, in an effort to create m3u playlist files for mp3 files stored in directories by artist and album. I got an unexpected solution from an unexpected source.
I had cast the problem as how to read data out of mp3 files so that I could populate m3u files. You see, there's no spec I could find for m3u files, so the best I could do was to create files like those created by Winamp. They look kind of like this:
#EXTINF:173,Aimee Mann - One
#EXTINF:207,Aimee Mann - Momentum
The number after #EXTINF is the duration of the song, in seconds. The rest of the line is the title to display in the player. So I figured I needed to determine the length of the song, and find a good title. But the title data is dirty and stored in discouragingly diverse ways. The length isn't stored at all, and seems to require reading all of the song data to decode fiddly bit rates. Yuck.
Then I got an email on the topic from Martin Fowler of all people. He wasn't delivering some deep insight about refactoring or object orientation. He told me about how he's organized his mp3 files, and in particular, he told me he makes m3u files that are just a long list of file names.
Of course! Just make a list of file names, and Winamp will read the other data itself when the song plays. Simple. A few minutes with Python, and I had it all done:
# Create a tree of .m3u files, one for each directory in the tree,
# containing all the .mp3 files in the subtree rooted there.
# A stack of .m3u files.
m3us = 
'''Called recursively for each directory in the tree.'''
# Make a new .m3u file for this directory.
m3u = d / (d.name + '.m3u')
# Add all the .mp3's in this dir to all the .m3u's.
for f in d.files('*.mp3'):
for m3ufile in m3us:
m3ufile.write(f + '\n')
# Recurse into all the subdirectories.
for dchild in d.dirs():
# We're done with this directory's .m3u file.
Update: In January 2004 I finally got a complete solution together.