Improve Your AppleScripts: Putting It All Together

Using What We’ve Learned So Far

In my previous columns in this series, I showed you a technique to simplify your script creation (pseudocode) and how to use Applescript to create three of the basic data structures that are used in computer science (stacks, queues, and priority queues), and the different types of sorting routines that you can write in Applescript. In this article, we’ll put several of those techniques together to help us quickly and efficiently write an intermediate-level script.

The Artist Formerly Known As AppleScript

If you’re like me, and use iTunes a lot while you’re working, sometimes you wish you could just quickly choose to play all the songs by a given artist (or album) without having to pay too much attention to iTunes. You just want to get iTunes going and get back to work. So let’s write a quick script to present us with a (sorted) list of artists to choose from and have the script “push the buttons” in iTunes to get the music going. If you want to follow along, I’ll be using the sortLib from my Nite Flite script library, or you can use your own sort routine.

The Script (3,000 ft. view)

First let’s use the pseudocode technique from an earlier column on Structured Programming. We want to use a shared library, so we will need to load it before we do anything else. Then we need to get a list of artists from iTunes, and present that list to the user to make a selection. Lastly, we need to use the selected artist to select all songs by that artist and group them into a playlist. Then we’ll play the playlist. In pseudocode, that sequence looks like this:
* --load the sort library
* --get Artist list from iTunes and sort it
* --get an Artist from the user
* --set up playlist and playJust as we’ve done before, the pseudocode is our “road map” and we’ll format it as comments, since they will help document our program. I keep a folder in my Scripts folder called “Script Library,” where I keep shared libraries such as my sortLib. If you keep yours somewhere else, use that path instead of the one I’m using here:

–load the sort library


set AppleScript's text item delimiters to {}
set scriptPath to (path to scripts folder from user domain) & "Script Library:"
set sortLib to load script ((scriptPath as text) & "sortLib.scpt") as alias

Now that the sort library is loaded, let’s get the list of artists from iTunes and sort it. Remember, when using a loaded library you must preface any of its handlers with the library’s name in the possessive case (“sortLib’s quickSort(shortArtistList)”).

– get Artist list from iTunes and sort it


set shortArtistList to {}
tell application "iTunes"
	set ArtistList to the artist of every track of library playlist 1
	set tcount to count ArtistList
end tell
repeat with i from 1 to tcount
	tell my ArtistList's item i to if it is not in my shortArtistList and it ≠ "" then set end of my shortArtistList to it
end repeat
set shortArtistList to sortLib's quickSort(shortArtistList)

This code seems fairly straightforward, I hope. If you have an older Mac (I used to own a G3), you can substitute the following code as it executes faster. It is optimized for speed, but isn’t very readable:

– get Artist list from iTunes and sort it (fast version)


set shortArtistList to {}
tell application "iTunes" to tell (get artist of tracks of library playlist 1) to set {ArtistList, tcount} to {it, count it}
repeat with i from 1 to tcount
	tell my ArtistList's item i to if it is not in my shortArtistList and it ≠ "" then set end of my shortArtistList to it
end repeat

Next, we get the user’s selection. Remember when using choose from list that if no item is selected, the call returns false, not a list! But we’ll trap for that and only proceed if the returned value isn’t false:

–get an Artist from the user


set theArtist to choose from list shortArtistList with prompt "Which Artist do you want to hear?" without multiple selections allowed
if theArtist is not false then
	set theArtist to theArtist as text

We set theArtist to theArtist as text because choose from list returns a list, not a text item! Now, should we give the user the option to shuffle the songs we’re about to play? Sure, why not!


	display dialog "Shuffle play?" buttons {"Yes", "No"} default button "No"
	if button returned of the result is "Yes" then
		set theShuffle to true
	else
		set theShuffle to false
	end if

Now all that is left to do is to create the playlist and fire up the tunes. For the use of scripts like this one, I keep a playlist in my iTunes playlists called “Applescript.” Any script that creates a playlist re-uses this list, but you can name yours something else, if you like:

--set up playlist and play

	tell application "iTunes"
		if exists user playlist "AppleScript" then
			delete every file track of user playlist "AppleScript"
		else
			make new user playlist with properties {name:"AppleScript"}
		end if
		set shuffle of user playlist "Applescript" to theShuffle
		duplicate (every file track of library playlist 1 whose artist is theArtist) to user playlist "Applescript"
		play user playlist "AppleScript"
	end tell
end if

One of the biggest errors beginning scripters make in iTunes is using the command copy when they mean duplicate. It’s an easy error to make. Our finished script looks like this:

–load the sort library


set AppleScript's text item delimiters to {}
set scriptPath to (path to scripts folder from user domain) & "Script Library:"
set sortLib to load script ((scriptPath as text) & "sortLib.scpt") as alias
-- get Artist list from iTunes and sort it
set shortArtistList to {}
tell application "iTunes"
	set ArtistList to the artist of every track of library playlist 1
	set tcount to count ArtistList
end tell
repeat with i from 1 to tcount
	tell my ArtistList's item i to if it is not in my shortArtistList and it ≠ "" then set end of my shortArtistList to it
end repeat
set shortArtistList to sortLib's quickSort(shortArtistList)
--get an Artist from the user
set theArtist to choose from list shortArtistList with prompt "Which Artist do you want to hear?" without multiple selections allowed
if theArtist is not false then
	set theArtist to theArtist as text
	display dialog "Shuffle play?" buttons {"Yes", "No"} default button "No"
	if button returned of the result is "Yes" then
		set theShuffle to true
	else
		set theShuffle to false
	end if
	--set up playlist and play
	tell application "iTunes"
		if exists user playlist "AppleScript" then
			delete every file track of user playlist "AppleScript"
		else
			make new user playlist with properties {name:"AppleScript"}
		end if
		set shuffle of user playlist "Applescript" to theShuffle
		duplicate (every file track of library playlist 1 whose artist is theArtist) to user playlist "Applescript"
		play user playlist "AppleScript"
	end tell
end if

Having written this script, it’s an easy copy & edit job to create a similar script that will play one of you favorite albums just as if you had inserted the CD:


--load the sort library
set scriptPath to (path to scripts folder from user domain) & "Script Library:"
set sortLib to load script ((scriptPath as text) & "sortLib.scpt") as alias
-- get album list from iTunes and sort it
set shortAlbumList to {}
tell application "iTunes"
	set albumList to the album of every track of library playlist 1
	set tcount to count albumList
end tell
repeat with i from 1 to tcount
	tell my albumList's item i to if it is not in my shortAlbumList and it ≠ "" then set end of my shortAlbumList to it
end repeat
--get an album from the user
set shortAlbumList to sortLib's quickSort(shortAlbumList)
set theAlbum to choose from list shortAlbumList with prompt "Which album do you want to hear?" without multiple selections allowed
if theAlbum is not false then
	set theAlbum to theAlbum as text
	display dialog "Shuffle play?" buttons {"Yes", "No"} default button "No"
	if button returned of the result is "Yes" then
		set theShuffle to true
	else
		set theShuffle to false
	end if
	--set up playlist and play
	tell application "iTunes"
		if exists user playlist "AppleScript" then
			delete every file track of user playlist "AppleScript"
		else
			make new user playlist with properties {name:"AppleScript"}
		end if
		set shuffle of user playlist "Applescript" to theShuffle
		duplicate (every file track of library playlist 1 whose album is theAlbum) to user playlist "Applescript"
		play user playlist "AppleScript"
	end tell
end if

I hope this gives you some idea of the power of combining pseudocode, sorting, and shared libraries. In a relatively short time you can “slap together” well-built scripts that you know work because you’re using bits of code that have already been debugged. It’s the difference between building a skyscraper and lots of little houses. By building on what you have already done, you don’t have to re-invent the wheel every time you write a script. Programmers call this “write once, use many.” Until next time, have fun, and script something you do every day!