After my last post I really wanted to explore AppleScript some more. So that’s what I did.
One thing I like to do is listen to podcast episodes in chronological order. That is to say episodes from different podcasts. But also one episode at a time. The podcasts I subscribe to average about 50 minutes per episode. I use these as a measure of time while working. When an episode finishes I know it is time to take a quick break, get up, walk around for a minute it two. I don’t want the default iTunes behavior of going straight into the next episode and have to pause it when I get up. Some people might say that there is a particular program which can already do this easily. I didn’t really feel like getting a new program to do it since I was already managing them in iTunes. And I wanted something to do in AppleScript. It seemed like a good candidate.
I wrote this script for iTunes 10. There are problems with it in iTunes 11 because iTunes appears to sometimes discard “played” state of individual episodes. Anyway, here it is.
tell application "iTunes" set podcastsPlaylist to some playlist whose special kind is Podcasts set allUnplayedPodcastEpisodes to tracks in podcastsPlaylist whose unplayed is true if (length of allUnplayedPodcastEpisodes) is 1 then play first item in allUnplayedPodcastEpisodes else if (length of allUnplayedPodcastEpisodes) is greater than 1 then set oldestPodcastEpisode to first item in allUnplayedPodcastEpisodes repeat with i from 2 to length of allUnplayedPodcastEpisodes set podcastEpisode to item i in allUnplayedPodcastEpisodes if release date of podcastEpisode comes before release date of oldestPodcastEpisode then set oldestPodcastEpisode to podcastEpisode end if end repeat play oldestPodcastEpisode end if end tell
My first post about AppleScript didn’t describe what the code does. Let’s do better with this post. People with little to no programming experience should still be able to understand it.
The first line,
tell application "iTunes", means to use the iTunes dictionary for subsequent lines. An AppleScript dictionary contains information about commands and types specific to a particular application.
set podcastsPlaylist to some playlist whose special kind is Podcasts, may look a little strange to those unfamiliar with AppleScript, but familiar with other languages. The expression
some playlist whose special kind is Podcasts searches all instances of the type
playlist and returns the first one it finds with
special kind of
Podcasts. It turns out the only playlist with
special kind of
Podcasts is the official podcast playlist containing all episodes. The result is then set to the variable
The third line,
set allUnplayedPodcastEpisodes to tracks in podcastsPlaylist whose unplayed is true, similarly takes care of many details for you. The expression
tracks in podcastsPlaylist whose unplayed is true finds and returns all unplayed episodes in the variable
podcastsPlaylist. (This is actually where the script trips up. iTunes appears to not save the unplayed value properly, and podcast episodes which I previously played appear unplayed.) The resulting list of that expression is then set to the variable
The next line,
if (length of allUnplayedPodcastEpisodes) is 1 then, is an optimization. Most of the work of the script is in searching for the oldest episode. When there is only one unplayed episode it is automatically the oldest. This line checks for that condition. When there is only one episode, the next line,
play first item in allUnplayedPodcastEpisodes, executes. The variable
allUnplayedPodcastEpisodes is a list, meaning there are multiple elements. List elements are normally accessed by index with index
0 being the first element, index
1 being the second, and so on. AppleScript has some shortcuts, one of which is accessing the first element. The line sends the
play command with that first element. The play command accepts a media object for iTunes to begin playing. The iTunes dictionary defines it, so it only works after a
tell application "iTunes" command.
The next line,
else if (length of allUnplayedPodcastEpisodes) is greater than 1 then, checks to make sure there are podcast episodes. If there aren’t any episodes there is no point to running any more code because in the end it wouldn’t do anything. The condition checks for more than one because it is clearer under what conditions the following code runs.
Now we’ve come to the interesting part. This is where we search for the oldest episode. Since the date of the oldest episode is unknown we must check every episode looking for the earliest date. A basic linear search is good for this. It goes through the list comparing each episode to the oldest known episode.
set oldestPodcastEpisode to first item in allUnplayedPodcastEpisodes starts the algorithm. When first starting there is no “oldest episode” so one needs picked. We use the first element in the list because it is easy to access.
The following line,
repeat with i from 2 to length of allUnplayedPodcastEpisodes, is the loop of what to look at. It tells the AppleScript interpreter to run the lines after it and before its corresponding
end repeat multiple times. The portion
with i says to use the variable
i to store a different value each iteration. The rest of the line,
from 2 to length of allUnplayedPodcastEpisode, says
i will start as 2 and end as the number of elements in
allUnplayedPodcastEpisode. Since it doesn’t define an increment, the value will increase by 1 each iteration. The first time an iteration runs
i will be 2, the second time it will be 3, and so on until it equals the number of elements in
allUnplayedPodcastEpisode. The first line within the loop,
set podcastEpisode to item i in allUnplayedPodcastEpisodes stores the episode the loop is examining into a variable to make it easy to refer to later. It really just makes the code more readable. Instead of having
item i in allUnplayedPodcastEpisodes every time we want to access the episode, we use the
The second line of the loop,
if release date of podcastEpisode comes before release date of oldestPodcastEpisode then finds the older episode. It compares the release date of the currently known oldest episode to the episode of the loop iteration. When the
release date of the iteration’s episode is before the oldest date the line inside the
set oldestPodcastEpisode to podcastEpisode, saves the iteration’s episodes as the oldest.
Once all elements of
allUnplayedPodcastEpisodes have been examined, the script has saved the oldest episode in the
oldestPodcastEpisode variable. At that point, we tell iTunes to play it by sending the
That’s all. I covered a lot of the basics of AppleScript. Feel free to ask any questions in the comments.