Use AppleScript to determine which media app is currently playing something (or was last paused), and have your PowerMate act accordingly

November 13, 2011

I earlier described how I configured my PowerMate to provide system-wide control of Spotify, and noted the ability of the PowerMate software to now run AppleScripts that can communicate with other apps, thus obviating the need for third-party "bridges."

A problem I ran into almost immediately with the setup described in the aforelinked post was that Spotify would start playing a track when I bopped my PowerMate to pause iTunes; you see, even though I'm now getting the majority of my music via Spotify, I'm still using iTunes for podcasts.

Because I wanted the PowerMate to control all media on my computer, I needed to give the AppleScripts some "intelligence" with respect to which app they should affect, depending on a few variables. Let's start with what ended up being the most involved script, the one for play/pause.

--Define the lastPaused property and give it a default value
property lastPaused : ""

--Get current states of iTunes and Spotify
tell application "iTunes" to set itunesState to (player state as text)
tell application "Spotify" to set spotifyState to (player state as text)

--Pause the active app; play the last-paused app
if itunesState is equal to "playing" then
    tell application "iTunes" to playpause
    set lastPaused to "iTunes"
else if spotifyState is equal to "playing" then
    tell application "Spotify" to playpause
    set lastPaused to "Spotify"
else if ((itunesState is equal to "paused") and (lastPaused is equal to "iTunes")) then
    tell application "iTunes" to playpause
else if ((spotifyState is equal to "paused") and (lastPaused is equal to "Spotify")) then
    tell application "Spotify" to playpause
end if

The reason this script is slightly more complicated than those for next track and 30-second skip (described below) is because it requires the maintenance of a variable across invocations of the script. Specifically, when playing a paused track we must determine which app--iTunes or Spotify--was last paused, so we know which app to tell to start playing again.

I struggled a bit with how to track this "last paused" descriptor, and ultimately resigned myself to maintaining it via a file. Though I got that solution working, I wasn't completely happy with it and asked my Twitter followers if there was a better way. @elasticthreads mentioned AppleScript's property construct and indeed it was exactly what I needed (and I was more than a little embarrassed I hadn't remembered it myself). (From the AppleScript Language Guide: "The value set by a property definition is not reset each time the script is run; instead, it persists until the script is recompiled." Perfect.)

The script first defines, and gives a default value to, the lastPaused property. (This value is set just once for each compilation of the script, which means, in practice, it likely will occur only during the script's initial run after a reboot.) Next, the script grabs the player states (e.g., paused, playing, stopped, etc.) of iTunes and Spotify so that we can work with them later.

Finally, the script determines if either app is currently playing a track; if so, it pauses that app and sets lastPaused to note that the app was paused. If neither app is currently playing, the script checks to see if either app is currently paused (as opposed to stopped) and currently "owns" lastPaused; if these two things are true for either app, it issues the play command to that app.

The next track script is similar, except that we don't need to remember the state of anything; all we need to do is determine which of the two apps is currently playing something (and one must be, else we wouldn't have reached for the PowerMate). With that in mind, the script doesn't involve iTunes at all if Spotify is active; I wrote it that way because 90% of the time I'm listening to music at my computer, not podcasts.

tell application "Spotify"
    if player state is equal to playing then
        next track
    else
        tell application "iTunes" to next track
    end if
end tell

The script logic for 30-second skip is the same as that for next track.

tell application "Spotify"
    if player state is equal to playing then
        set player position to (player position + 30)
    else
        tell application "iTunes" to set player position to (player position + 30)
    end if
end tell

You should follow me on Twitter here