Do-It-Yourself Time Machine for iTunes (Building year-based playlists)

Build Your Own Time Machine

No, I’m not talking about Apple’s Time Machine, which helps you backup your files. No, the time machine I’m talking about is a musical time machine. If, like me, you keep close track of the “year” field in your iTunes tracks, wouldn’t it be nice if you could just run an Applescript and have it randomly select a year and play some tracks? Or maybe you’d prefer to select a year yourself? For those that are familiar with a TV program called “Doctor Who,” you know that his time machine is called the TARDIS. If you have never seen “Doctor Who”, then just know that the TARDIS looks like a british police call box (phone booth) and is larger on the inside than it is on the outside. And sometimes it goes astray and winds up someplace the Doctor didn’t intend.

With that out of the way, let’s get to work building our time travel script. First, we need to survey your iTunes tracks and find out what years are available. Compiling this list is fairly easy, we simple ask for “set trackyears to year of file tracks of playlist ‘Music’.” This list will have lots of duplicates in it, which would bias the following selection of tracks toward those years with lots of tracks. We prefer a fairer distribution, so we create a repeat loop and a new list, adding only those years that aren’t already in the list. After this, we use the “some item” command to randomly select a year from our list.

That done, we need to check and see if the playlist we’re about to use exists already or if we need to create it. I’ve got several scripts that use that functionality in iTunes, so I’ve written a separate handler that I can just cut and paste into my iTunes scripts. “CreateList(‘TARDIS’,‘’)” tells the handler we want a playlist named ‘TARDIS’ but the empty quotes tells the handler we don’t want it placed in a folder, otherwise we’d supply the name of the folder.

Just for fun, I’ve set the script to start by playing the first 10 seconds of the Doctor Who theme to set the mood. If you’re a fan of the old TV series “Time Tunnel” you can use that theme instead and change the playlist name. Playing the music also helps fill the time it takes to sort the year list and select the tracks, so it’s also a useful diversion.

Since we build the list of available years instead of just picking a year that you might not have in your iTunes library, we’re assured of getting at least one track for the specified year. I’ve set my script to try and get ten unique tracks. But if the library has less than ten tracks, we just duplicate them to the playlist.

If we have more than ten tracks to choose from, we again use the “some item” command to randomly select tracks. Since we don’t want ten instances of the same track we need to check the track list to make sure the new track isn’t already there. If it is, we keep iterating the “repeat” loop until we get ten tracks that are unique. When finished, we duplicate the tracks to the playlist “TARDIS.”

At this point, we’re ready to play the list. Let’s stop the TV show theme and announce the year we’ve landed in! As a nice touch, let’s also show the user the playlist by revealing track 1 of the list.

You’ve successfully built your own musical time machine! Here’s the completed script:

tell application "iTunes"
	--For fun!
	play file track "Doctor Who Theme"
	--compile list of available years
	set tracklist to {}
	set trackyears to year of file tracks of playlist "Music"
	--cull out the duplicates
	repeat with aYear in trackyears
		if tracklist does not contain aYear then set end of tracklist to aYear
	end repeat
	set theYear to some item of tracklist
end tell
--if playlist exists, wipe it
--else create it
createList("TARDIS", "")
--populate list with songs from target year
tell application "iTunes"
	set tracklist to every file track of playlist "Music" whose year is theYear and kind is not "PDF Document"
	--if more than ten tracks, we'll randomly pick 10
	--otherwise we'll skip the repeat loop and just load the few tracks we have
	if length of tracklist > 10 then
		set done to false
		repeat until done
			set theTrack to some item of tracklist
			set theName to name of theTrack
			set theTest to every file track of playlist "TARDIS" whose name is theName
			if length of theTest = 0 then duplicate theTrack to playlist "TARDIS"
			set testTracks to count tracks of playlist "TARDIS"
			if testTracks = 10 then set done to true
		end repeat
	else
		duplicate every file track of tracklist to playlist "TARDIS"
	end if
	repeat until player position ≥ 10
	end repeat
end tell
tell application "iTunes" to stop
say "The Tardis has landed in the year " & theYear & "."
tell application "iTunes"
	play playlist "TARDIS"
	reveal track 1 of user playlist "TARDIS"
end tell


on createList(newlist, folderlist)
	-- check for my playlist and create if necessary
	tell application "iTunes"
		if exists playlist newlist then
			delete every file track of playlist newlist
		else
			if length of folderlist > 0 then
				make new user playlist at (folder playlist folderlist) with properties {name:newlist}
			else
				make new user playlist with properties {name:newlist}
			end if
		end if
	end tell
end createList

Building an Accurate Time Machine
Now, let’s look at another sort of time machine - one which you control. Rather than choosing a year randomly, you can input a year you would like to hear. Given that we already have the mechanics of choosing tracks based on the year, all we need to do is rewrite the beginning of the script so that instead it accepts a typed year from the user. I’ve put in some “try” statements to avoid any conversion error, faulty input, or years that don’t exist in the library. Here’s the finished script:

set theYear to (year of (current date)) --the default year
set success to false
tell application "iTunes"
	activate
	repeat until success
		display dialog "Set the WABAC Machine to year:" default answer theYear buttons {"Cancel", "Go!"} default button 2
		try
			--first see if it's a valid number
			set theYear to (text returned of the result) as integer
			set success to true
		on error
			display dialog "That wasn't a valid year."
			set success to false
		end try
		try
			--now see if we can find any tracks for that year
			set tracklist to every file track of playlist "Music" whose year is theYear
			if (length of tracklist) > 0 then
				set success to true
			else
				set success to false
				display dialog "No tracks for that year."
			end if
			
		on error
			display alert "Error reading tracks from iTunes."
			set success to false
		end try
	end repeat
end tell
if success then
	--if playlist exists, wipe it
	--else create it
	createList("WABAC Machine", "")
	--populate list with songs from target year
	tell application "iTunes"
		--use the tracklist to select some tracks
		set sometracks to true
		if length of tracklist ≥ 10 then
			set done to false
			repeat until done
				set theTrack to some item of tracklist
				set theName to name of theTrack
				set theTest to every file track of playlist "WABAC Machine" whose name is theName
				if length of theTest = 0 then duplicate theTrack to playlist "WABAC Machine"
				set testTracks to count tracks of playlist "WABAC Machine"
				--say (testTracks & " tracks") as text
				if testTracks = 10 then set done to true
			end repeat
		else if length of tracklist = 0 then
			display dialog "No tracks for this year."
			set sometracks to false
		else
			repeat with aTrack in tracklist
				duplicate aTrack to playlist "WABAC Machine"
			end repeat
		end if
		
		if sometracks then
			play playlist "WABAC Machine"
			reveal track 1 of user playlist "WABAC Machine"
		end if
	end tell
end if

on createList(newlist, folderlist)
	-- check for my playlist and create if necessary
	tell application "iTunes"
		if exists playlist newlist then
			delete every file track of playlist newlist
		else
			if length of folderlist > 0 then
				make new user playlist at (folder playlist folderlist) with properties {name:newlist}
			else
				make new user playlist with properties {name:newlist}
			end if
		end if
	end tell
end createList

To avoid confusion, I have named the second script “WABAC Machine” (“way back”) after the time machine that Mr. Peabody and Sherman used on “The Bullwinkle Show.” If you don’t know who they are, ask your parents, they’ll know.

You can script something similar using other criteria to filter your results (or for choosing at random). For example you can write a script to pull tunes with short durations, or play some tracks by artists whose name starts with a random letter. You get the idea.

Now you can sit back and listen to songs from a particular year as if you were listening to an old radio station (one with no commercials). If you use Apple’s speech recognition, you can put these scripts in your “Speakable Items” folder and impress your friends by showing off something that even Windows 7 can’t do.

That’s all. Go crunch some code!

Very nice, indeed, Kevin. I’ve moved it to unScripted as you can see. :smiley: