iTunesQ - Query your iTunes in GeekTool

iTunes logo
  1. Introduction
  2. Download
  3. Installation
  4. Usage
  5. Source Code

iTunesQ shows what's currently playing inside Apple's iTunes.
iTunesQ works on Mac OS X - 64 bit - Snow Leopard, Lion 10.7.4 with iTunes 10.6.3 or greater only! (Other permutations may or may not work!)

It's a simple command line utility meant to do one job: show you what's playing. A useful way to show what's playing is GeekTool.

My reasons for writing this utility were these:

  1. I no longer had a way to query the iTunes state via a decent scripting language.
  2. Ruby rb-appscript wasn't working since Apple upgraded iTunes to 10.6.3 and no new version of this was forthcoming. If you are interested to find out why, then please see this article.
  3. I severely dislike AppleScript.
  4. I wanted to mildly wet my appetite with Objective-C.

Download Links

Download iTunesQ: iTunesQ_1.2.tgz or iTunesQ_1.2.zip (around 7 kiB).

Installation

Unzip or untar the downloaded file, then copy the included iTunesQ program into your path (or adjust the path to suit your taste when you run the program.)

This program is meant to be scripted, so you can do various nifty things in your own programs. For example I use this program through a script called from GeekTool to update the currently playing track and artwork on my desktop.

Usage

Usage is simple:

    iTunesQ -help

This command should show some brief usage information. Note that if you installed it somewhere not in your PATH, then you'd need to provide the path to iTunesQ eg. ~/Applications/iTunesQ/iTunesQ if you installed iTunesQ into your home directory's Application folder.

    iTunesQ

The above command may display something like this:

    state=playing
    artist=Leonard Bernstein: Bavarian Radio Symphony Orchestra, London Symphony Orchestra
    album=Ode To Freedom - Beethoven: Symphony #9
    name=Beethoven: Symphony #9 In D Minor, Op. 125, "Choral" - 1. Allegro Ma Non Troppo
    trackno=1
    duration=1086

Or when run as:

    iTunesQ -xml

Then this may be the output:

    <?xml version="1.0" encoding="UTF-8"?>
    <itunes>
        <state>playing</state>
        <artist>Leonard Bernstein: Bavarian Radio Symphony Orchestra, London Symphony Orchestra</artist>
        <album>Ode To Freedom - Beethoven: Symphony #9</album>
        <name>Beethoven: Symphony #9 In D Minor, Op. 125, "Choral" - 1. Allegro Ma Non Troppo</name>
        <trackno>1</trackno>
        <duration>1086</duration>
    </itunes>

This output may be suitable for direct GeekTool usage:

    iTunesQ -nice
>>>>>> playing <<<<<<
Leonard Bernstein: Bavarian Radio Symphony Orchestra, London Symphony Orchestra
Ode To Freedom - Beethoven: Symphony #9
[1] Beethoven: Symphony #9 In D Minor, Op. 125, "Choral" - 1. Allegro Ma Non Troppo (18:06)

iTunesQ will also save album art work for the currently playing track (if available.)

To export the image, please provide the -albumimgfile argument to the utility:

    iTunesQ -albumimgfile /tmp/itunes_art.png -noalbumimgfile ~/Pictures/blank.png

The file /tmp/art.png will then contain the artwork image, if available and otherwise will be a copy of the blank.png file (this file can be any PNG file, a blank.png image is included and works well for GeekTool.) Of course, you may use an "Album art not available" image of your own design if you prefer.

    state=playing
    artist=Leonard Bernstein: Bavarian Radio Symphony Orchestra, London Symphony Orchestra
    album=Ode To Freedom - Beethoven: Symphony #9
    name=Beethoven: Symphony #9 In D Minor, Op. 125, "Choral" - 1. Allegro Ma Non Troppo
    trackno=1
    duration=1086
    albumimg=/tmp/art.png

If the output includes the "albumimg=" line (or XML <albumimg> element) then the image was saved to /tmp/art.png. Otherwise the image was not available.

Source Code

The utility is roughly centered around this bit of Objective-C code to extract information from iTunes.

NSString *fname = @"/tmp/art.png";

iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
if (iTunes != nil && [iTunes isRunning] ) {
    iTunesEPlS state = [iTunes playerState];
    if (state == iTunesEPlSStopped)
        show_nstr("state", @"stopped");
    else if (state == iTunesEPlSPaused)
        show_nstr("state", @"paused");
    else
        show_nstr("state", @"playing");
    show_nstr("artist", [[iTunes currentTrack] artist]);
    show_nstr("album", [[iTunes currentTrack] album]);
    show_nstr("name", [[iTunes currentTrack] name]);
    show_int("trackno", (int) [[iTunes currentTrack] trackNumber]);
    show_int("duration", (int) ([[iTunes currentTrack] duration] + .5));
    SBElementArray *artwork = [[iTunes currentTrack] artworks];
    if (artwork != nil && [artwork count] > 0) {
        iTunesArtwork *item = [artwork objectAtIndex: 0];
        NSImage *img = [[NSImage alloc] initWithData:[item rawData]];
        if (img != nil && [[img represensations] size] > 0) {
            NSBitmapImageRep *imgRep = [[img representations] objectAtIndex: 0];
            NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
            [data writeToFile: fname atomically: NO];
            show_nstr("albumimg", fname);
        }
    }
} else {
    show_nstr("state", @"stopped");
}