Python to replace AppleScript targeting Apple Music

Use this forum to post specific questions you may have when trying to convert an AppleScript to Python. Answers may also include pointers to plugins that would help.
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Python to replace AppleScript targeting Apple Music

Post by Different Computers »

Since the iTunes plugin doesn't work any more, and iTunes Local Control doesn't return track info, and AirFoil Pro is flaky as hell on my network while AirPlay works just fine, I'm trying to figure out how to get track info into Indigo, including being able to trigger on play pause.

Anyone achieving this currently?

My fumbling and ChatAI-assisted attempt has gotten close, but still generates errors I can't work around:

Code: Select all

tell application "Music"
	set currentTrack to current track
	set trackName to name of currentTrack
	set artistName to artist of currentTrack
	set trackInfo to trackName & "|" & artistName
	
end tell

set pythonScript to "insert_track_info.py"
set pythonPath to "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3"
set scriptPath to quoted form of "/Library/Application Support/Perceptive Automation/Scripts/" & pythonScript
set trackInfo to trackName & "|" & artistName
#do shell script quoted form of pythonPath & " " & quoted form of scriptPath & " " & quoted form of trackInfo
do shell script quoted form of "/Library/Application Support/Perceptive Automation/Scripts/insert_track_info.py"
(This generates errors relative to the path, hence the two different tries at getting the path. The true error seems to be related to the various Python installs on and which should be used.)

That AppleScript is supposed to target this Python:

Code: Select all

import indigo
import sys

trackInfo = sys.argv[1]
trackName, artistName = trackInfo.split("|")

indigo.variable.updateValue(trackVariableId, value=trackName)
indigo.variable.updateValue(artistVariableId, value=artistName)
Apparently "import indigo" is a wrong answer from ChatAI?

My current thought about moving forward is super kludgy and would involve a repeating Indigo Schedule running every 15 seconds or so, running a python script that looks for changes in a file created by AppleScript with the Apple Music info I want, and that then updates variables if the file has changed.

Hopefully there's a better way. This seems like a thing someone out there who actually understands Python would already have working. :D
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

Is this stumbling in the right direction? Python modified from https://wiki.indigodomo.com/doku.php?id ... strategies

Code: Select all

tell application "Music"
	set currentTrack to current track
	set trackName to name of currentTrack
	set artistName to artist of currentTrack
	set trackInfo to trackName & "|" & artistName
	 return trackInfo

	
end tell

Code: Select all

import applescript

# From a file
path_to_script_file = "/Library/Application Support/Perceptive Automation/Scripts/Send_Current_Track_to_Indigo.scpt"
AscriptTrackInfo = applescript.AppleScript(path=path_to_script_file)
AscriptTrackInfo = AscriptTrackInfo.call("trackInfo")
Right now that's generating a "general" error. Maybe a path to the AppleScript problem?
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
jay (support)
Site Admin
Posts: 18351
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by jay (support) »

Yes, glad you read through that article.

Here's a couple of tweaks to keep you moving forward:

Code: Select all

import applescript

# From a file
path_to_script_file = "/Library/Application Support/Perceptive Automation/Scripts/Send_Current_Track_to_Indigo.scpt"
track_info_script = applescript.AppleScript(path=path_to_script_file)
reply = track_info_script.run()
track_name, artist_name = reply.split("|")

indigo.variable.updateValue(trackVariableId, value= track_name)
indigo.variable.updateValue(artistVariableId, value= artist_name)
Should be close though I didn't test it.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

Worked great!

I now have the track and Artist values in Indigo :lol:

Now to figure out how to trigger an update when the track changes.
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

Looks like I need to incorporate something like

Code: Select all

on trackChanged()
	tell application "Music"
		set currentTrack to current track
		set trackName to name of currentTrack
		set artistName to artist of currentTrack
		set trackInfo to trackName & "|" & artistName
		return trackInfo
		return trackName
		return artistName
	end tell
end trackChanged
on run
	-- This line registers the trackChanged() function to be called
	-- whenever the currently playing track changes
	set track_change_handler to trackChanged
	# tell application "Music" to set current track's name current track
end run
Hmmmm, no, that generates an error.

Code: Select all

  Script Error                    action group "Get Current Track Info" embedded script error:
   Script Error                    'NSAppleEventDescriptor' object has no attribute 'split'
   Script Error                    Exception Traceback (most recent call shown last):

     embedded script, line 7, at top level
AttributeError: 'NSAppleEventDescriptor' object has no attribute 'split'
Guessing the on run command is preventing the trackInfo from being preserved. Or something's not being passed properly.

That gets me to the AppleScript running whenever the track changes. I'd sure like to avoid polling to make the Python run.
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
jay (support)
Site Admin
Posts: 18351
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by jay (support) »

I don't know anything about registering functions and the Music AppleScript (that's not Python and I've never heard of it in AppleScript either - did you get that from ChatAI too?).

If you can get that to work, then you'd want to use the Indigo Control AppleScript approach to updating the variable. Basically, the AppleScript would be the one driving the update rather than the Indigo python script driving the change.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

yeah it seems to be a false lead.

ChatAI contradicted itself when I pointed out to it that it generated an error. Seems it confused a custom handler with one that had baked-in functionality.

I can't find any info on "trackChanged" in the Music dictionary or anywhere else.

But this works. However, I think I need to make it an application to keep it running.... and then I don't think the python script can get what it returns. Can it?

Code: Select all

property previousTrack : ""

on run
	set currentTrack to getCurrentTrack()
	if currentTrack is not previousTrack then
		set previousTrack to currentTrack
		trackChanged()
	end if
	my doEvery(5)
end run

on trackChanged()
	tell application "Music"
		set currentTrack to current track
		set trackName to name of currentTrack
		set artistName to artist of currentTrack
		set trackInfo to trackName & "|" & artistName
		return trackInfo
	end tell
end trackChanged

on getCurrentTrack()
	tell application "Music"
		set currentTrack to current track
		set trackName to name of currentTrack
		set artistName to artist of currentTrack
		set trackInfo to trackName & "|" & artistName
		return trackInfo
	end tell
end getCurrentTrack

on doEvery(interval)
	repeat interval times
		set currentTrack to getCurrentTrack()
		if currentTrack is not previousTrack then
			set previousTrack to currentTrack
			trackChanged()
		end if
	end repeat
end doEvery
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
jay (support)
Site Admin
Posts: 18351
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by jay (support) »

Please -don't use ChatAI for this sort of thing, it will lead you astray every time.

Your script doesn't do anything other than repeat 5 times in rapid succession (getting the track data), probably with a millisecond between calls (which will likely impact system performance if you let it runaway). It has nothing to do with changes in the track data. getCurrentTrack is just a duplicate of trackChanged so is unnecessary. Making it an application will not help in its current form.

You have two options as I see it:
  1. Write an AppleScript application that polls the Music app periodically (every few seconds) to see if there's been a track change and if there is update the Indigo variables
  2. Run the python script that you have running above in an Indigo Schedule that just periodically gets the track data and updates the variables
In either instance you are polling, the difference is that the AppleScript application is doing it in the first one and Indigo is doing it in the second one.

I personally would do the second - running a script like this every few seconds from a schedule is fine.

Note that in either case if someone quits the Music app it will just automatically relaunch (AppleScript does that automagically). If that's not the behavior you want, then you'll need to add some extra code to first check to see if the Music app is running before trying to do an AppleScript tell to it.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

I'm still fumbling along.

Relying more on stack overflow :wink:

So this works fine:

Code: Select all

tell application "Music"
	set myArtwork to first artwork of current track
	if format of myArtwork is JPEG picture then set myPicture to data of myArtwork
	set myFile to (open for access file ((path to desktop as text) & "some.jpeg") with write permission)
	set eof myFile to 0
	write myPicture to myFile
	close access myFile
end tell
But when I try to make the path something useful, it fails:

Code: Select all

set filePath to "/Library/Application Support/Perceptive Automation/Indigo 2022.1/Web Assets/public/x/test.png"
set fileRef to open for access filePath with write permission
tell application "Music"
	set myArtwork to first artwork of current track
	if format of myArtwork is JPEG picture then set myPicture to data of myArtwork
	set myFile to fileRef
	set eof myFile to 0
	write myPicture to myFile
	close access myFile
end tell
it gives error "File file Macintosh HD:Library:Application Support:Perceptive Automation:Indigo 2022.1:Web Assets:public:x:test.png is already open." number -49 from file "Macintosh HD:Library:Application Support:Perceptive Automation:Indigo 2022.1:Web Assets:public:sst:test.png"

Any help? inserting various "close access" commands in various places didn't seem to help.
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

I also tried

Code: Select all

set fileRef to (open for access filePath with write permission)
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

I probably shouldn't have been testing it when Music wasn't running. :oops:

Working now.
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Korey
Posts: 822
Joined: Wed Jun 04, 2008 11:47 am
Location: Henderson, NV
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Korey »

Did you find a way to return if Music is Playing / Paused / Stopped?

I'm still running indigo 2022.2 realizing that it is going to break the iTunes plugin if I upgrade. This would be a huge fail on the WAF. :(

Indigo with iTunes, Spotify and Airfoil is a core function of Indigo in our house.

Still running OSX 10.14 on a 2012 Mac mini, but looking at a M1 Studio down the road..

I need a way to tell if iTunes and eventually (Apple Music) is playing, I have a script for Spotify that does this and I run it every 10 seconds, one of the wonderful four members helped convert it to python ages ago. (it would be lovely to have a Spotify Plugin! )

Anyone know if it's possible to do this with Apple Music /iTunes with the new version of Py3 only Indigo?

Thanks!

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)
--
Korey
User avatar
jay (support)
Site Admin
Posts: 18351
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by jay (support) »

https://stackoverflow.com/questions/311 ... pplescript

You might also check the iTunes Local Control plugin, it may do (I don't know for sure).
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
Different Computers
Posts: 2600
Joined: Sat Jan 02, 2016 10:07 am
Location: East Coast
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Different Computers »

Korey,

I don't have anything that specifically checks for "running" et al. But I do have something that checks to see if track info has changed. put this script in an action group:

Code: Select all

import applescript

# From a file
path_to_script_file = "/Library/Application Support/Perceptive Automation/Scripts/Send_Current_Track_to_Indigo.scpt"
track_info_script = applescript.AppleScript(path=path_to_script_file)
reply = track_info_script.run()
track_name, artist_name = reply.split("|")

indigo.variable.updateValue(1336843372, value= track_name)
indigo.variable.updateValue(1192881436, value= artist_name)
The referenced AppleScript is:

Code: Select all

tell application "Music"
	if player state is playing then
		set currentTrack to current track
		set trackName to name of currentTrack
		set artistName to artist of currentTrack
		set trackInfo to trackName & "|" & artistName
		return trackInfo
	else
		return "It's quiet|Nothing playing"
	end if
end tell
Run that action group on whatever schedule you want.

You could capture the "It's quiet|Nothing playing" variable value to trigger things.
Sonoma on a Mac Mini M1 running Airfoil Pro, Bond Home, Camect, Roku Network Remote, Hue Lights, DomoPad, Adapters, Home Assistant Agent, HomeKitLinkSiri, EPS Smart Dimmer, Fantastic Weather, Nanoleaf, LED Simple Effects, Grafana. UnifiAP
User avatar
Korey
Posts: 822
Joined: Wed Jun 04, 2008 11:47 am
Location: Henderson, NV
Contact:

Re: Python to replace AppleScript targeting Apple Music

Post by Korey »

Thanks to you both!

I'll play with this once I have time!


:D
--
Korey
Post Reply

Return to “Help Converting from AppleScript”