Export iTunes Playlists to a non-iTunes World
Tuesday, 1 March 2011
I freely admit my dislike for iTunes—it’s a black box where you toss your music, giving full control over your library to Apple.
The problem is that sometimes you might want to manage your library in a way that Apple never intended, and then things become challenging. iPods, iPads, and iPhones pretty much force us to use iTunes, so why not figure out some way to lessen the pain?
I like the playlist tools that iTunes provides, and I find it very convenient to create Smart Playlists or to create Genius lists. However, I want to keep my Master Library of music elsewhere, far from iTunes. Wouldn’t it be great if I could share these playlists on my home network in a completely nondenominational format? Wouldn’t it be nice if my Squeezebox server would have those same playlists available? And wouldn’t it be spectacular if those playlists would magically appear on a network drive whenever the lists change in iTunes?
Read on for details on how I accomplished this and to download the free utility I wrote to handle this task.
The Problem To Be Solved
In order to understand what this application does, you need to know what I was trying to accomplish.
I have a NAS drive on my network that contains my Master Library of mp3 files. The files on this drive are located under /media/music.
I have a Squeezebox server, running on an Ubuntu machine. This server is used by Squeezebox devices to play music anywhere in my house. It holds a copy of the Master Library, located under /srv/squeezebox/music
What I want: I want my Mac to magically push proper m3u playlists to the Squeezebox server—the Squeezebox server understands m3u playlists.
What I don’t want: Squeezebox supports direct access to iTunes. But I don’t want to do this because I don’t want to have to run Squeezebox on my Mac. Why did I bother setting up a dedicated server if I have to keep my Mac running?
Why is this challenging: Even if I could point Squeezebox to the bare iTunes database file, all of the file paths are wrong. My master library might have a song at …/artist/album_name/disc 1/, while iTunes might put it at …/Artist/Album Name/, omitting the disc 1 folder and reformatting names.
I wrote a small command line application in Perl that supports the following:
- Paths to songs in Apple’s mysterious black box are converted to nice paths to the same songs in my golden Master Library.
- Even if a song name changes or a folder path changes, the original master copy is found.
- All playlists are generated in m3u format.
- Smart playlists and Genius playlists are supported.
- The generated playlists are automatically moved to either a local directory or a remote server, using scp.
- Network shares are automatically mounted at beginning of process and unmounted at end of process.
- You can provide a file path to be prepended to all playlist entries.
- Exits early if the iTunes library has not changed since the last run.
- Supports exclusion patterns in order to skip some playlists.
- A local Squeezebox server can be automatically pinged to cause it to refresh playlists.
Here is the full documentation for the Playlist Mapper application.
Please note that this is a command line program. Some day I might figure out how to make a pretty GUI installer for it, but for now you have to get your hands a little dirty in order to install and configure.
Download the application here: plmapper
This is a Perl script that uses many standard utilities already present in a Snow Leopard OS X installation. You should not need anything other than the plmapper file itself.
Unzip the file and place plmapper in your home directory.
Open a Terminal window and make the script executable:
chmod u+x plmapper
Read the man page for the application by doing this:
There are many command line arguments, but you don’t need to worry about most of them. Create a file called plmapper.config in your home directory and put any arguments you need in that file, as name-value pairs.
itunes=/Users/Bozo/Music/iTunes Music Library.xml
Once you have added all of the configuration settings, go ahead and run it:
You should see plenty of status information go by as each playlist is processed.
Making it Run Automatically
0 22 * * * /Users/Me/bin/plmapper >/Users/Me/plmapper.log 2>&1
This causes the plmapper program to run once daily at 10pm, logging output to a file called plmapper.log in my home directory.
Of course, this can be tweaked to taste; it doesn’t matter if you run it hourly since the app skips any heavy lifting once it sees that the iTunes library file hasn’t been touched.
How It Works
The application performs the following basic steps:
- Mounts network shares using mount_smbfs.
- All music files in the external non-iTunes Master Library are listed in an internal data structure, sorted by file size.
This allows us to quickly find a “short list” of possible candidate files that match a given source file. This works because mp3 files have fairly random sizes.
- The iTunes database XML file is processed using an XSLT transformation to generate a set of basic m3u playlist files. The xsltproc command line utility is used to run the transformation.
- All paths in the playlists are converted from escaped URI syntax (e.g. %20 for space) to regular UTF-8 characters.
- Each path is resolved to a single music file (i.e. an mp3 file) in the Master Library.
This is done by obtaining the size of the iTunes version of the file and then looking this up in the internal list created in the first step.
- Once a short list of candidates is found, the first few thousand bytes of each file are compared until a match is found.The risks of choosing the wrong file are low: all that will happen is that a song might be switched in the playlist accidentally. As such, it isn’t worth scanning the full file to ensure they are exact matches.This algorithm works quite well, and can detect music files that have been renamed and moved around.
- The playlist files are now converted from utf8mac to utf8 using the iconv command line utility.This process collapses wide UTF-8 characters, consisting of a letter plus an accent add-on, into their single-letter equivalents. This process is known as Unicode Normalization, and this tool uses Normalization form C: Compatibility decompisitiion followed by canonical composition.
- Playlist files are now copied to a local or remote directory, either as direct file copy or via the scp utility.
- Optionally, a special call is made to a specified Squeezebox server to tell the server to refresh all playlists.
- Any mounted shares that were mounted by this process are unmounted via diskutil unmount.
- Nested folders of playlists currently act funny. The lists will come over, but you may get two lists. You can use the exclude option to prevent this.
- Songs with non-ASCII characters in the file name might not be recognized by all players. Squeezebox has a problem with many special characters—I tested this by adding songs like Águas de Março.mp3 using Squeezebox’s own playlist editor, and when I reloaded the list the songs were not there. This is a bug in Squeezebox server.
- Occasionally the file matching algorithm might pick the wrong song. In an effort to speed up processing, the program only looks at the first few thousand bytes of files when comparing. It isn’t a big deal if the wrong file is added to a playlist, is it?
- You might see a message that says that the network share is already mounted followed by an error that says that the music library path cannot be found. This may be the result of an empty mount-point directory (e.g. /Volumes/mymusic) left when the device was last mounted or if mounting failed. It is not uncommon in Unix environments to leave mount points hanging around unmounted, but OS X usually doesn’t leave them this way—when you unmount a network drive in OS X, the mount point directory disappears. This orphaned mount point directory will cause plmapper to think the share is mounted when it isn’t. Just remove the empty mount point directory.
As often happens, this program was written because I had an itch that needed to be scratched. Now that I went through all of the hassles, I hope others can benefit.
Through good fortune, I am working in a Macintosh environment. This means that all of the important tools were already present on my machine: perl, xsltproc; mount; iconv; scp; nc; and others. If I were writing this for a PC, I probably would have written the whole thing in Java—a more familiar language to me, but one that comes with its own configuration issues.
I plan on updating plmapper over time, and if anyone has suggestions, please let me know.
And if a Perl guru wants to tell me my Perl skillz are subpar, go right ahead—but be gentle, and let me know how to improve the app.
Fixed a couple of bugs related to path and “qx” calls, thanks to Chris. Updated version here.
It has been quite a long time since I last looked at this. As things turned out, my Squeezebox Server died an untimely death and that sort of put the brakes on my central music library project.
A couple of weeks ago I located a spare PC and set up a new Squeezebox Server, so I’m back in business.
Some things I have noticed:
- Squeezebox Server is now called Logitech Media Server. Keep that in mind when you are looking for an installer. I was following instructions on how to install Squeezebox Server on Ubuntu and I had to change the apt-get command from sudo apt-get install squeezeboxserver to sudo apt-get install logitechmediaserver
- Apparently they have changed from using MySQL to using SQLite. This made the install even easier—there was no need for me to mess around with creation or configuration of the MySQL user or database.
- The default server port has changed from 9090 to 9000.
- They still haven’t fixed the bug with international characters in song titles in playlists.
That said, the plmapper script worked just fine with my new Squeezebox even on Lion. Hope it works for everyone else.