Notifications

Monday, 2006-09-25; 01:50:00

A problem with iTunes notifications, and a question on how to generate new comment e-mails

I've mentioned TuneTagger on a few occasions. (If you're wondering about it, here's the latest entry regarding the app.) With iTunes 7, part of its functionality became kind of moot, since iTunes automatically downloads high-quality artwork. It still doesn't, however, get correct ID3 tags which is part of what TuneTagger does. Lyrics is another example where TuneTagger helps a lot -- I really wish that Apple would conquer both of these problems with music libraries as well.

I have a fundamental problem with TuneTagger, though: since part of the functionality that I've built into it displays lyrics based on the player position within the currently playing song, I have to poll iTunes fairly frequently in order to get the player position. The default right now is 5 seconds. But the only way to poll the player position is through AppleScript, which not only is extremely slow, but causes many problems.

First of all, sometimes an AppleScript can take longer than 5 seconds to respond. In that case, executing another AppleScript through Cocoa using an NSAppleScript causes the program to crash, IIRC. It's been a while since I dealt with this problem, but my solution was to sub-class NSAppleScript and implement a method called safelyExecuteAndReturnErrorUsingDict:ignorable: . When an the execution of an EPAppleScript object is requested, this method checks a global variable to see if an AppleScript is already running; if there is, it does one of two things based upon the ignorable flag. If ignorable is set to YES, then the EPAppleScript object is simply discarded without the AppleScript being executed. If ignorable is set to NO, then the EPAppleScript object simply delays itself from being executed until the currently running EPAppleScript object terminates. EPAppleScript objects also, obviously, set the global variable for whether an EPAppleScript object is running.

This seems to be a pretty good solution, but polling iTunes via AppleScript has other problems. First of all, it causes iTunes to stall when the AppleScript is being executed. So every 5 seconds, iTunes stalls for a second or two. When you're trying to do something in iTunes, obviously this is not nice. AppleScript execution can also be temporarily put on hold by the most rudimentary things -- like, for example, having a song info window open. This causes an AppleScript that calls iTunes to hang until the song info window is closed. Arg.

I was hoping that iTunes 4.7.1 held the answer to the problem. Since version 4.7.1, iTunes pushes out notifications so that apps like TuneTagger don't have to poll iTunes to see when the song changes or when the user pauses or re-initiates playback. You can inspect these notifications by downloading Notification Watcher from TildeSoft.

iTunes notifications include, as far as I can tell, all of the ID3 tag info right in the notification, including (but probably not limited to) the grouping, track name, disc number, genre, album artist, total song time, year, track number, album, rating, track count, artist, and disc count. Also included with the notification is the player state (i.e.: "playing", "paused", etc.), an iTunes Store URL for the song, and the location of the song file on the hard drive.

Conspicuously absent from these notifications is the player position. It would actually be kind of pointless to include this information in the current notifications, because notifications are only sent on a change of player state, or when the song changes. If you simply skip forward or back in the same song -- by using the progress bar or the fast-forward and rewind buttons -- no iTunes notification is generated.

So, unfortunately, these iTunes notifications are pretty much useless in getting around the main problem that I have with iTunes polling in TuneTagger. The notifications aren't entirely useless, because it does eliminate the need to get the ID3 tag information on song change; it just doesn't help for automatic lyrics scrolling which requires the precise track location at any given point in time. If iTunes generated notifications when the user artificially changes the track location, that would be enough -- TuneTagger could use its own timer to figure out where in the song you are, and only update that information when unexpected changes occur due to the user changing the position.

Does anybody have any ideas on how I would figure out when the user jumps around in a song? Is there any way to monitor specific button presses in a certain application? I suppose I could write an InputManager that would inject itself into iTunes and generate notifications when I need them, but how would I go about creating one, and figuring out which methods I would need to override? I suppose a bug report might also help, but I don't particularly want to wait until Apple decides if/when to implement my suggestion into iTunes.

[UPDATE: Since I skipped this past Friday for ABFs, I decided to submit this enhancement request to Apple as bug LXIII. One can hope for iTunes 7.0.1. Filed: 4748144.]

And while I'm at it, I may as well ask another question. Since activating .mac comments, I'm getting tired of monitoring the most recent entries for new comments. Does anyone know how to send e-mails via JavaScript (without requiring the user to manually send an e-mail)? If it's not directly possible, I could set up some sort of listener on my computer at work -- that's always on -- which would then send myself an e-mail if it hears a "new comment" message. But I'm not sure how to go about this. (It seems this would probably be a good addition to Dot Comments, once I figure out a reasonable way to solve this problem.)