Hacking iPod and iTunes
Pages: 1, 2, 3, 4, 5


Hack #72 Tame iTunes with AppleScript Hack

Whether you need an AppleScript refresher or you are a willing AppleScript newbie, this hack provides the AppleScript basics you’ll need to understand the rest of the scripts in this chapter.

AppleScript is a simple but powerful programming language that lets you control applications on your computer and automate the tasks that they perform. Basically, an AppleScript script is a list of instructions. When you activate the script, the instructions are carried out. Additionally, a script is able to perform computations that allow it to make decisions about how its instructions are executed.

You write, test, and save AppleScript scripts with Script Editor, an application that comes installed with your Macintosh operating system. Scripts are saved as files and can be run like applications or, even simpler, like menu commands. As you will see, the language used to write AppleScript is much more English-like than other programming languages, which makes Apple- Script relatively easy to learn and use.

TIP: Unlike scripts written in other scripting languages (such as Perl or JavaScript) that can be written and saved using any text editor and can run on other computer platforms, Apple- Script scripts can be written only with an AppleScript editor and can be used only on a Mac. Apple provides Script Editor as part of the operating system, but there are a couple other script editors available as well—most notably, Script Debugger, a commercial product ($189.00; demo available), and Smile (free).

Using AppleScript, you can perform automated iTunes tasks that otherwise would be repetitive, time-consuming, or just plain difficult. For example, you can create scripts that clean up the text in track tags [Hack #74], create playlists [Hack #82], export artwork [Hack #86], send track tag information to other applications [Hack #80], [Hack #87], control the playing of tracks [Hack #88], send files to iPod [Hack #83], and much, much more.

TIP: This hack is a crash course in some of the AppleScript you should know to understand the hacks in this chapter. For a comprehensive guide to AppleScript, take a gander at AppleScript: The Definitive Guide, by Matt Neuburg (O’Reilly).

Writing AppleScript Scripts with Script Editor

Script Editor is located on your computer in /Applications/AppleScript. When you run Script Editor and create a new Script Editor document (File ->New) you might notice how similar it looks to a text editor (see Figure 5-1). As in a text editor, the document window is where you will enter and edit text that will eventually become a script.

The Script Editor toolbar contains a default set of four buttons:

Lets you start recording your actions in the Finder and any other Apple- Script-aware applications, although not all of these applications are

recordable (including iTunes). We will not be using this function much, if at all.

Figure 5-1. Script Editor is quite similar in appearance to a text editor such as TextEdit
Figure 5-1. Script Editor is quite similar in appearance to a text editor such as TextEdit

Stops execution of the script or halts recording if it is active. Pressing c-. (that’s the Command key and the period) also aborts the running of a script.
Executes the current script.
Tells Script Editor to check the script for correct syntax before running it. This does not check if the script actually works, just whether it’s constructed properly.

Along the bottom of the Script Editor window are three tabs that determine what is displayed in the lower half of the window. The Description tab contains a text description from the author of what the script does, displayable as a splash screen at startup. I also use it for temporarily parking snippets of code or copy-and-pasted text. The Result tab displays the last result computed by the running script. Event Log is a running display showing the results of a running script and logged results—very handy for debugging. You will use the Event Log window often while writing AppleScript scripts.

For the purposes of introduction, we’re going to create, save, and run a simple script to use with iTunes. We’ll get into more detail about the language momentarily.

Type the following text into the Script Editor window:

  tell application "iTunes"
  play playlist "Library"
  end tell
TIP: Hit the Return/Enter key on your keyboard to end each line and begin another. You will also notice that the continuation character (¬), created by pressing Option-Return, is used in many of the later scripts to segment single lines of code so that they look better in print; you can omit them in your code if you like.

Your Script Editor window should look like Figure 5-2.

Figure 5-2. An AppleScript script in the Script Editor window
Figure 5-2. An AppleScript script in the Script Editor window

When you first enter text into a Script Editor window, it's only text. But click the Compile button (or press Command-K), and Script Editor will check the script's syntax for any errors and format it nicely for you, as shown in Figure 5-3.

Figure 5-3. Script Editor, compiling and formatting the text
Figure 5-3. Script Editor, compiling and formatting the text

You now have a script that you can run and save.

To use a script from iTunes’s Scripts menu, you need to save it as a compiled script (see the sidebar “Save As…”).

A compiled script is one that has the proper syntax and whose commands work properly on your computer. However, it is not a freestanding application. It can be run only by Script Editor or within an application that has a Scripts menu and script interpreter (such as iTunes), or by using the optional system wide Scripts menu, installable by running the Install Script Menu AppleScript applet located in /Applications/AppleScript/. For this option, select Script from the File Format drop-down box in the Save As… dialog.

A script saved as an application is self-contained and can be run by double clicking it in the Finder, as with any other application. Sometimes, Apple- Script applications are called applets. Applets can also be activated from iTunes’s Scripts menu. For this option, select Application from the File Format drop-down box in the Save As… dialog.

A stay-open application is an AppleScript applet that just doesn’t quit—literally. In general, this is a type of script application that runs in the background indefinitely, watching for a particular condition or changes to a condition. For instance, a stay-open applet can be used to detect when a new track has started playing in iTunes and then perform some task. The script Current Track to iChat Status [Hack #87] is a stay-open applet. For this option, select Application from the File Format drop-down box in the Save As… dialog, and check the Stay Open checkbox.

Scripts can also be saved as text files in Script Editor. However, these text files can only be read by Script Editor, not by regular text editors. Script Editor doesn’t try to compile a script before saving it as text, so often it’s convenient to save an unfinished script this way. For this option, select Text from the File Format drop-down box in the Save As… dialog.

We will be working with compiled scripts at first. Later, you will see scripts saved as applets and stay-open applications.

  1. Select File ->Save As….
  2. In the Save As… box, enter the name for your script—Play Library is as good as anything else.
  3. Select either the non–user-specific /Library/iTunes/Scripts folder or the /Users/username/Library/iTunes/Scripts folder as the destination folder for your script (if either folder doesn’t exist, simply create it).
  4. Choose Compiled from the File Format menu, and click the Save button.

The script is available in the iTunes Scripts menu, as shown in Figure 5-4.

Go ahead and give it a whirl.

Figure 5-4. The Play Library script in the iTunes Scripts menu
Figure 5-4. The Play Library script in the iTunes Scripts menu

AppleScript for iTunes: A Primer

The language of AppleScript is pretty similar to everyday language (though with a stricter-than-English grammar), so you won’t have to learn too many new code words. This also makes it much easier to explain. Usually, a line of AppleScript does exactly what it says it will do.

tell statements. Type this fairly simple sentence into Script Editor, and then activate it by pressing the Run button:

  tell application "iTunes" to play

This is a tell statement; it tells a particular application to do something. In this case, it tells iTunes to start playing. tell statements contain objects and commands, which are very much like nouns and verbs, respectively. When you want to perform several commands on one targeted application, you can use just one tell statement around a block of other commands, terminated by an end tell:

  tell application "iTunes"
    set sound volume to 40
    set EQ enabled to true
  end tell

Sometimes, this is called a compound tell statement or a tell block. Usually, all of a script’s commands and computations occur within just one set of tell statements.

Objects and references. An AppleScript object is a thing that is scriptable. In the case of iTunes, this includes a playlist, a track, an audio source, and so on. AppleScript identifies an object in a scriptable application by using a reference to it. A reference is an unambiguous pointer to a very specific thing. Observe the middle line in the following script:

  tell application "iTunes"
    play track 7 of user playlist "Sparkle and Fade"
  end tell

In this script, the phrase track 7 of user playlist "Sparkle and Fade" is a reference to a specific track in a specific playlist in the application iTunes. The word of is used in a reference to unambiguously connect a particular object to its container; in the previous code snippet, the user playlist named “Sparkle and Fade” is the container of track number 7.

Additionally, an object can contain properties. For example, name is a property of the track object; the value of name is the text of the track’s Song Name. You can specify a particular property of an object using a reference as well. In the following script, the statement in the second line references the name of a particular track in a particular playlist:

  tell application "iTunes"
    name of track 7 of user playlist "Sparkle and Fade"
  end tell

Often, rather than typing the same reference over and over whenever you need it in the script, you can store the reference in a variable. A variable is a user-named holder for a value. The value in this case will be a reference. In the following example, I store a reference to the playlist called “Mom’s Favorites” in a variable I have chosen to name thisPlaylist:

  tell application "iTunes"
    set thisPlaylist to playlist "Mom's Favorites"
  end tell

Later in the script, whenever I want to refer to the playlist “Mom’s Favorites,” I can simply use the variable thisPlaylist instead.

get and set (and sometimes copy). You can retrieve the value of a variable or property with the AppleScript command get, and you can assign a new value to a variable or property with set:

  tell application "iTunes"
    -- get a value
    copy (get name of track 12 of playlist "Favorites") to trackName
    -- and set one
    set name of track 4 of playlist "Favorites" to "Everlong"
  end tell
TIP: In AppleScript, a line starting with a pair of dashes (--) is a comment, there for your own reference and the edification of others reading your code. The AppleScript interpreter ignores comments, so we encourage you to comment liberally.

The AppleScript copy command, which I used in the statement with get in the previous example, is similar to the set command. Notice that their syntax appears inverted. A set statement assigns a variable to a value:

  set thisVariable to someValue

whereas copy assigns a value to a variable:

  copy someValue to thisVariable

Because there are some situations in which their usages are not interchangeable (situations that are a bit too advanced to explain here) I got into the habit of using set exclusively. You should, too.

Conditionals. You can determine how the script will behave by testing whether certain conditions are met by way of a conditional statement. By far, the most common conditional across programming languages is the if...then statement—literally, “if the result of an expression is true, then do something.”

The following snippet of code tells iTunes to play if it is currently paused:

  tell application "iTunes"
    if player state is paused then play
    end tell

And this bit of code instructs iTunes to delete the “Black Sea” playlist if it is empty (literally, “if the number of tracks is zero”):

  tell application "iTunes"
    if (count tracks of playlist "Black Sea") is 0 then delete playlist "Black Sea"
  end tell

In much the same way that you can group together several statements in a tell block, you can also create compound conditional statements, causing all of the enclosed statements to be run if the if condition is true.

This code checks to see if the playlist "Mom's Favorites" is set to shuffle. If not (that is, if the statement shuffle of playlist “Mom‘s Favorites” is false is true), iTunes is instructed to turn on shuffling for “Mom’s Favorites” (i.e., set the shuffle property to true) and play it:

  tell application "iTunes"
    if shuffle of playlist "Mom's Favorites" is false then
      set shuffle of playlist "Mom's Favorites" to true
      play playlist "Mom's Favorites"
    end if
  end tell

A compound block ends with an end if statement.

TIP: Notice that the if...end if block is contained within the tell...end tell block. This is called nesting and is rather common practice in scripting logic.

You can also use else to provide an alternative task if the initial if condition is not true. Here, for example, if mute is not true (i.e., audio is not muted), go ahead and mute the sound now:

  tell application "iTunes"
    if mute is true then
      set mute to false
    else -- if mute is not true
      set mute to true
    end if
  end tell

The else terminates the initial if block in much the same manner an end if would, but further states that there’s an alternative coming up. The end if then closes the else block.

When an if statement offers an alternative using an else statement, the flow of the script is said to branch to either the if or the else clause.

You can offer more alternatives using else if:

  tell application "iTunes"
    if player state is paused then
    else if player state is playing then
    end if
  end tell

In this script, there are three possible branches. If neither of the conditions in the if or else if statements are true, then the final else clause is executed no matter what. You can use as many else if clauses as you require.

Repeat loops. A repeat loop iterates over a set of statements a certain number of times, on each item in a collection of objects, or while a certain condition is true. AppleScript provides repeat loops for each of these occasions.

In the course of the hacks in this chapter, we will most often be using a repeat loop to perform a set of tasks on each item in a list. A list, as the name suggests, is a collection of items (strings, numbers, object references, other lists, etc.) delimited by commas and held within braces, like so:

  -- text strings:
  {"Come Together", "Something", "Maxwell's Silver Hammer"}
  -- numbers:
  {1, 456, 27}
  -- references:
  {file track id 4100, file track id 4099, file track id 4098}
  -- combination:  {2,"cute to be",4,"got","ten"}

The lists you use in your interactions with iTunes usually contain track or playlist references.

To briefly illustrate how various repeat loops work, let’s suppose you want to change the artist’s name for every track in a playlist to Talking Heads. The first task is to get the list of tracks in the playlist. The following code sets a variable called theList to a list of references to every track in the “Talking Heads Songs” playlist:

  tell application "iTunes"
    set theList to every track in the playlist "Talking Heads Songs"
  end tell

Each track reference in theList is an item of that list. Now we can loop through each item in the following ways.

Here, each item in theList is assigned to the variable thisTrack on each loop:

  tell application "iTunes"
    set theList to every track in the playlist "Talking Heads Songs"
    repeat with thisTrack in theList
      set thisTrack's artist to "Talking Heads"
    end repeat
  end tell

Here, the variable i is automatically incremented on each loop and is used to target each item in the list successively:

  tell application "iTunes"
    set theList to every track in the playlist "Talking Heads Songs"
      repeat with i from 1 to (count items in theList)
        set artist of item i of theList to "Talking Heads"
      end repeat
  end tell

This repeat loop references the tracks in the playlist directly and does not use the list variable at all:

  tell application "iTunes"
    repeat with i from 1 to (count every track of playlist "Talking Heads Songs")
      name of track i of playlist "Talking Heads Songs"
    end repeat
  end tell

Many of the scripts in this book use variations of these repeat blocks. I provide greater detail when discussing a script that uses a repeat loop.

Consulting the dictionary. An application’s AppleScript Dictionary describes all the objects and commands that the application understands. It’s generally useful to take a look at the Dictionary before you start scripting. You can access iTunes’s AppleScript Dictionary, shown in Figure 5-5, in one of two ways: click on Open Dictionary in Script Editor’s File menu and select iTunes from the list of applications that appears, or drag the iTunes icon to Script Editor’s icon in the Finder or the Dock.

Figure 5-5. iTunes 4.5’s AppleScript Dictionary
Figure 5-5. iTunes 4.5’s AppleScript Dictionary

In Figure 5-5, the column on the left side of the window lists the various AppleScript classes (objects) and commands that iTunes understands. The track object is selected, and its properties are displayed in the right column.

Basic Debugging

No matter how well you know your AppleScript syntax, your script will generate errors while you are developing it and trying to get it to work properly. Script Editor has a couple features that will help you observe how a script is working so that you can see results, spot trouble, trap errors and problems, and eliminate a lot of the guesswork (although guesswork will always go on!).

You will want to be able to see the final results of any script actions, so click on the Result tab. You can resize this window so that you have easy visual access to it while working on your script in the main Script Editor window. The Result window always displays the last result from the Script window, as shown in Figure 5-6.

Figure 5-6. The Result window
Figure 5-6. The Result window

To see how a script is interpreted by AppleScript as it’s running, click the Event Log tab. When you run a script from Script Editor, the Event window (see Figure 5-7) will display each command as it’s interpreted by Apple- Script and each result (when available). This is particularly helpful in refining your syntax or figuring out where a bad script has gone wrong.

Figure 5-7. The Event window
Figure 5-7. The Event window

The iTunes Scripts menu

You need to put AppleScript script files for use with iTunes in a special folder so that they will be accessible from the iTunes Scripts menu.

To make iTunes scripts available to all users of your Mac, create a folder called Scripts in the /Library/iTunes folder.

To make iTunes scripts available only to a particular user of your Mac (most likely you), make a Scripts folder in that user’s personal /Library/iTunes folder (i.e., /Users/username/Library/iTunes, where username is the user’s login name).

After creating the Scripts folder, the next time you launch iTunes you will see the AppleScript menu bar icon appear magically between the Window and Help drop-down menus.

Compiled and application scripts in the Scripts folder will appear in iTunes’s Scripts menu. Scripts saved as an Application Bundle cannot be accessed via the iTunes Scripts menu. (We will be using and writing both compiled and application scripts.)

You can organize your scripts to some degree by placing them in folders inside your Scripts folder—one folder deep. You can also use aliases to scripts that are stored outside the Scripts folder. This might be helpful to you in the Finder, but the scripts will still appear in one long list in the iTunes Scripts menu.

Another trick for staying organized in the Scripts menu is to use various alphanumeric prefixes in your script names, such as spaces, underscores, bullets (Option-8), or degrees (Shift-Option-8). This groups like-prefixed scripts together by various alphanumeric strata in the Scripts menu. I am not aware of a maximum limit on the number of scripts you can put in your Scripts folder. I have had as many as 288, and no evil was visited upon me.

Alternatives to the iTunes Scripts menu

In addition to iTunes’Scripts menu, you can also use the system wide Scripts menu. This is handy for accessing iTunes scripts if iTunes is not the front most application. You add scripts to the Finder’s Scripts menu by putting them in /Library/Scripts (for all users) or /Users/username/Library/Scripts (for individual users). As with iTunes, once you create the folder, a drop-down menu with the AppleScript icon appears in the Finder menu bar.

TIP: If the Scripts menu was not installed with your system, download it for free from Apple at www.apple.com/applescript/scriptmenu. The installer should also be located in /Applications/AppleScript/. Simply run the Install Script Menu script located within that folder to install the system wide Script menu.

You can drag and drop AppleScript applets (scripts saved as self-contained applications) to the Finder’s toolbar for easy access.

Dock and launcher applications are handy for firing scripts, too. I use the venerable DragThing ($29.00; trial version available) to run compiled scripts.

There are also several applications that allow you to assign shortcut keys to AppleScript applets. These include iKey ($20.00; free trial version available) and QuicKeys ($99.95; trial version available).

Final Thoughts

You now have the basic tools for manipulating iTunes with AppleScript, and the scripts that lie ahead will reveal to you the range of tasks that you can accomplish with it. We will discuss each new concept as it comes.

—Doug Adams

Hadley Stern is a designer, writer, and photographer residing in Boston.