Spotify Status - AppleScript to Python

Posted on
Mon Nov 19, 2018 12:30 am
Korey offline
User avatar
Posts: 813
Joined: Jun 04, 2008
Location: Henderson, NV

Spotify Status - AppleScript to Python

Anyway to convert this to python that will do the same thing?

The script is launched in indigo's attachments folder and tracks the status of Spotify.

Unfortunately it seems like I need to run:
Code: Select all
sudo killall -9 appleeventsd
in Terminal before it will update indigo :?

I modified this script: https://www.indigodomo.com/library/101/ to suit my needs..

Any of you python gurus want to take a stab at it? (or better yet develop a Spotify Plugin :wink: ).

Code: Select all

-- appTimeout is the lenght of time to wait for an application to respond
property appTimeout : 3

-- refreshRate is the frequency of variable updates
property refreshRate : 3


global appList
global appSetters
global arrayKeyList
global arrayValueList
global hdlrApp -- Perhaps this could be handled better. Just pretend it's not here.


-- The list of psudo key/value pairs that define what will be sent to Indigo
set arrayKeyList to {}
set arrayValueList to {}

-- Applist contains a list of apps and parameters (appName, Parameters), ...

-- This is the application list - used to identify what applications are running in each itteration.
-- Automatically creates a variable for "appnameIsRunning"
set appList to {"Spotify"}
set appSetters to {updateSpotifyProperties}

-- Get Spotify properties
on updateSpotifyProperties()
   tell application "Spotify"
      set strState to (get player state) as string
      set strTrack to (get name of current track) as string
      set strArtist to (get artist of current track) as string
      set strAlbum to (get album of current track) as string
   end tell
   setPropValue("SpotifyPlayerState", strState, false)
   -- There seems to be a problem - at least on my system.
   -- Instead of "playing" - when running inside of Indigo - the state is "«constant ****play»"
   -- We can assume play status based on the running status (both should be checked).
   set blnPlaying to (strState is equal to "playing" or strState is equal to "paused")
   -- set blnPlaying to true
   setPropValue("SpotifyIsPlaying", blnPlaying, false)
   setPropValue("SpotifyPlayerState", strState, false)
   if (blnPlaying) then
      setPropValue("CurrentPlaylist", strStation, false)
      setPropValue("CurrentArtist", strArtist, false)
      setPropValue("CurrentAlbum", strAlbum, false)
      setPropValue("CurrentTrack", strTrack, false)
   end if
end updateSpotifyProperties

-- Below this point is the core of the system, where the above are used to add new application interfaces as needed
-- Main event loop - check each related "app" for variable changes...
repeat
   -- update property values
   updateAppProperties()
   
   -- Save back to indigo
   updateIndigo()
   delay refreshRate
end repeat


-- Cycle through each of the applications and run the appropriate handlers to gather properties
on updateAppProperties()
   repeat with indx from 1 to length of appList
      set strApp to item indx of appList
      set hdlrApp to item indx of appSetters
      set blnRunning to isAppRunning(strApp)
      setPropValue(strApp & "IsRunning", blnRunning, true)
      
      try
         if blnRunning then
            with timeout of appTimeout seconds
               hdlrApp()
            end timeout
         end if
      end try
   end repeat
end updateAppProperties

-- Update properties to Indigo server
on updateIndigo()
   repeat with strKey in arrayKeyList
      set currentValue to getPropValue(strKey)
      try
         with timeout of appTimeout seconds
            tell application "IndigoServer"
               if not (variable strKey exists) then
                  make new variable with properties {name:strKey, value:currentValue}
               else
                  set indigoValue to (value of variable strKey)
                  if currentValue is not equal to indigoValue then
                     set value of variable strKey to currentValue
                  end if
               end if
            end tell
         end timeout
      end try
   end repeat
end updateIndigo

-- Log information to IndigoServer
on IndigoLog(logString)
   try
      with timeout of appTimeout seconds
         tell application "IndigoServer" to log logString using type "IndigoStatus Updater"
      end timeout
   end try
end IndigoLog

-- Used to check to see if a specified application is currently running
on isAppRunning(strApp)
   try
      with timeout of appTimeout seconds
         tell application "System Events"
            if (get name of every process) contains strApp then
               return true
            end if
         end tell
      end timeout
   end try
   return false
end isAppRunning

-- Clean a string to only alphanumeric values (used to create Indigo variable names based on data, where necessary)
on cleanName(str)
   set goodChars to "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
   set strNew to ""
   repeat with i from 1 to length of str
      if character i of str is in goodChars then set strNew to strNew & (character i of str)
   end repeat
end cleanName

-- Get Key ID (from arrayKeyList)
on getKeyID(strKey)
   set strKey to strKey as string
   set intId to 1
   repeat with strName in arrayKeyList
      if strKey is equal to (strName as string) then return intId
      set intId to intId + 1
   end repeat
   set end of arrayKeyList to strKey
   set end of arrayValueList to ""
   return intId
end getKeyID

-- set Property Value (arrayValueList) based on key (arrayKeyList)
on setPropValue(strKey, strValue, bLogChange)
   set intId to getKeyID(strKey)
   if bLogChange then
      set prevValue to get item intId of arrayValueList
      if prevValue as string is not equal to strValue as string then
         IndigoLog(strKey & " Changed from \"" & prevValue & "\" to \"" & strValue & "\"")
      end if
   end if
   set item intId of arrayValueList to strValue
end setPropValue

-- get Property Value from arrayValueList (based on key in arrayKeyList)
on getPropValue(strKey)
   return get item (getKeyID(strKey)) of arrayValueList
end getPropValue


Thanks!

--
Korey

Posted on
Tue Nov 20, 2018 4:33 pm
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Spotify Status - AppleScript to Python

Untested since I don't have Spotify. Run this as an external script. Create a schedule that runs it however often you want it to update.

Code: Select all
'''
Some notes:
 - I've removed all the stuff in the script that tried to make it generic and just
   focused on the Spotify specifics
 - As part of the above, your variables must already exist
 - strStation was never set from Spotify in your script so I just skipped trying to set it
'''
import applescript

spotifyScript = '''
tell application "Spotify"
  set strState to (get player state) as string
  set strTrack to (get name of current track) as string
  set strArtist to (get artist of current track) as string
  set strAlbum to (get album of current track) as string
end tell
set blnPlaying to (strState is equal to "playing" or strState is equal to "paused")
set returnRec to {SpotifyPlayerState:strState}
set returnRec to returnRec & {SpotifyIsPlaying:blnPlaying as string}
if (blnPlaying) then
   set returnRec to returnRec & {CurrentArtist:strArtist}
   set returnRec to returnRec & {CurrentAlbum:strAlbum}
   set returnRec to returnRec & {CurrentTrack:strTrack}
end if

return returnRec
'''

a_script = applescript.AppleScript(source=spotifyScript)
reply = a_script.run()

for var_name, value in reply.items():
    indigo.variable.updateValue(str(var_name), value=value)

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Nov 20, 2018 7:24 pm
Korey offline
User avatar
Posts: 813
Joined: Jun 04, 2008
Location: Henderson, NV

Re: Spotify Status - AppleScript to Python

:D :D :D

Thats fantastic!

Next best thing to an actual plugin!

Works great!

Thanks Jay! :wink:

--
Korey

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 2 guests