Control iTunes and Spotify with one script

Hey guys!

I’ve been switching between iTunes and Spotify to play my music and ” being an avid user of Quicksilver ” I felt the need to have one, universal script to control playback of both these apps.

I came up with something that actually works (that’s a bit of an achievement for me, I don’t consider myself even remotely adept in AS). I’m posting it here so you can have a look (maybe someone finds it useful?) and help me answer the following questions:

  1. Does it even make sense to write such a thing?
  2. Is the code clean and elegant? If not, what should I change?
  3. Can someone take a look at that maze of if statements? They make me go a bit like this :slight_smile:
  4. There is one major flaw in the logic (that I’m aware of): if both iTunes and Spotify are running and if they were paused not by the script, it doesn’t know which app it should resume playback for. Any ideas how to fix it?

Thanks for reading so far! Now, onto the behemoth:

property itun : "iTunes"
property spot : "Spotify"
property blackStar : «data utxt2605» as Unicode text
property whiteStar : «data utxt2606» as Unicode text
property appNames : {itun, spot}
property random : random number from 100 to 99999
property newFile : (POSIX path of (path to home folder) & ".Trash/" & random & ".jpg") as string
property apps : (POSIX path of (path to applications folder)) as string

set AppleScript's text item delimiters to "\\|"
set expression to appNames as string
set AppleScript's text item delimiters to ""
set runningApps to every paragraph of (do shell script "ps -acwx -o command | grep -ix " & quoted form of expression & " || echo 'true'")

using terms from application "iTunes"
	if (count of runningApps) > 1 then
		if player state of application spot is playing then
			set lastplayed to spot
			tell application "Spotify" to pause
			
		else if player state of application itun is playing then
			set lastplayed to itun
			tell application itun to pause
			
		else if player state of application itun is paused then
			if lastplayed is itun then
				tell application itun to play
				my notify(itun)
			else if lastplayed is spot then
				tell application "Spotify" to play
				my notify(spot)
			else
				tell application itun to play
				my notify(itun)
			end if
			
		else if player state of application spot is paused then
			if lastplayed is spot then
				tell application "Spotify" to play
				my notify(spot)
			else if lastplayed is itun then
				tell application itun to play
				my notify(itun)
			else
				tell application itun to play
				my notify(itun)
			end if
			
		else
			set lastplayed to null
		end if
		
	else if runningApps is {spot} then
		if player state of application spot is paused then
			tell application "Spotify" to play
			my notify(spot)
		else if player state of application spot is playing then
			tell application "Spotify" to pause
			set lastplayed to spot
		end if
		
	else if runningApps is {itun} then
		if player state of application itun is paused then
			tell application itun to play
			my notify(itun)
		else if player state of application itun is playing then
			tell application itun to pause
			set lastplayed to itun
		end if
	else
		my nothingPlaying()
	end if
	
end using terms from

on notify(appName)
	if appName is itun then
		set {cover, starDisplay} to iTunesStuff()
	else if appName is spot then
		set {cover, starDisplay} to my spotifyStuff()
	end if
	tell application appName
		using terms from application "iTunes"
			set {tname, aName, alName} to {name, artist, album} of current track
			my growl(tname, aName, alName, starDisplay, cover)
		end using terms from
	end tell
end notify

on iTunesStuff()
	tell application "iTunes"
		if (count of artwork of current track) ≥ 1 then
			tell me to set fileRef to (open for access newFile with write permission)
			write (get raw data of artwork 1 of current track) to fileRef starting at 0
			tell me to close access fileRef
			set art to newFile
		else
			set art to apps & "iTunes.app/Contents/Resources/iTunes.icns"
		end if
		set rate to rating of current track
		my calcrating(rate)
		return {art, my calcrating(rate)}
	end tell
end iTunesStuff

on spotifyStuff()
	tell application "Spotify"
		set {art, rate} to {artwork, popularity} of current track
		if art is not missing value then
			tell me to set fileRef to (open for access newFile with write permission)
			write art starting at 0 to fileRef
			tell me to close access fileRef
			set art to newFile
		else
			set art to apps & "Spotify.app/Contents/Resources/icon.icns"
		end if
		my calcrating(rate)
		return {art, my calcrating(rate)}
	end tell
end spotifyStuff

on calcrating(rate)
	set stars to (rate div 20)
	if rate is greater than 0 and stars is equal to 0 then
		set stars to 1
	end if
	set starDisplay to "" as Unicode text
	repeat with i from 1 to stars
		set starDisplay to starDisplay & blackStar
	end repeat
	repeat with i from stars to 4
		set starDisplay to starDisplay & whiteStar
	end repeat
end calcrating

on growlRegister()
	tell application "Growl" to register as application "Song Info" all notifications {"Song Info", "Error"} default notifications {"Song Info", "Error"} icon of application "iTunes"
end growlRegister

on growl(aName, tname, alName, pop, art)
	my growlRegister()
	tell application "Growl" to notify with name "Song Info" title aName & " ” " & tname description alName & return & pop application name "Song Info" priority 0 image from location art
end growl

on nothingPlaying()
	my growlRegister()
	tell application "Growl" to notify with name "Error" title "There is no song playing." description "Press play on tape." application name "Song Info" priority 2 image from location apps & "iTunes.app/Contents/Resources/English.lproj/ParentalAdvisory.png"
end nothingPlaying

I was looking for a scripted solution like this (to use with Keyboard Maestro) and found yours. Sorry that I can’t offer any help to improve the script as I also am a novice scripter “ so just wanted to say thanks for the useful script.

Hi Pe8er,

Looking in the iTunes dictionary right off the bat:

So, if iTunes is the app you want to toggle play or pause, then you should be able to use ‘playpause’ instead of checking if it is playing or paused.

gl,
kel

Hi,

Another thing I remember is that you can tell if an app is running with ‘running’ (a property of every application. e.g.:

tell application "iTunes"
	running
end tell

Edited: also almost forgot this. If both apps are running, then which one would you like to toggle? I don’t have Spotify, so can’t write a script with it.

gl,
kel