iTunes scripts I can’t live without

posted at around evening time by Constantinos. Filed under Code, OS X

This post was originally published in 2007
The tips and techniques explained may be outdated.

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

Download this script

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:

The other is named “All Unrated”, and has the following rules:

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

Download this script

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!

11 Responses to “iTunes scripts I can’t live without”

  1. 1. Comment by Daryl
    on 17 Aug 2007 @ 10:21 pm

    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. 2. Comment by Constantinos
    on 22 Aug 2007 @ 3:20 am

    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:

    tell application "iTunes"
    	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. 3. Comment by Constantinos
    on 17 Sep 2007 @ 1:55 am

    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.

  4. 4. Comment by Daniel
    on 11 Jun 2008 @ 6:13 pm

    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?

  5. 5. Comment by L8on
    on 18 Jul 2008 @ 1:09 am

    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!

  6. 6. Comment by Constantinos
    on 18 Jul 2008 @ 3:24 pm

    This is ENTIRELY untested, I just typed it up in this textbox. But it should be something along these lines:

    property oldRepeatType : ""
     
    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.

  7. 7. Comment by L8on
    on 21 Jul 2008 @ 4:40 am

    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…

  8. 8. Comment by L8on
    on 21 Jul 2008 @ 5:01 am

    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!

  9. 9. Comment by Ian Jones
    on 22 Sep 2008 @ 11:25 am

    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.

  10. 10. Comment by Alex Drost
    on 23 Oct 2010 @ 11:05 am

    Hi there, I absolutely love your script techniques. I’m having the same problems as you – a large library which I want to fix with tags and ratings. Now I’m looking desperately for a script which reminds me to rate the item, e.g. 15 seconds before the end of the song.

    e.g. the song’s playing and 15 seconds before it, a little bell (or something like that) rings and I just hit my shortcuts to rate the song. That way, I don’t have to jump back and forth (esp. with soundtracks) whether I have skipped a song or not. 🙂

    Do you have an idea?

    Best!
    Alex. 🙂

  11. 11. Comment by TomTom
    on 21 Jun 2011 @ 10:43 pm

    Hey dude..
    Cool scripts..
    I was wondering if I could ask you about making a fairly easy script, or at least I think it will be easy, that simply links GrowlTunes to launch/quit when launching/quitting iTunes..?
    If its even possible..?

    PS. I know this post is quite old, but I’m hoping your still checking up once every now and then…