A better iTunes status AppleScript code

Recently I created a script object that returns an iTunes status message. This script snippet can come in handy when you plan to write your own custom AppleScript solution for showing the world what you are currently listening to in iTunes (in your eMail signature, in iChat, on your website, you name it).

Now you don’t need to waste your time and write your own custom routine to ask iTunes for the track informations. Just open the long scriplet below in your Script Editor, copy the whole script object to your code and use it like follows:


set curstat to my iTunesStat's getcurstat()

The script object so far supports detailed status messages for file tracks, audio CD tracks and URL tracks. Only shared tracks are not yet supported, as they are evil (you never know, what a shared track really is: a file track, an URL track?).

If a playing track does not offer all necessary informations, the script will nevertheless choose an appropriate status message. Here is an example:

If all necessary track infos (title, artist, album) are available, a complete status message like follows will be returned:
“I am currently listening to Me & Mr. Jones by Amy Winehouse from the album Back to Black.”

If the album name is missing, the script chooses another status message template:
“I am currently listening to Me & Mr. Jones by Amy Winehouse.”

Of course, all status message templates can easily be edited in the script object.

The script code was successfully tested on Mac OS X 10.5.2 using iTunes 7.6.2, but will most probably also work on earlier versions. Just give it a try.


-- created: 18.03.2008

-- The getcurstat function of the iTunesStat script object will return an iTunes
-- status message like "iTunes is currently not running on my Mac."
-- The various status message templates can be edited. iTunesStat currently
-- supports detailed status messages when a local file track/audio CD track
-- or URL track is playing. shared tracks are not yet supported.

my iTunesStat's getcurstat()

script iTunesStat
	-- Status Message Templates
	-- iTunes is not running / playing
	property statmsg_itnotrunning : "iTunes is currently not running on my Mac."
	property statmsg_itnotplaying : "iTunes is currently not playing on my Mac."
	-- iTunes is playing a local file track/audio CD track
	-- statmsg_titartalb > title, artist & album information is available for the currently playing track
	-- statmsg_artalb > only artist and album information is available for the currently playing track
	-- ...
	property statmsg_titartalb : "I am currently listening to $title$ by $artist$ from the album $album$."
	property statmsg_titart : "I am currently listening to $title$ by $artist$."
	property statmsg_titalb : "I am currently listening to $title$ from the album $album$."
	property statmsg_artalb : "I am currently listening to a song  by $artist$ from the album $album$."
	property statmsg_alb : "I am currently listening to a song from the album $album$."
	property statmsg_art : "I am currently listening to a song by $artist$."
	property statmsg_tit : "I am currently listening to a song named $title$."
	-- no track info at all :(
	property statmsg_unknown : "I am currently listening to a very mysterious song."
	-- iTunes is playing an internet stream/radio
	property statmsg_iradio : "I am currently listening to the internet stream $stream$ at <$url$>."
	-- iTunes is playing an unsupported track class, hence a shared track
	-- shared tracks are evil!
	property statmsg_unsupported : "I am currently listening to an unsupported track class and enjoying it!"
	
	-- I am the main function of this script object and return the current iTunes status
	on getcurstat()
		if not my appisrunning("iTunes") then
			set curstat to statmsg_itnotrunning
		else
			if not my itunesisplaying() then
				set curstat to statmsg_itnotplaying
			else
				set curtrack to my getcurtrack()
				set curstat to my getstatmsg(curtrack)
			end if
		end if
		return curstat
	end getcurstat
	
	-- I am indicating if a given application is currently running or not
	-- only the (full) application name must be given, e.g. "Address Book"
	on appisrunning(appname)
		tell application "System Events"
			set processnames to name of every process
		end tell
		if appname is in processnames then
			return true
		else
			return false
		end if
	end appisrunning
	
	-- I am indicating if iTunes is currently playing or not
	on itunesisplaying()
		tell application "iTunes"
			if player state is playing then
				return true
			else
				return false
			end if
		end tell
	end itunesisplaying
	
	-- I am returning the currently playing track in iTunes
	on getcurtrack()
		tell application "iTunes"
			return current track
		end tell
	end getcurtrack
	
	-- I am returning an iTunes status message based on the given track
	on getstatmsg(ittrack)
		-- getting infos about the given track
		tell application "iTunes"
			if class of ittrack is file track or class of ittrack is audio CD track then
				set trackclass to (class of ittrack) as Unicode text
				set tracktit to name of ittrack
				set trackart to artist of ittrack
				set trackalb to album of ittrack
			else if class of ittrack is URL track then
				set trackclass to (class of ittrack) as Unicode text
				set trackstr to name of ittrack
				set trackurl to address of ittrack
			else
				set trackclass to "unsupported"
			end if
		end tell
		-- creating the status message
		if trackclass is "file track" or trackclass is "audio CD track" then
			-- determining which track information is available
			set availinfo to ""
			if tracktit is not missing value and tracktit is not "" then
				set availinfo to availinfo & "tit"
			end if
			if trackart is not missing value and trackart is not "" then
				set availinfo to availinfo & "art"
			end if
			if trackalb is not missing value and trackalb is not "" then
				set availinfo to availinfo & "alb"
			end if
			log availinfo
			-- choosing the appropriate status message template 
			-- based upon the available track information
			if availinfo is "" then
				set tmpstatmsg to statmsg_unknown
			else if availinfo is "titartalb" then
				set tmpstatmsg to statmsg_titartalb
			else if availinfo is "titart" then
				set tmpstatmsg to statmsg_titart
			else if availinfo is "titalb" then
				set tmpstatmsg to statmsg_titalb
			else if availinfo is "artalb" then
				set tmpstatmsg to statmsg_artalb
			else if availinfo is "alb" then
				set tmpstatmsg to statmsg_alb
			else if availinfo is "art" then
				set tmpstatmsg to statmsg_art
			else if availinfo is "tit" then
				set tmpstatmsg to statmsg_tit
			end if
			-- inserting the track information into the status message template
			set statmsg to my tagstoinfos(tmpstatmsg, {"$title$", "$artist$", "$album$"}, {tracktit, trackart, trackalb})
		else if trackclass is "URL track" then
			set tmpstatmsg to statmsg_iradio
			set statmsg to my tagstoinfos(tmpstatmsg, {"$stream$", "$url$"}, {trackstr, trackurl})
		else
			set statmsg to statmsg_unsupported
		end if
		return statmsg
	end getstatmsg
	
	-- I am replacing found tags in a text with the corresponding infos
	-- I am a silly, but working template engine :)
	on tagstoinfos(txt, tags, infos)
		set counttags to length of tags
		repeat with i from 1 to counttags
			set tag to (item i of tags) as Unicode text
			set info to (item i of infos) as Unicode text
			set txt to my searchnreplace(tag, info, txt)
		end repeat
		return txt
	end tagstoinfos
	
	-- I am a very old search & replace function, that my master
	-- Martin still likes to use
	-- This time I am working as a slave for the template engine
	-- above
	on searchnreplace(searchstr, replacestr, txt)
		considering case, diacriticals and punctuation
			if txt contains searchstr then
				set olddelims to AppleScript's text item delimiters
				set AppleScript's text item delimiters to {searchstr}
				set txtitems to text items of txt
				set AppleScript's text item delimiters to {replacestr}
				set txt to txtitems as Unicode text
				set AppleScript's text item delimiters to olddelims
			end if
		end considering
		return txt
	end searchnreplace
end script

Alternatively, save the contents of the script object as a separate script file and load it into your own script(s) at run time as follows:

set iTunesStat to (load script file ("your:path:here:" & "Martin's iTunes status script.scpt"))

iTunesStat's getcurstat()

“I am currently listening to $title$ by Djavan from the album Coisa De Acender.” :confused:

Trying your script on my Jaguar machine revealed a very strange delimiter bug on that system that I’d never noticed before. (I haven’t tried it in Tiger yet.) If the main text is a string, AND the delimiter is Unicode text, AND the delimiter is in a list, then the delimiter doesn’t work when getting the text items! In these two handlers from the script:

on tagstoinfos(txt, tags, infos)
	set counttags to length of tags
	repeat with i from 1 to counttags
		set tag to (item i of tags) as Unicode text
		set info to (item i of infos) as Unicode text
		set txt to my searchnreplace(tag, info, txt)
	end repeat
	return txt
end tagstoinfos

on searchnreplace(searchstr, replacestr, txt)
	considering case, diacriticals and punctuation
		if txt contains searchstr then
			set olddelims to AppleScript's text item delimiters
			set AppleScript's text item delimiters to {searchstr}
			set txtitems to text items of txt
			set AppleScript's text item delimiters to {replacestr}
			set txt to txtitems as Unicode text
			set AppleScript's text item delimiters to olddelims
		end if
	end considering
	return txt
end searchnreplace

. ‘tag’ and ‘info’ ” but not ‘txt’ ” are coerced to Unicode text. (‘txt’ comes from one of the script’s pre-defined properties and is a string by default on pre-Leopard systems.) In searchnreplace(), ‘tag’ becomes ‘searchstr’ and the delimiters are set to it-in-a-list. Because of the bug, the "$title$ tag isn’t cut from ‘txt’ and so isn’t replaced with the track name when ‘txtitems’ is coerced to Unicode text a couple of lines later. However, this Unicode text becomes ‘txt’ in the next round, so the bug doesn’t kick in any more and the artist and album names are successfully substituted for those tags. :slight_smile:

To get round the bug, either: don’t coerce ‘tag’ to Unicode text, or: coerce ‘txt’ to Unicode text too, or: don’t set the delimiters as a list.

Edit: I can confirm this morning that the above-mentioned bug doesn’t affect Tiger and that Martin’s script works perfectly there as posted. :slight_smile: