¶ iTunes customization · 14 April 2005 fiction/tech
Before Tiger renders some large amount of it obsolete, I want to make some notes about my customized iTunes configuration. The actual Applescript code is too obscure and specific to be very enlightening, but possibly a brief description of the overall flow would be of interest to others.
First some notes about use. At this point iTunes controls virtually all of my music listening. The bulk of my music is still acquired by purchasing physical CDs, but these are ripped into iTunes immediately (AAC, 128kbps). At home our main stereo is hooked to an Airport Express so both B and I can beam music to it from our Powerbooks. We both also have small speakers on our desks, and there's another set by the bed that we can plug iPods into when we want. I still do use the CD changer in my car, but both of us also use our iPods in our cars, and I use either the Powerbook or the iPod at work.
My music collection is far larger than my Powerbook or iPod can accommodate, so my encoded selection rotates as new and revived interests push other things out of the active 20GB. Much of the time I use iTunes in Browse mode, listening to individual whole albums in the same way I would have pre-shuffle-era. But increasingly, and especially during periods when my listening isn't so dominated by new releases, I also use iTunes' Party Shuffle mode, fed by a Smart Playlist that filters out non-music genres, cuts out tracks that are too short (<1:30) or too long (>5:22) for my shuffle attention-span, and via another playlist reference excludes anything that has been played recently (i.e., in the last two weeks, or the last 10 hours of music, whichever list is shorter). If I'm in an especially random mood, I have an Applescript that goes through the upcoming Party Shuffle selections and eliminates repetition of artists.
Organizationally, I normalize all incoming music to one of four genre tags: J-Pop, Metal, Noise and Rock, where "Rock" means simply "everything else". For sorting purposes I flip all artist names to "Last, First" and delete leading "The"s. Sound Check, Sound Enhancer and Crossfade Playback are all off. I show the little arrow links, but have tweaked the preference file so that they search within my library first, instead of jumping to the iTMS.
I use Synergy heavily. The Play/Pause button sits alone in my menu bar, but I have keyboard shortcuts for Previous, Play/Pause, Next, Volume Up and Volume Down, and I like Synergy's own Floater better than the version it produces through Growl. The rest of my customization is run by an Applescript triggered by Synergy as a Track Change Item.
The script in turn does several things:
1. Updates my IM status message to include the track info for whatever is playing.
2. Uploads the track info and artwork for the current track to this website, with the proper HTML encoding for Unicode characters.
3. Maintains a single-track playlist called "last started" which contains the most recent track that iTunes began playing.
4. Checks, any time iTunes switches to the "stopped" state, to see if the track in "last started" is the same as the last track in "Recently Played" (which iTunes adds tracks to when they finish), and if so, if that track falls in the middle of an album. If all these things are true, the script restarts playback on the next track of that album. This is a complicated but fairly effective way of compensating for iTunes' predilection to lose track of what it was playing if you're poking around in your Library or the iTMS while you're listening to something else. The began/finished double-check is necessary to prevent this part of the script from effectively disabling the Stop button entirely, which my first iteration of it did.
5. Automatically updates the rating for the track. Although on very rare occassions I do rate tracks manually, for the most part I find that it is more effective to treat the rating as a temporary variable representing my actual behavior towards the track, instead of an attempt to measure my subjective assessment directly. In my case, the rules are approximately these (I've left out some of the more logistical obscurities):
a. New songs enter the system rated 0, which means simply "unplayed".
b. If a song plays all the way through, and it is currently rated 0 or 1, its rating is increased to 2.
c. If a song is played again while it is still on the Recently Played playlist (which with my Party Shuffle configuration would only happen through my deliberate action), its rating is increased. It takes only one repetition to promote a track from 2 to 3, but two to go from 3 to 4, and three to go from 4 to 5. So 5, my highest rating, means that I've played the song all the way through at least seven times in relatively close succession.
d. If a song plays for at least :03, but less than half its length, its rating is decreased by 1. It takes only one skip to demote a track from 5 to 4, 4 to 3 or 3 to 2, but two to go from 2 to 1. Since promotion goes from 0 directly to 2, the rating 1 is reached only by demotion, which allows it to serve as an unambiguous indicator of disfavor.
e. If a set of songs from an album plays all the way through in order, and then the subsequent track on the album starts but doesn't finish, and nothing else from that album is played, I am considered to have skipped all the unplayed songs on the album (where "unplayed" means they don't occur in the previous or next 10 entries in the track history, to catch the case where I interrupt an album but return to it). This rule is screwed up if I single out the last song on the album, since there's no subsequent track to check for, so I try not to do that.
f. At the end of a calendar month, any song with a rating of 3 or lower that hasn't been played since the previous calendar month has its rating decreased by 1, and any track whose rating would be reduced to 0 by this is left at 1 but added to a "to be deleted" playlist, which at the moment I still review manually. The missing detail here, obviously, is that I need to keep track of both a track's current rating and its historical maximum. A track that never got above 3 can be deleted when it gets back to 0, but a track that was ever rated 4 or higher should be down-converted to a lower bitrate encoding instead of being deleted entirely. Hopefully the new Automator framework in Tiger will expose programmatic control of encoder parameters, which the Applescript interface to iTunes 4.7.1 does not.
6. Feeds the track's first two artworks (on the assumption that these are the front and back cover) via ImageEngine to Manatics' Handler plug-in, set at 15%, which applies a mostly transparent mask of my scanned-fingerprints to simulate package wear. The script skips this step if the track or its album are repeated without any non-album tracks intervening, figuring that in physical use this would have meant I didn't need to touch the LP sleeve or CD case.
7. Checks the Comment section for the track, which I maintain in a semi-structured format, for my private rights coding. Any track marked "Bought" came from a legally purchased CD or download, and so requires no further compensation to be issued. A track marked "Preview" is one I have acquired without the artist being compensated, but which only exists temporarily in my library while I decide whether to purchase it. By default no compensation is issued for these tracks during the first week after they are added to the library. Each time one is played more than a week after download, the script asks whether to convert their status to "Honor". Tracks marked "Honor" are ones for which I owe the artist separate compensation from any involved in acquiring the data itself.
For handling the bookkeeping of this separate compensation, the script (actually a combination of Applescript and perl/MySQL) maintains an external database of compensatable artists. By default each full album is worth $4, and individual non-album tracks are worth $0.20 (the system provides support for different values per-album and per-track, and for different system defaults based on acquisition date, but at the moment I'm not actually using those features). I prorate these amounts over the first four times I play the material, so if I play a whole album once, but only once, my accounting considers the artist to be owed only 1/4 of the value, currently $1. The database keeps track of the total amount I owe each artist, the amount they have been paid already, and the amount that has been transferred into a compensation escrow account.
For artists who accept electronic payment via Paypal or credit cards, the database records the relevant payment info. A separate nightly perl script issues electronic payments (via CapitolOne's excellent web-services "micropayment" (sic) interface) where possible (batched until the amount exceeds $1.75), and for artists without electronic payment info, totals the corresponding amounts and transfers the overall total to the money-market escrow account I have for this purpose. The escrow account isn't automated yet, but I usually kludge around this, when I get new payment info for an artist, by simply moving the money back out of escrow, resetting the amount paid/escrowed to $0, and rerunning the original script. At the end of each month I mail physical checks to artists for whom I have physical addresses but not electronic, and rebalance the escrow account accordingly. I don't currently have a way to split this compensation across the performer and the publisher for material where the two are different. The best I can do is include track info with all my payments and rely on the artist in turn to pay for material they acquired from elsewhere.
8. Finally, and I admit that this last bit is a little geeky, the script files some extra metadata that I use periodically to generate some reports of personal interest. It notes a) where I was when I played a track, b) if it's a running day, whether the track was played before or after my run, c) whether the previous track's info got any hits on my website before being replaced by the current one, d) whether the track starts or ends exactly on a minute boundary according to the NIST atomic clock, e) how many years old the track is (that is, current year minus release year), f) whether the track is an alternate version of an original album track, and g) if the track comes from a release that consisted on CD of multiple discs. For portability reasons this metadata is written into a semicolon-delimited self-addressed email, and re-extracted by a different Applescript run by a Mail rule and appended to an Excel file that I then output in PDF form for archiving.
Clearly there's a lot more that could be done to make my iTunes usage actually conform to my personal listening habits, rather than me just letting the technology control my life the way it usually does, but eventually you've got to strike some kind of balance.
First some notes about use. At this point iTunes controls virtually all of my music listening. The bulk of my music is still acquired by purchasing physical CDs, but these are ripped into iTunes immediately (AAC, 128kbps). At home our main stereo is hooked to an Airport Express so both B and I can beam music to it from our Powerbooks. We both also have small speakers on our desks, and there's another set by the bed that we can plug iPods into when we want. I still do use the CD changer in my car, but both of us also use our iPods in our cars, and I use either the Powerbook or the iPod at work.
My music collection is far larger than my Powerbook or iPod can accommodate, so my encoded selection rotates as new and revived interests push other things out of the active 20GB. Much of the time I use iTunes in Browse mode, listening to individual whole albums in the same way I would have pre-shuffle-era. But increasingly, and especially during periods when my listening isn't so dominated by new releases, I also use iTunes' Party Shuffle mode, fed by a Smart Playlist that filters out non-music genres, cuts out tracks that are too short (<1:30) or too long (>5:22) for my shuffle attention-span, and via another playlist reference excludes anything that has been played recently (i.e., in the last two weeks, or the last 10 hours of music, whichever list is shorter). If I'm in an especially random mood, I have an Applescript that goes through the upcoming Party Shuffle selections and eliminates repetition of artists.
Organizationally, I normalize all incoming music to one of four genre tags: J-Pop, Metal, Noise and Rock, where "Rock" means simply "everything else". For sorting purposes I flip all artist names to "Last, First" and delete leading "The"s. Sound Check, Sound Enhancer and Crossfade Playback are all off. I show the little arrow links, but have tweaked the preference file so that they search within my library first, instead of jumping to the iTMS.
I use Synergy heavily. The Play/Pause button sits alone in my menu bar, but I have keyboard shortcuts for Previous, Play/Pause, Next, Volume Up and Volume Down, and I like Synergy's own Floater better than the version it produces through Growl. The rest of my customization is run by an Applescript triggered by Synergy as a Track Change Item.
The script in turn does several things:
1. Updates my IM status message to include the track info for whatever is playing.
2. Uploads the track info and artwork for the current track to this website, with the proper HTML encoding for Unicode characters.
3. Maintains a single-track playlist called "last started" which contains the most recent track that iTunes began playing.
4. Checks, any time iTunes switches to the "stopped" state, to see if the track in "last started" is the same as the last track in "Recently Played" (which iTunes adds tracks to when they finish), and if so, if that track falls in the middle of an album. If all these things are true, the script restarts playback on the next track of that album. This is a complicated but fairly effective way of compensating for iTunes' predilection to lose track of what it was playing if you're poking around in your Library or the iTMS while you're listening to something else. The began/finished double-check is necessary to prevent this part of the script from effectively disabling the Stop button entirely, which my first iteration of it did.
5. Automatically updates the rating for the track. Although on very rare occassions I do rate tracks manually, for the most part I find that it is more effective to treat the rating as a temporary variable representing my actual behavior towards the track, instead of an attempt to measure my subjective assessment directly. In my case, the rules are approximately these (I've left out some of the more logistical obscurities):
a. New songs enter the system rated 0, which means simply "unplayed".
b. If a song plays all the way through, and it is currently rated 0 or 1, its rating is increased to 2.
c. If a song is played again while it is still on the Recently Played playlist (which with my Party Shuffle configuration would only happen through my deliberate action), its rating is increased. It takes only one repetition to promote a track from 2 to 3, but two to go from 3 to 4, and three to go from 4 to 5. So 5, my highest rating, means that I've played the song all the way through at least seven times in relatively close succession.
d. If a song plays for at least :03, but less than half its length, its rating is decreased by 1. It takes only one skip to demote a track from 5 to 4, 4 to 3 or 3 to 2, but two to go from 2 to 1. Since promotion goes from 0 directly to 2, the rating 1 is reached only by demotion, which allows it to serve as an unambiguous indicator of disfavor.
e. If a set of songs from an album plays all the way through in order, and then the subsequent track on the album starts but doesn't finish, and nothing else from that album is played, I am considered to have skipped all the unplayed songs on the album (where "unplayed" means they don't occur in the previous or next 10 entries in the track history, to catch the case where I interrupt an album but return to it). This rule is screwed up if I single out the last song on the album, since there's no subsequent track to check for, so I try not to do that.
f. At the end of a calendar month, any song with a rating of 3 or lower that hasn't been played since the previous calendar month has its rating decreased by 1, and any track whose rating would be reduced to 0 by this is left at 1 but added to a "to be deleted" playlist, which at the moment I still review manually. The missing detail here, obviously, is that I need to keep track of both a track's current rating and its historical maximum. A track that never got above 3 can be deleted when it gets back to 0, but a track that was ever rated 4 or higher should be down-converted to a lower bitrate encoding instead of being deleted entirely. Hopefully the new Automator framework in Tiger will expose programmatic control of encoder parameters, which the Applescript interface to iTunes 4.7.1 does not.
6. Feeds the track's first two artworks (on the assumption that these are the front and back cover) via ImageEngine to Manatics' Handler plug-in, set at 15%, which applies a mostly transparent mask of my scanned-fingerprints to simulate package wear. The script skips this step if the track or its album are repeated without any non-album tracks intervening, figuring that in physical use this would have meant I didn't need to touch the LP sleeve or CD case.
7. Checks the Comment section for the track, which I maintain in a semi-structured format, for my private rights coding. Any track marked "Bought" came from a legally purchased CD or download, and so requires no further compensation to be issued. A track marked "Preview" is one I have acquired without the artist being compensated, but which only exists temporarily in my library while I decide whether to purchase it. By default no compensation is issued for these tracks during the first week after they are added to the library. Each time one is played more than a week after download, the script asks whether to convert their status to "Honor". Tracks marked "Honor" are ones for which I owe the artist separate compensation from any involved in acquiring the data itself.
For handling the bookkeeping of this separate compensation, the script (actually a combination of Applescript and perl/MySQL) maintains an external database of compensatable artists. By default each full album is worth $4, and individual non-album tracks are worth $0.20 (the system provides support for different values per-album and per-track, and for different system defaults based on acquisition date, but at the moment I'm not actually using those features). I prorate these amounts over the first four times I play the material, so if I play a whole album once, but only once, my accounting considers the artist to be owed only 1/4 of the value, currently $1. The database keeps track of the total amount I owe each artist, the amount they have been paid already, and the amount that has been transferred into a compensation escrow account.
For artists who accept electronic payment via Paypal or credit cards, the database records the relevant payment info. A separate nightly perl script issues electronic payments (via CapitolOne's excellent web-services "micropayment" (sic) interface) where possible (batched until the amount exceeds $1.75), and for artists without electronic payment info, totals the corresponding amounts and transfers the overall total to the money-market escrow account I have for this purpose. The escrow account isn't automated yet, but I usually kludge around this, when I get new payment info for an artist, by simply moving the money back out of escrow, resetting the amount paid/escrowed to $0, and rerunning the original script. At the end of each month I mail physical checks to artists for whom I have physical addresses but not electronic, and rebalance the escrow account accordingly. I don't currently have a way to split this compensation across the performer and the publisher for material where the two are different. The best I can do is include track info with all my payments and rely on the artist in turn to pay for material they acquired from elsewhere.
8. Finally, and I admit that this last bit is a little geeky, the script files some extra metadata that I use periodically to generate some reports of personal interest. It notes a) where I was when I played a track, b) if it's a running day, whether the track was played before or after my run, c) whether the previous track's info got any hits on my website before being replaced by the current one, d) whether the track starts or ends exactly on a minute boundary according to the NIST atomic clock, e) how many years old the track is (that is, current year minus release year), f) whether the track is an alternate version of an original album track, and g) if the track comes from a release that consisted on CD of multiple discs. For portability reasons this metadata is written into a semicolon-delimited self-addressed email, and re-extracted by a different Applescript run by a Mail rule and appended to an Excel file that I then output in PDF form for archiving.
Clearly there's a lot more that could be done to make my iTunes usage actually conform to my personal listening habits, rather than me just letting the technology control my life the way it usually does, but eventually you've got to strike some kind of balance.