One of the nice things about
Mac OS X is that you can interact with many of the applications using external scripts. The main issue is what scripting language you use to write your scripts in. The obvious choice is, of course,
AppleScript, but while it makes it easy to interact with the applications it isn't as functional at text or date manipulation as a traditional scripting language, such as
Perl.
A few years ago I was pleased to find there was a
Perl module available called
Mac::Glue that would let you talk to applications in
OS X without having to use
AppleScript. I had downloaded the
AppleScript guide from
Apple and had tried to use it, honest. But having used
Perl nearly every waking hour over the previous 7 years I had a fair amount of expertise locked up in
Perl and in a short time, with the help of
Mac::Glue, I was able to knock up a quick script to help me organise my
iPhoto library, and later I added scripts that I used with other applications.
Perl, however, is not an officially supported scripting language for
OS X, and in
OS X 10.5 both Ruby and Python were supported by Apple for scripting OS X. I decided that
Ruby was the cooler of the two languages to use as it's a bit like
Perl rewritten by a
Smalltalk geek (that and I have always had a reservation about
Python's use of syntactic whitespace), so in 2008 I dabbled a bit by rewriting my
iPhoto script in
Ruby using
RubyOSA and was pleasantly suprised to find that it ran quite a lot faster.
That was all fine and dandy, and I transitioned from
OS X 10.4 on my
PowerBook G4 to
OS X 10.5 on my
MacBook without a glitch. Until
Apple released
OS X 10.5.7, at which point my
RubyOSA scripts stopped working, so I went back to using
Perl and
Mac::Glue.
Recently I have wanted to export playlists from
iTunes to the memory stick from my phone (or sometimes to a USB stick or just to a directory), something that
iTunes doesn't seem that keen on (unless optical media is involved). And I have also been looking for a suitable programming language for my 10 year old nephew (who has just got a netbook for his birthday - Hi, Matthew!) to learn. So, bolstered by a comment on
Slashdot that had mentioned it only takes a couple of hours to learn, I put away my irrational dislike of
Python and decided to give it a go. And sure enough I was able to knock up a script, very straightforwardly, that did exactly what I wanted.
If you're a UNIX command line geek and you'd like to give it a go you can download from the link below. Obviously you'll need the
Python appscript library for it to work.
The script currently supports the following actions:
- list-playlists [<pattern>]
This lists the playlists in iTunes (that optionally match the specified pattern). The playlists listed include the names of the enclosing folders, and are prefixed by an integer index for easy reference (especially useful if you have multiple playlists with the same name). Also displayed is a track count, the duration of the playlist and the cumulative size of the files in the playlist.
- export-playlist <playlist> [<dir>]
This exports media from the specified playlist to specified directory (or the current directory if none is specified). You can specify the playlist either as the playlist name (along with enclosing folders) as, or the playlist index, both of which are printed out by list-playlists. The directory will be created, if it doesn't exist. The filenames for the exported media are generated from the track numbers in the playlist, along with the track name, and have punctuation and spaces removed or translated to make them more friendly.
- export-current-playlist [<dir>]
If you are currently listening to something in iTunes this will export the current playlist to the specified directory (or the current directory if none is specified).
- help
List the available actions, along with brief descriptions.
So you can use it like this:
% itunes list-playlists never
[282] CDs > Nirvana > Nevermind (12trk 42m31s 61.4MB)
[547] Compilations > 16. Never Give In (2008) (28trk 1h33m15s 127.4MB)
% itunes export-playlist 547 /Volumes/JIM\'S\ W380I/music/compilations/never_give_in
Exporting: "Compilations > 16. Never Give In (2008)" -> /Volumes/JIM'S W380I/music/compilations/never_give_in
Creating directory: /Volumes/JIM'S W380I/music/compilations/never_give_in
[ 1] "Changed Daily" -> 01-changed_daily.mp3
[ 2] "It's A Fine Day" -> 02-its_a_fine_day.mp3
[ 3] "Road To Nowhere" -> 03-road_to_nowhere.mp3
[ 4] "To Get Down" -> 04-to_get_down.mp3
[ 5] "Teenage Dirtbag" -> 05-teenage_dirtbag.mp3
[ 6] "Gay Bar" -> 06-gay_bar.mp3
[ 7] "Voodoo Child" -> 07-voodoo_child.mp3
[ 8] "Games Without Frontiers" -> 08-games_without_frontiers.mp3
[ 9] "Overload (Original Edit)" -> 09-overload.mp3
[10] "Best Of You" -> 10-best_of_you.mp3
[11] "19-2000 (Soulchild Remix)" -> 11-19-2000.mp3
[12] "Come On Home" -> 12-come_on_home.mp3
[13] "National Express" -> 13-national_express.mp3
[14] "Some Girls" -> 14-some_girls.mp3
[15] "Turning Japanese" -> 15-turning_japanese.mp3
[16] "All The Small Things" -> 16-all_the_small_things.mp3
[17] "Flagpole Sitta" -> 17-flagpole_sitta.mp3
[18] "Sk8er Boi" -> 18-sk8er_boi.mp3
[19] "Get Over It" -> 19-get_over_it.mp3
[20] "Thrillseeker" -> 20-thrillseeker.mp3
[21] "Single Girl" -> 21-single_girl.mp3
[22] "Sale Of The Century" -> 22-sale_of_the_century.mp3
[23] "P.V.C." -> 23-pvc.mp3
[24] "Take Me Out" -> 24-take_me_out.mp3
[25] "Scream" -> 25-scream.mp3
[26] "Underwater Love" -> 26-underwater_love.mp3
[27] "Green Bird" -> 27-green_bird.mp3
[28] "Changed Pandimensionally" -> 28-changed_pandimensionally.mp3
Note that I have a symlink to
itunes from
itunes.py, so I can point the
itunes command to whichever implementation of the script is currently in favour.
If you don't like the " > " separator used to indicate playlist folders you can change the
SEP variable in the script to whatever you prefer.
One day I may learn to do GUI scripting in
OS X and put an interface on to it.
The only problem I did have was with
Unicode characters. Although my terminal is set to use
UTF-8 and the
$LANG variable is set accordingly,
Python kept blowing up when it encountered playlists or folders with non-ASCII characters in. So I did a bit of jiggery-pokery in the script that seemed to sort it out for me. When I am more familiar with
Python I may come up with a better solution.
Feel free to use this script, and also to pass any comments on to me, although it works for me as I intended so I'm unlikely to put a great deal of effort into maintenance. Bear in mind it is my first Python script (and I happen to like 2 space indents). I'm hoping that it will continue to work when
OS X 10.6 (Snow Leopard) is released in September (and even
OS X 10.5.8 which is likely to come even sooner).