iTunes Scripting Seizure

December 5th, 2006

I love iTunes, but it has a number of rough edges that leave me constantly praying that a major revision will come along one day soon. Most of my complaints have to do with it being simultaneously the “only way to manage music and podcasts on the Mac” and yet being frustratingly feature-incomplete in some important ways. For instance, it does a great job of downloading my podcasts, but neglects to put them on my iPod until I either unplug and replug it, or else manually select “Sync.” Inevitably, I end up thinking that since iTunes and my iPod have been making out all weekend, surely those new podcasts are on the iPod. It’s not until I’m at the gym with nothing to listen to that I realize I’ve been sync-jacked!

But that’s a complaint for another time. Today I’d like to highlight an infuriating behavior that iTunes has, of blocking the processing of all incoming AppleEvents while its preferences dialog is being displayed. What does this mean in most practical terms? iTunes can’t respond to AppleScript while the Preferences window is open. So if you run some script that asks for the name of the current track, for instance, it will hang and give the running app a spinning beachball while you wonder what the heck is going on. Finally you switch to iTunes and realize that you were fiddling with preferences yesterday when you got distracted and switched to another application. Close the dialog, and life goes on as usual.

This is bad enough when it’s inflicted on yourself as the script author and user, but it’s worse when your script is either shared with other users, or included as part of the functional infrastructure for an application. With iTunes integration popping up everywhere, it stands to reason that any developer who uses AppleScript to achieve the integration runs the risk of answering support call from users who have run into this iTunes freeze-out behavior.

The solution? Apple should fix iTunes so it doesn’t freeze-out AppleEvent processing while displaying the Preferences dialog.

The solution for people who live in the real world? We have a few techniques to choose from.

Time Out Gracefully

The first is to use AppleScript’s “with timeout” clause to seriously shorten the length of time it will hang out waiting for iTunes to wake up. We can pick a relatively short period of time in seconds that still constitutes an eternity in scripting time:

try
	with timeout of 2 seconds
		activate application "iTunes"
	end timeout
on error
	display dialog "iTunes is Frozen, try closing the Preferences window!"
end try

Go ahead, try it with the iTunes Preferences window open. This eliminates the outright freeze that users would experience otherwise.

But it feels risky to estimate with confidence the precise number of seconds that is “long enough, but not too long.” Maybe the user just has a really slow Mac, or something unusual happens to slow things down one out of ten times. For many iTunes scripting purposes, activating iTunes and bringing it to the front is part of the procedure. If iTunes is frontmost, then the user will see that the Preferences dialog is open and (hopefully) intuit that they must dismiss the dialog to let the scripted action carry on. The problem is, merely activating iTunes with AppleScript requires that it respond to AppleEvents! As the example script above shows, we can’t even bring it forward when it’s frozen. Or can we?

Blame It On iTunes

We know the user can bring it forward, so how do we simulate that from a script? If we keep iTunes itself out of the scripting loop, we can enlist the services of the system to change the frontmost application:

tell application "System Events"
	set frontmost of application process "iTunes" to true
end tell

Try this script with iTunes Preferences open and you’ll see that it zips to the fore, regardless of the frozen state. By putting this script command first in your iTunes-activating script, you can ensure that users will at least be confronted by the offending Preferences window, instead of staring at a spinning beachball in your application.

Not Give A Damn

Finally, we have the option of sort of throwing our scripting requests out to the world with little regard for their success or failure. For programmer types you can think of this as roughly equivalent to weak-linking a particular system API. If something neat can be done, fine we want it. Otherwise, we’ll keep running business as usual. The “ignoring application responses” clause tells AppleScript to send events but to disregard responses. For instance, the following script asks iTunes to skip to the next track, but shed no tears if that can’t be done right this second:

ignoring application responses
	tell application "iTunes" to next track
end ignoring

The big negative here of course is the script gives no feedback to the user about the success or failure of the intended action. It also silently queues up an action that might disturb the user later. For instance, when she switches to iTunes and closes the Preferences dialog, suddenly her favorite song gets skipped over.

In Closing

As I said, the solution here is for iTunes to grow up and be a real 21st Century application. At least in terms of modelessness. But for anybody trying to work around the failings of iTunes or other event-blocking applications, I hope these tips will come in handy.

6 Responses to “iTunes Scripting Seizure”

  1. Brennan Young Says:

    I dunno why everyone seems so enamoured of the iTunes scripting implementation in the first place. It implements a good half-dozen cardinal ‘sins’ (at least according to Apple technote 2106).

    http://developer.apple.com/technotes/tn2002/tn2106.html

    Which states very clearly, “If a term consists of more than one word, separate the words with spaces. Do not join the words together with capital letters or underscores.”

    It also says “If a property or parameter refers to an object, its type should be an actual object, never data that signifies an object.” It then goes onto give the example of a ‘bad’ command, ‘closeWindow’ and suggests instead using the ‘close’ command on a properly modelled ‘window’ object. So far so good.

    Then I look in the iTunes dictionary and I see ‘updatePodcast’ and ‘updateAllPodcasts’. WTF? What about having a ‘podcast’ object, and an ‘update’ command instead?

    Hardly any of the iTunes preferences are available to the dictionary. It would be very useful to set those, for example to specify what format the ‘convert’ command is going to create. (Better still, ‘convert’ should have optional parameters for compression/encoding settings).

    And why can’t you use the filter reference form? e.g. tracks whose name contains “blah” fails.

    And why are ‘smart playlists’ not modelled properly?

    And what about this occult use of the word ‘view’ – which is usually what we might call a playlist. Not a very informative name for something which you’ll be scripting often. ‘view of browser window 1′ might be usefully referred to as ‘frontmost playlist’ and save a lot of hair pulling.

    And why can’t I find out whether iTunes is busy burning a disc so I can (for example) wait before quitting it. I have a script which quits iTunes if it is running in a background account, when launched from the foreground account. It would be nice to know that I could avoid screwing up a disc burning operation under those circumstances.

    Really, disc-burning needs to have an object model, properties like burn state, percent complete, a reference to the playlist getting burned, which drive is getting used – I have two burners in my Mac – and so on. The same goes for encoding/compression. We need to know what state iTunes is in. This is related to the whole ‘modal prefs window’ issue, I think. It’s just sloppy.

    The iTunes scripting implementation needs a lot of work, and we neeed to demand that it happens. Apple is paying lip-service to AppleScript in too many areas.

    Well at least iTunes has a scripting implementation, which is more than can be said for Apple’s ‘professional’ ($$$) apps.

  2. Cameron Hayne Says:

    In my experiments, the following AppleScript serves to close the iTunes preferences if it is open. If only the main iTunes window is open, it does nothing – but there might be other effects that I haven’t noticed.

    tell application “System Events”
    set frontmost of application process “iTunes” to true
    key code 53
    end tell

  3. Daniel Jalkut Says:

    Brennan: I agree that iTunes’s scripting support is frustratingly inadequate. The “updatePodcast” and “updateAllPodcasts” items are particularly bad.

    Cameron: Good idea, but one major caveat with synthesizing keystrokes like that is that you fall victim to combining with whatever keys the user may already be pressing. For instance, it’s quite common with FastScripts (and other script runners) to attach a script to a keyboard shortcut. What happens when I attach a shortcut to the script with the Cmd key? I end up getting Front Row (cmd-esc). When I attach a shortcut including Cmd-Opt, the script brings up the force-quit dialog.

  4. Rich Pollock Says:

    iTunes scripting is highly frustrating. I think Brennan seems to have covered everything rather comprehensively, but it’s the lack of a “playlist” object that grates most for me, especially in terms of script “understandability”.

    And this article really does highlight the stupid decision of having a modal preferences dialog in the first place. Why? Just why?

  5. Pierre Igot Says:

    I suspect the fact that the Preferences dialog is modal is because it’s always been so :). iTunes is an “old” application (even iTunes 1.0 was a revamp of an already existing application) and Apple simply have never bothered to “update” that aspect of the application.

    I suspect it is the same reason why the track information dialog box too is a modal dialog. I find this even more irritating than the modal Preferences dialog. I certainly invoke the track information dialog box far more often than the Preferences dialog (although I am constantly forced to travel to Prefs for changes in encoding settings, which is really not appropriate either). There are some many tracks out there with improper tags, and even the stuff from the CDDB needs to be corrected all the time… Each time you have to go through that modal dialog. Painful!

    The problem with the modal track information dialog is that Apple has kept adding stuff to it over the years, so there really is a lot of information in there right now. They are also using these “Next” and “Previous” buttons within the dialog box that actually enable you to change tracks without exiting the modal dialog, but it’s a clumsy workaround for a very real shortcoming.

    I really feel that iTunes should have a track information drawer or inspector. But that would require a major UI revamp, and somehow I don’t think Apple is going to do this any time soon.

  6. jakattak Says:

    It’s taken days to locate something I didn’t even know the name of until I linked here. I’m a recording artist still mostly crawling around in the analog world. I cannot seem to attach a proper “TAG” to my original songs so they will be recognized and ‘picked up’ by Gracenote online. Now I understand it has something to do with ‘scripting’ and ‘encoding’ TAGS on my song wave files. If anyone has any other info or links concerninf this dilemma go ahead and drop me an email: I could not find anything addressing this issue at studio central.
    bye for now……………jak

Comments are closed.

Follow the Conversation

Stay up-to-date by subscribing to the Comments RSS Feed for this entry.