iTunes scripts I can’t live without
posted at around evening time by Constantinos. Filed under Code, OS X
I have few obsessions in my life, and one of those happens to be keeping my iTunes library in some form (and definition) of ‘order’, without having me go completely insane. This involves keeping the ID3 data as accurate as I can make it (very tedious process as I had about 100 songs named Track 3 - Unknown Artist), but that is more or less under control. What I’m working on now is rating all of my music (I’m sure every one has their own rating scheme, and there’s no need to share mine here… Just suffice to say that a 0-star rating means the song hasn’t been reviewed), and also getting as much album artwork to go with iTune’s cover flow so I can use it without looking at the same default image every time…
Doing all this manually would pretty much take up all my time, so over a period of few months (back when I first started dealing with my iTunes library), I built a few applescripts which help me manage all these tasks, and which are bound to keyboard shortcuts in Quicksilver.
Rating
I have all the standard 0-5 star rating scripts, which are bound to cmd-opt-0 through cmd-opt-5 respectively. Since I use Growl, I wanted a notification to come up for this fact, and use the album artwork (if any) as the notification icon. This is the script for the 5 star rating, where for every other (0-4 stars) script the only modification is the actual rating (commented in the script)
property emdash : «data utxt2014» as Unicode text
property black_star : «data utxt272F» as Unicode text
property white_star : «data utxt2606» as Unicode text
property dot : «data utxt00B7» as Unicode text
set appName to "GrowlHelperApp"
set app2Name to "iTunes"
tell application "System Events"
set appIsRunning to (name of processes contains appName) and (name of processes contains app2Name)
end tell
if appIsRunning then
tell application "iTunes"
if class of current track is in {track, file track, URL track, device track, shared track, audio CD} then
(* Increments of 20, from 0 to 100 for 0 - 5 stars *)
set rating of current track to 100
end if
my notifyTrack(current track, player position, "5 Stars") (* or whatever else you want *)
end tell
end if
on notifyTrack(myTrack, pos, txt)
tell application "iTunes"
set trkName to name of myTrack
set trkArtist to artist of myTrack
set trkAlbum to album of myTrack
set trkTime to time of myTrack
set trkRating to (rating of myTrack) / 20
set trkPos to my getTimeString(pos)
set artworkCount to count of artwork of myTrack
if artworkCount > 0 then
tell myTrack
set trkArt to (data of artwork 1)
end tell
else
set iTunesIcon to "Macintosh HD:Applications:iTunes.app:Contents:Resources:iTunes.icns"
set trkArt to read (file iTunesIcon) as picture
end if
if (txt is equal to false) then
set txt to trkName
set trkInfo to trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist & return & trkAlbum
else
set trkInfo to trkName & return & trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist
if (trkAlbum is not equal to "") then
set trkInfo to trkInfo & " (" & trkAlbum & ")"
end if
end if
end tell
my showQSNotify(txt, trkArt, trkInfo)
end notifyTrack
on showStars(trkRating)
set stars to ""
repeat trkRating times
set stars to stars & black_star
end repeat
repeat (5 - trkRating) times
set stars to stars & " " & dot
end repeat
return stars
end showStars
on showQSNotify(txt, trkArt, trkInfo)
tell application "GrowlHelperApp"
set the allNotificationsList to {"Rating Change", "Song Skipping", "Song Info"}
register as application ¬
"Hotkey iTunes Notification" all notifications allNotificationsList default notifications allNotificationsList ¬
icon of application "iTunes"
if (trkArt is equal to missing value) then
notify with name "Rating Change" title txt description trkInfo application name "Hotkey iTunes Notification"
else
notify with name "Rating Change" title txt description trkInfo application name "Hotkey iTunes Notification" pictImage the trkArt
end if
end tell
end showQSNotify
on showTrackInfo()
try
tell application "GrowlTunes"
show current track
end tell
end try
end showTrackInfo
on getTimeString(secs)
set no_seconds to the secs as number
set no_minutes to no_seconds div 60
set no_seconds to no_seconds mod 60
if no_seconds < 10 then
set seconds_text to "0" & (no_seconds as string)
else
set seconds_text to no_seconds as string
end if
if no_minutes ≥ 60 then
set no_hours to no_minutes div 60
set no_minutes to no_minutes mod 60
if no_minutes < 10 then
set no_minutes to "0" & (no_minutes as string)
end if
set minutes_text to (no_hours as string) & ":" & (no_minutes as string)
else
set minutes_text to no_minutes as string
end if
return minutes_text & ":" & seconds_text
end getTimeString
Skipping
Sometimes, I find myself having a few hours of free time, where I want to just sit down and rate all my unrated songs. Instead of using the mouse to skip through every song (since I’ve already heard all of them, I just haven’t considered a rating for them), I have a script that skips a quarter of the song on each press, and places the playhead at 3 seconds from the end on the 4th activation. Useful for quickly skipping through a song.
property emdash : «data utxt2014» as Unicode text
property black_star : «data utxt272F» as Unicode text
property white_star : «data utxt2606» as Unicode text
property dot : «data utxt00B7» as Unicode text
set appName to "GrowlHelperApp"
set app2Name to "iTunes"
tell application "System Events"
set appIsRunning to (name of processes contains appName) and (name of processes contains app2Name)
end tell
if appIsRunning then
try
tell application "iTunes"
set myTrack to current track
set dur to duration of myTrack
set q1 to dur / 4
set q2 to q1 * 2
set q3 to q1 * 3
set q4 to dur - 3
set curPos to player position
set counter to 0
set theList to {q1, q2, q3, q4, dur}
set pos to 0
repeat while pos is less than or equal to curPos
set counter to counter + 1
set pos to item counter of theList
end repeat
if pos is less than 1 then set pos to 1
set player position to pos
if counter is greater than 3 then
my notifyTrack(myTrack, player position, "Ending Song")
else
my notifyTrack(myTrack, player position, "Song Skip")
end if
(* my showTrackInfo() *)
end tell
end try
end if
on notifyTrack(myTrack, pos, txt)
tell application "iTunes"
set trkName to name of myTrack
set trkArtist to artist of myTrack
set trkAlbum to album of myTrack
set trkTime to time of myTrack
set trkRating to (rating of myTrack) / 20
set trkPos to my getTimeString(pos)
set artworkCount to count of artwork of myTrack
if artworkCount > 0 then
tell myTrack
set trkArt to (data of artwork 1)
end tell
else
set iTunesIcon to "Macintosh HD:Applications:iTunes.app:Contents:Resources:iTunes.icns"
set trkArt to read (file iTunesIcon) as picture
end if
if (txt is equal to false) then
set txt to trkName
set trkInfo to trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist & return & trkAlbum
else
set trkInfo to trkName & return & trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist
if (trkAlbum is not equal to "") then
set trkInfo to trkInfo & " (" & trkAlbum & ")"
end if
end if
end tell
my showQSNotify(txt, trkArt, trkInfo)
end notifyTrack
on showStars(trkRating)
set stars to ""
repeat trkRating times
set stars to stars & black_star
end repeat
repeat (5 - trkRating) times
set stars to stars & " " & dot
end repeat
return stars
end showStars
on showQSNotify(txt, trkArt, trkInfo)
tell application "GrowlHelperApp"
set the allNotificationsList to {"Rating Change", "Song Skipping", "Song Info"}
register as application ¬
"Hotkey iTunes Notification" all notifications allNotificationsList default notifications allNotificationsList ¬
icon of application "iTunes"
if (trkArt is equal to missing value) then
notify with name "Song Skipping" title txt description trkInfo application name "Hotkey iTunes Notification"
else
notify with name "Song Skipping" title txt description trkInfo application name "Hotkey iTunes Notification" pictImage the trkArt
end if
end tell
end showQSNotify
on showTrackInfo()
try
tell application "GrowlTunes"
show current track
end tell
end try
end showTrackInfo
on getTimeString(secs)
set no_seconds to the secs as number
set no_minutes to no_seconds div 60
set no_seconds to no_seconds mod 60
if no_seconds < 10 then
set seconds_text to "0" & (no_seconds as string)
else
set seconds_text to no_seconds as string
end if
if no_minutes ≥ 60 then
set no_hours to no_minutes div 60
set no_minutes to no_minutes mod 60
if no_minutes < 10 then
set no_minutes to "0" & (no_minutes as string)
end if
set minutes_text to (no_hours as string) & ":" & (no_minutes as string)
else
set minutes_text to no_minutes as string
end if
return minutes_text & ":" & seconds_text
end getTimeString
Download this script
This method works well with a couple of smart playlists and clever manipulation of the Party Shuffle feature. I have two smart playlists (one of them is used to filter out tv shows and movies, but not video clips). One is named “Other Video”, and has the following rules:
- Match any of the following:
- Video kind is Movie
- Video kind is TV Show
The other is named “All Unrated”, and has the following rules:
- Match all of the following:
- My rating is less than 1 star
- Podcast is false
- Playlist is not Other Video
Finally, in Party Shuffle, at the bottom, I have Source: “All Unrated”, Display 5 recently played songs, and 15 upcoming songs. This way, even though the song I just rate will be removed from the “All Unrated” smart playlist, it won’t stop playing as it’s in the Party Shuffle playlist.
Artwork
I first ran “Get Album Artwork” in iTunes, but obviously that had a fairly limited success as a lot of my music has vital information like Album missing, and also a lot of the music I listen to isn’t even in the iTunes store. To cover the gap, I’m a fanatic GrowlTunes user, which does all the heavy work of fetching album covers (sometimes more successfully than others). GrowlTunes first looks for album artwork in the song itself, and if it doesn’t find any it then fetches it from the internet to display the Growl alert. What it does NOT do is save it with the song, but it DOES save it locally so it doesn’t have to fetch it again (in my opinion this is a very good thing as anything under a 95% success ratio you’ll want to review, and GrowlTunes is more like 70%). So what I’ve done is prepared a script that, for the current track, looks at the default GrowlTunes location, and if it finds an album cover it adds it to the song (to run it, you will need to replace your own short user name at the first line of the script):
property myUserName : "Constantinos"
property appName : "iTunes"
tell application "System Events" to set appIsRunning to name of processes contains appName
if appIsRunning then
tell application "iTunes"
try
set myTrack to current track
set trackName to name of myTrack
if (trackName is equal to "") then
set trackName to "Unknown Track"
end if
set trackArtist to artist of myTrack
if (trackArtist is equal to "") then
set trackArtist to "Unknown Artist"
end if
set trackAlbum to album of myTrack
if (trackAlbum is equal to "") then
set trackAlbum to "Unknown Album"
end if
end try
end tell
set artworkFilename to "/Users/" & myUserName & "/Library/Images/Music/" & trackArtist & "/" & trackAlbum & "/Tracks/" & trackName & "/Track.png"
set deleteFilename to "Macintosh HD:Users:" & myUserName & ":Library:Images:Music:" & trackArtist & ":" & trackAlbum & ":Tracks:" & trackName & ":Track.png"
set deleteCoverFilename to "Macintosh HD:Users:" & myUserName & ":Library:Images:Music:" & trackArtist & ":" & trackAlbum & ":Cover.png"
set albumCoverFilename to "/Users/" & myUserName & "/Library/Images/Music/" & trackArtist & "/" & trackAlbum & "/Cover.png"
set tempfile to "Macintosh HD:tmp:temporary.pict"
tell application "Image Events"
(* set artworkFile to (POSIX file artworkFilename)
set myImage to open (artworkFile as alias) *)
set myImage to open artworkFilename
try
save myImage as PICT in (file tempfile)
on error
try
set deleteFilename to deleteCoverFilename
set myImage to open albumCoverFilename
save myImage as PICT in (file tempfile)
on error
return
end try
end try
close myImage
end tell
tell application "iTunes"
set myTrack to current track
set artworkCount to count of artwork of myTrack
set myArt to read (file tempfile) from 513 as picture
if artworkCount > 0 then
set data of artwork (artworkCount + 1) of current track to myArt
else
set data of artwork 1 of current track to myArt
end if
end tell
tell application "Image Events"
delete (file tempfile)
delete (file deleteFilename)
end tell
end if
Notifications
The first two scripts use the same “Hotkey iTunes Notification” application name to register with Growl, with three types of notification: “Rating Change”, “Song Skipping” and “Song Info”. The last one simply brings up a detailed notification dialog with the current song’s playhead position, title, artist, rating, album and album art, which can all fit in the small “Smoke” style notification window. If you’re interested in that, the script follows:
property emdash : «data utxt2014» as Unicode text
property black_star : «data utxt272F» as Unicode text
property white_star : «data utxt2606» as Unicode text
property dot : «data utxt00B7» as Unicode text
set appName to "GrowlHelperApp"
set app2Name to "iTunes"
tell application "System Events"
set appIsRunning to (name of processes contains appName) and (name of processes contains app2Name)
end tell
if appIsRunning then
tell application "iTunes"
my notifyTrack(current track, player position, false)
end tell
end if
on notifyTrack(myTrack, pos, txt)
tell application "iTunes"
set trkName to name of myTrack
set trkArtist to artist of myTrack
set trkAlbum to album of myTrack
set trkTime to time of myTrack
set trkRating to (rating of myTrack) / 20
set trkPos to my getTimeString(pos)
set artworkCount to count of artwork of myTrack
if artworkCount > 0 then
tell myTrack
set trkArt to (data of artwork 1)
end tell
else
set iTunesIcon to "Macintosh HD:Applications:iTunes.app:Contents:Resources:iTunes.icns"
set trkArt to read (file iTunesIcon) as picture
end if
if (txt is equal to false) then
set txt to trkName
set trkInfo to trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist & return & trkAlbum
else
set trkInfo to trkName & return & trkPos & "/" & trkTime & " " & emdash & " " & my showStars(trkRating) & return & trkArtist
if (trkAlbum is not equal to "") then
set trkInfo to trkInfo & " (" & trkAlbum & ")"
end if
end if
end tell
my showQSNotify(txt, trkArt, trkInfo)
end notifyTrack
on showStars(trkRating)
set stars to ""
repeat trkRating times
set stars to stars & black_star
end repeat
repeat (5 - trkRating) times
set stars to stars & " " & dot
end repeat
return stars
end showStars
on showQSNotify(txt, trkArt, trkInfo)
tell application "GrowlHelperApp"
set the allNotificationsList to {"Rating Change", "Song Skipping", "Song Info"}
register as application ¬
"Hotkey iTunes Notification" all notifications allNotificationsList default notifications allNotificationsList ¬
icon of application "iTunes"
if (trkArt is equal to missing value) then
notify with name "Song Info" title txt description trkInfo application name "Hotkey iTunes Notification"
else
notify with name "Song Info" title txt description trkInfo application name "Hotkey iTunes Notification" pictImage the trkArt
end if
end tell
end showQSNotify
on showTrackInfo()
try
tell application "GrowlTunes"
show current track
end tell
end try
end showTrackInfo
on getTimeString(secs)
set no_seconds to the secs as number
set no_minutes to no_seconds div 60
set no_seconds to no_seconds mod 60
if no_seconds < 10 then
set seconds_text to "0" & (no_seconds as string)
else
set seconds_text to no_seconds as string
end if
if no_minutes ≥ 60 then
set no_hours to no_minutes div 60
set no_minutes to no_minutes mod 60
if no_minutes < 10 then
set no_minutes to "0" & (no_minutes as string)
end if
set minutes_text to (no_hours as string) & ":" & (no_minutes as string)
else
set minutes_text to no_minutes as string
end if
return minutes_text & ":" & seconds_text
end getTimeString
Download this script
That’s pretty much it… Enjoy!


1. Comment by Daryl
on 17 Aug 2007 @ 10:21 pm · Quote #2034 ·
I wanted a simple apple script that will simply play the first anyNumber of seconds of a song so I can play my music in an ‘intro mode’ feel at night with dashboard open so my lyrics fetch widget can get all the lyrics for my iTunes lib. If you could help me with some applescripting (I am pretty good at programming, but I don’t yet understand applescript. The language is too close to human language, I think I need a language to be obscure to understand it
) It would be in your debt.
Thanks in advance
2. Comment by Constantinos
on 22 Aug 2007 @ 3:20 am · Quote #2039 ·
I’d love to help, but I can’t see how such an applescript would work without having the script be resident and running… Which actually might be a solution.
How about trying something like this:
play
repeat with i from 1 to 1000
next track
delay 15
end repeat
end tell
where 1 to 1000 is just a “large loop”, I’m sure there’s an easy way to have an infinite loop in applescript but it doesn’t pop in my head right now. Also the “delay 15″ part will let the current song play for 15 seconds before moving on to the next track. Modify to your enjoyment.
This is obviously really crude and can probably handle a lot of improvement, but I don’t see a way of getting rid of the loop/delay part of the program which is what bugs me. To stop this you’ll have to terminate the applescript.
3. Comment by MightyAdsense Google Ad
on 7 Jan 2009 @ 1:48 am · Quote #0 ·
4. Comment by Constantinos
on 17 Sep 2007 @ 1:55 am · Quote #2057 ·
Note on the skipping script: There was a bug where if you tried to skip as soon as the song started, or twice in less than a second, it would skip to the same quarter of the song. If you’re experiencing this problem, copy the updated script above.
5. Comment by Daniel
on 11 Jun 2008 @ 6:13 pm · Quote #2305 ·
I’m new to apple scripts and have tried reading up on where to put these to get them running.
But the more i search the more questions i came up with. But, here are my top 2.
1. where do i place the scripts
2. they are auto running correct? in other words i dont have to run the script every time i start itunes correct?
6. Comment by L8on
on 18 Jul 2008 @ 1:09 am · Quote #2398 ·
You have great scrips! However, I can’t seem to find the one I want anywhere on the internet. I am looking for a script I can run to enable single repeat of a song until I run it again [or run another script to go back to repeat all].
I am often on a random playlist and hear a song I want to hear again and don’t want to have to switch to iTunes to turn repeat on and then off again. I also don’t want to just rewind to beginning as the song doesn’t get the “play count”.
Then I would be able to trigger this script with a keystroke.
ANY SUGGESTIONS!
thanks!
7. Comment by Constantinos
on 18 Jul 2008 @ 3:24 pm · Quote #2401 ·
This is ENTIRELY untested, I just typed it up in this textbox. But it should be something along these lines:
tell application "iTunes"
if oldRepeatType is "" then
set oldRepeatType to all
end if
set repeatType to get song repeat of current playlist
if repeatType is not one then
set oldRepeatType to repeatType
set song repeat of current playlist to one
else
set song repeat of current playlist to oldRepeatType
end if
end tell
Let me know if it works for you, or what errors it produces.
8. Comment by L8on
on 21 Jul 2008 @ 4:40 am · Quote #2408 ·
THANK YOU VERY MUCH! I ran it over and over again with iTunes in the background and it does EXACTLY what I want it to do. I just wish Apple would’ve build a toggle into the mini controller. Thank you so very much! Is there any way there can be a way of knowing whether it’s on “one” or “all”? To check I’d have to switch to iTunes which kind defeats the purpose. Either way, I’m very happy with it.
How did you get so good at script writing?
I’ll definitely be reading the blog more often…
9. Comment by L8on
on 21 Jul 2008 @ 5:01 am · Quote #2409 ·
just a thought. I saved it as an application on my desktop. Can you make the label on the turn green when it is on “one” and turn red when it is on “all”? That would be great and would instantly let me know mid-song whats the status.
In the middle of a song, I might think, okay this is the last time I wanna hear it but dont want to have to pull up iTunes to change it if in fact it was on repeat.
Thanks again!
10. Comment by Ian Jones
on 22 Sep 2008 @ 11:25 am · Quote #2580 ·
Is it possible to have a script that finds all “orphaned” songs (listing not linked to file) and move them to a playlist so that I can work through them to re-link them? I’ve seen scripts that find the orphans, but then just writes the list to a text file.