Sending a media command to a browser window

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
radiocam
Posts: 2
Joined: 25 Mar 2019, 10:14

Sending a media command to a browser window

25 Mar 2019, 10:35

Hi,
I've been looking for a way to send a play command to a (Chrome) browser window - but that sounds vague, so I better explain:

I've been trying to get a Spotify playlist to play automatically. Spotify gives you an URL to the playlist, and when you activate the URL, typically the default browser opens a windows displaying the Spotify playlist - but requires an extra click on a standard media "Play" control in the browser.
It occurred to me that I might be able to get AHK to do this. I haven't tried this at all, it only just occurred to me today and I thought I might ask before starting to fiddle around, in case someone has done this or has a script with a different approach.
It certainly is a question that gets asked frequently on Spotify user forums, (not with AHK, just a general need to play the list automatically).
Without diving into the page source yet, I am pretty sure this would be an instance of standard HTML media player controls. ie. I doubt there's anything specific to Spotify, it probably has some setting disallowing autoplay.

PS: Please note that the term autoplay can be misleading in the Spotify context because they have an "Autoplay" setting that gets tossed up in any Google search. This is different, and refers to whether at the end of a playlist Spotify goes into a mode where it keeps on playing "similar" songs. NOt what I'm after. My question is about getting the playlist to start playing when the page opens. (More like "Autostart" than "Autoplay", I guess)

Cheers, and thanks
gregster
Posts: 9014
Joined: 30 Sep 2013, 06:48

Re: Sending a media command to a browser window

25 Mar 2019, 11:55

It's not that easy, I think. You could just send a Space key, but that would just press the play button at the bottom of the screen and play whatever was last played in Spotify and not the playlist.

Instead, after identifying that you opened a new spotify window/playlist (perhaps via SetTimer and wintitle of the Chrome browser), you probably will have to find the green Play button under the image of the playlist or the > button in the middle of the playlist image. You could probably try this via ImageSearch or just clicking certain hardcoded coordinates (but the Chrome window needs to be visible for this).

More elegant (and reliable) would be to automate the Chrome browser via the Chrome.ahk library. I already played around a bit with this library in combination with Spotify, so I might have some code lying around that, after a little tweaking, might allow to do this (even if the window is in the background...) - I could look for it tomorrow, if you are interested. But you should clarify how you want "to activate the URL" ...? Are you clicking it when you are already in Chrome? Otherwise, it could be tricky with this technique.

But perhaps I miss an easier solution... if you are a Spotify paying member, this is probably also possible via the official Spotify API interface, but I haven't tried that, so far.
radiocam
Posts: 2
Joined: 25 Mar 2019, 10:14

Re: Sending a media command to a browser window

27 Mar 2019, 01:17

Hi gregster,
Thanks very much for a most helpful reply. Which has now got me off my you-know-what and thinking a bit deeper - rather than looking for the quick fix...

Forgive me if this proves a bit long-winded, but if I explain my starting point, it will give you an idea of how wide my parameters are.
Simple objective: To have my Windows PC wake me up with music.
I've had this working for years, initially playing song files, then internet radio stations (like the wonderful Radio Paradise), itunes playlists (->vbs scripts), et al.
But I'm a big Spotify user now and yes, I have a paid subscription. So I wanted to be able to wake up to any of my zillion playlists in Spotify.

Core program that does the job these days is a 3rd party Windows scheduler utility called System Scheduler (one of many schedulers available), with a very good interface and diagnostics.
Why I went the way of Chrome/Spotify is that I have this pretty impressive Win application installed, called Unified Remote. A client-server setup, with the client on my phone. And an amazing range of functionality: PC controls, keyboard, media controls.. it is a very well thought out and implemented application
But.. not what I want, because it needs me to use the phone like a remote. I want this automated.
So.. I thought AHK could simply mimic the command that Unified Remote sends to my open-but-waiting Spotify window in Chrome.
But even with that, you alerted me to something I had not realized: the play command only plays the last song played - which could be a different playlist of course.
The Chrome window being open does not bother me, this is on my PC - but I do agree, there are more elegant solutions beckoning:

1. I didn't know there's a Chrome library for ahk (I have not dabbled in it for a very long while) - and thank you! any old code you have lying around would be very helpful to get a feel for how I may be able to use it.

2. There also are Spotify URIs that typically look like this: spotify:user:fred:playlist:7ptUWoHNjmiU0zwiWA90pk . These seem to use the APIs, because I can start the app in windows from a command prompt using this URI and it opens Spotify (the program) onto the playlist - but not autoplaying. I will explore the possibility of an API parameter that says "Autoplay" but from the myriad discussions on the topic, I don't think I will find one. So it may be that I use a more direct ahk approach.
Not through a Chrome layer but directly in the Spotify app window, still probably having to locate the play button and activate it.

Any thoughts that you have on this - or old experimentation code - will be most welcome. You've certainly got me going on this and I thank you for that ;)
What I meant by having wide parameters is that this is just for running on my PC, doesn't need to be generalized, so I can customize as much as required (permissions. environment, etc)

Cheers - and thanks again
gregster
Posts: 9014
Joined: 30 Sep 2013, 06:48

Re: Sending a media command to a browser window

27 Mar 2019, 02:11

Alright, now I have a clearer picture. I will test a bit with the code I already have (iirc I automated the "normal" player controls) and then probably come back to this topic in the next 1-2 days... I am interested in further exploring the possibilities of automating the Chrome browser anyway - and creating general helper functions for the Chrome.ahk library. But if I understand you correctly, this should be possible (we might have to look at some details).

Ps.: This Unified Remote app sounds interesting. I might take a look at it, even if it is not relevant for this problem ;) .
gregster
Posts: 9014
Joined: 30 Sep 2013, 06:48

Re: Sending a media command to a browser window

30 Mar 2019, 03:59

OK, played around a bit - the basic code with the Chrome.ahk library was quite simple - but I encountered two obstacles.

When I tested yesterday, the code worked well with albums, but I often got 'not found' messages when I tried to open playlist URLs - but this seemed to be a (local?) Spotify server hickup; now it works again.

The other issue is also not AHK-, but Chromium-related (especially using Element.getBoundingClientRect() ) - in its current state the script only works, if the opened Spotify page is displayed at 100% zoom level in Chrome - otherwise the calculated coordinates will be off. This could probably be easily remedied with a little math - but let's see first, if this goes in the right direction:

Code: Select all

#Include Chrome.ahk		; adjust path, if necessary
SetTitleMatchMode 2

playlists:= [ "https://open.spotify.com/playlist/0XdhKaK0qx7wQPX4YtHuMf"					; default playlists and albums
					,"https://open.spotify.com/playlist/0pUItxZh4LNpvkkM22kBTj"						; index 2
					, "https://open.spotify.com/playlist/37i9dQZF1DXdpVGstUksUC"
					,"https://open.spotify.com/album/6jJKeu4hPomUuMOM6iGVzQ"
					,"https://open.spotify.com/album/1ZTVXLg7ze1r2HR2JPtPyM" ]						; index 5

random, idx , 1, % playlists.count()			; determine random playlist index
url := playlists[idx]

if  % param := A_Args[1] 				; check for command line parameter
{
	if param is integer
	{	
		if (param > 0) && (param <= playlists.count() )
			url := playlists[param]
	}
	else
		url := param
}
; start your default Chrome profile in debugging mode
ChromeInst := new Chrome()			
WinWait, Google Chrome

; --- Connect to the page ---
if !(PageInst := ChromeInst.GetPage())
{
	MsgBox, Could not retrieve page!
	ChromeInst.Kill()
}
else
{
	; --- Navigate to the desired URL ---
	PageInst.Call("Page.navigate", {"url": url})
	PageInst.WaitForLoad()
}
sleep 500

; class name of the play/pause button of the playlist/album
attribute := "btn btn-green false"
index := 1
objPos := Chrm_GetPosition(PageInst, "Class", attribute, index)
index :=  "[" index-1 "]"

Loop 3 					; make 3 attempts to start the playlist
{
	playpause := PageInst.Evaluate("document.getElementsByClassName('" Attribute "')" index ".innerText").Value
	if (playpause = "PLAY") 
		try Chrm_ClickCenter(PageInst, objPos ,  "left", 1,  100)
	else
		break
	sleep 3000			; waiting 3 seconds before trying it again
}
return				; or  ExitApp
;------------------------------- Hotkeys ----------------------------------------------
Esc::Exitapp		; Hit 'Esc' to exit script

Numpad0::		; Hit 'Numpad0' to toggle play/pause state
attribute := "btn btn-green false"
index := 1
objPos := Chrm_GetPosition(PageInst, "Class", attribute, index)
Chrm_ClickCenter(PageInst, objPos ,  "left", 1,  100)
return 
;-------------------------------- helper functions ---------------------------------------------

Chrm_ClickCenter(PageInst, Pos ,button := "left", count :=1, delay := 100){
   x := Pos.x + Pos.w/2,     y := Pos.y + Pos.h/2
   PageInst.Call("Input.dispatchMouseEvent" , {"type" : "mousePressed", "x" : x , "y" : y, "button" : button, "clickCount" : count } ) 
   sleep, delay 
   PageInst.Call("Input.dispatchMouseEvent" , {"type" : "mouseReleased", "x" : x , "y" : y, "button" : button, "clickCount" : count } ) 
   return
}

Chrm_GetPosition(PageInst, method :="Class" , attribute :="" ,Index := 1){
  obj:={}
  oMethods := {"class" : "sByClassName", "name" : "sByName" , "tag" : "sByTagName", "id" : "ById"}
  if oMethods.HasKey(method)
       element := oMethods[method]
  else                                                                                    
  {
       msgbox "Error in Chrm_GetPosition: Unknown method"
       return "unkown method"
 }
  index := (method = "id") ? "" : "[" index-1 "]"
 
  obj.x := PageInst.Evaluate("document.getElement" element "('" Attribute "')" index ".getBoundingClientRect().x").value
  obj.y := PageInst.Evaluate("document.getElement" element "('" Attribute "')" index ".getBoundingClientRect().y").value
  obj.w := PageInst.Evaluate("document.getElement" element "('" Attribute "')" index ".getBoundingClientRect().width").value
  obj.h := PageInst.Evaluate("document.getElement" element "('" Attribute "')" index ".getBoundingClientRect().height").value
  return obj
}
(hopefully I correctly copy-pasted everything - but you will need to download Chrome.ahk)

So, this script can be called in three ways:
  • without any command line parameter: then it will randomly play one of the albums/playlists in the playlists array, defined at the top of the script
  • with an integer as command line parameter. For example, scriptname.ahk 2 will play the second element of the playlists array, defined in the script
  • finally, with a playlist/album URL as a command line parameter, for example: scriptname.ahk https://open.spotify.com/playlist/0XdhKaK0qx7wQPX4YtHuMf (the https:// part is important)
Then, your default Chrome profile will be opened in debugging mode (necessary for automation) - it is assumed that you are already logged into Spotify and chose 'remember me' so that you don't have to login again (although that could be done, too) - and a playlist/album page will be opened; and if you are lucky ;), it will be played. After that, the script could exit, but for testing I added a hotkey (Numpad0) that should allow to toggle play/pause...

What else?
Error handling can surely be improved; it would also be possible to create an own Chrome profile just for this task, that could be run side-by-side with your default Chrome profile. As always, with such automation code, use it at your own risk: I am not sure, if Spotify will like it :shifty:

Let me know, if this is what you looked for... we can still modify it.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], lirouxtm and 313 guests