-
Star
(109)
You must be signed in to star a gist -
Fork
(1)
You must be signed in to fork a gist
-
-
Save jcsteh/7ccbc6f7b1b7eb85c1c14ac5e0d65195 to your computer and use it in GitHub Desktop.
; SpotifyGlobalKeys.ahk: | |
; AutoHotkey script to control Spotify with global keyboard shortcuts | |
; Author: James Teh <[email protected]> | |
; Copyright 2017-2018 James Teh | |
; License: GNU General Public License version 2.0 | |
DetectHiddenWindows, On | |
; Get the HWND of the Spotify main window. | |
getSpotifyHwnd() { | |
WinGet, spotifyHwnd, ID, ahk_exe spotify.exe | |
Return spotifyHwnd | |
} | |
; Send a key to Spotify. | |
spotifyKey(key) { | |
spotifyHwnd := getSpotifyHwnd() | |
; Chromium ignores keys when it isn't focused. | |
; Focus the document window without bringing the app to the foreground. | |
ControlFocus, Chrome_RenderWidgetHostHWND1, ahk_id %spotifyHwnd% | |
ControlSend, , %key%, ahk_id %spotifyHwnd% | |
Return | |
} | |
; Win+alt+p: Play/Pause | |
#!p:: | |
{ | |
spotifyKey("{Space}") | |
Return | |
} | |
; Win+alt+down: Next | |
#!Down:: | |
{ | |
spotifyKey("^{Right}") | |
Return | |
} | |
; Win+alt+up: Previous | |
#!Up:: | |
{ | |
spotifyKey("^{Left}") | |
Return | |
} | |
; Win+alt+right: Seek forward | |
#!Right:: | |
{ | |
spotifyKey("+{Right}") | |
Return | |
} | |
; Win+alt+left: Seek backward | |
#!Left:: | |
{ | |
spotifyKey("+{Left}") | |
Return | |
} | |
; shift+volumeUp: Volume up | |
+Volume_Up:: | |
{ | |
spotifyKey("^{Up}") | |
Return | |
} | |
; shift+volumeDown: Volume down | |
+Volume_Down:: | |
{ | |
spotifyKey("^{Down}") | |
Return | |
} | |
; Win+alt+o: Show Spotify | |
#!o:: | |
{ | |
spotifyHwnd := getSpotifyHwnd() | |
WinGet, style, Style, ahk_id %spotifyHwnd% | |
if (style & 0x10000000) { ; WS_VISIBLE | |
WinHide, ahk_id %spotifyHwnd% | |
} Else { | |
WinShow, ahk_id %spotifyHwnd% | |
WinActivate, ahk_id %spotifyHwnd% | |
} | |
Return | |
} |
to make the controls work when the window is minimized to the taskbar or tray, you need to use winhide
can be done like this
#If OnMy_Close_or_Min_Buttons()
LButton:: Winhide
#If
OnMy_Close_or_Min_Buttons() {
Static MyWindowCriteria := "ahk_exe Spotify.exe" ; change to meet your neeeds
Critical
SetTitleMatchMode, 2
CoordMode, Mouse, Screen
MouseGetPos, X, Y, MID
;ToolTip, mid %mid%
If (WID := WinExist(MyWindowCriteria)) && (WID = MID) {
SendMessage, 0x0084, 0, (X & 0xFFFF) | ((Y & 0xFFFF) << 16) ; WM_NCHITTEST
;Return (ErrorLevel = 20) ; HTCLOSE
;Return (ErrorLevel = 8) ; HTmin
;ToolTip, ErrorLevel %ErrorLevel%
if ((ErrorLevel = "20") or (ErrorLevel = "8"))
{
;ToolTip, test
return true
}
}
Return False
}
and function to send hotkeys is like this
; Send a key to Spotify.
spotifyKey(key) {
;spotifyHwnd := getSpotifyHwnd()
; Chromium ignores keys when it isn't focused.
; Focus the document window without bringing the app to the foreground.
IfWinNotActive, ahk_exe Spotify.exe
{
DetectHiddenWindows, on
DetectHiddenText, on
WinGet, OutputVar1, ID , ahk_exe Spotify.exe
ControlFocus, , ahk_id %OutputVar1%
ControlSend, ahk_parent , %key%, ahk_class Chrome_WidgetWin_1
return
}
IfWinActive, ahk_exe Spotify.exe
{
Send, %key%
;ToolTip, keyssend
return
}
Return
}
to make the controls work when the window is minimized to the taskbar or tray, you need to use winhide
can be done like this
#If OnMy_Close_or_Min_Buttons() LButton:: Winhide #If OnMy_Close_or_Min_Buttons() { Static MyWindowCriteria := "ahk_exe Spotify.exe" ; change to meet your neeeds Critical SetTitleMatchMode, 2 CoordMode, Mouse, Screen MouseGetPos, X, Y, MID ;ToolTip, mid %mid% If (WID := WinExist(MyWindowCriteria)) && (WID = MID) { SendMessage, 0x0084, 0, (X & 0xFFFF) | ((Y & 0xFFFF) << 16) ; WM_NCHITTEST ;Return (ErrorLevel = 20) ; HTCLOSE ;Return (ErrorLevel = 8) ; HTmin ;ToolTip, ErrorLevel %ErrorLevel% if ((ErrorLevel = "20") or (ErrorLevel = "8")) { ;ToolTip, test return true } } Return False }
and function to send hotkeys is like this
; Send a key to Spotify. spotifyKey(key) { ;spotifyHwnd := getSpotifyHwnd() ; Chromium ignores keys when it isn't focused. ; Focus the document window without bringing the app to the foreground. IfWinNotActive, ahk_exe Spotify.exe { DetectHiddenWindows, on DetectHiddenText, on WinGet, OutputVar1, ID , ahk_exe Spotify.exe ControlFocus, , ahk_id %OutputVar1% ControlSend, ahk_parent , %key%, ahk_class Chrome_WidgetWin_1 return } IfWinActive, ahk_exe Spotify.exe { Send, %key% ;ToolTip, keyssend return } Return }
Where should I paste this code? I get an error
«Error at line 23.
Line Text: and function to send hotkeys is like this
Error: This line does not contain a recognized action.»
The code above from walbjorn works great!
(and the page author's code does not work for me) It turned out to work, but somehow strangely and every once in a while
what is in line 23?
you can insert this part at the beginning or end of the code
#If OnMy_Close_or_Min_Buttons()
LButton:: Winhide
#If
OnMy_Close_or_Min_Buttons() {
Static MyWindowCriteria := "ahk_exe Spotify.exe" ; change to meet your neeeds
Critical
SetTitleMatchMode, 2
CoordMode, Mouse, Screen
MouseGetPos, X, Y, MID
;ToolTip, mid %mid%
If (WID := WinExist(MyWindowCriteria)) && (WID = MID) {
SendMessage, 0x0084, 0, (X & 0xFFFF) | ((Y & 0xFFFF) << 16) ; WM_NCHITTEST
;Return (ErrorLevel = 20) ; HTCLOSE
;Return (ErrorLevel = 8) ; HTmin
;ToolTip, ErrorLevel %ErrorLevel%
if ((ErrorLevel = "20") or (ErrorLevel = "8"))
{
;ToolTip, test
return true
}
}
Return False
}
this
; Send a key to Spotify.
spotifyKey(key) {
;spotifyHwnd := getSpotifyHwnd()
; Chromium ignores keys when it isn't focused.
; Focus the document window without bringing the app to the foreground.
IfWinNotActive, ahk_exe Spotify.exe
{
DetectHiddenWindows, on
DetectHiddenText, on
WinGet, OutputVar1, ID , ahk_exe Spotify.exe
ControlFocus, , ahk_id %OutputVar1%
ControlSend, ahk_parent , %key%, ahk_class Chrome_WidgetWin_1
return
}
IfWinActive, ahk_exe Spotify.exe
{
Send, %key%
;ToolTip, keyssend
return
}
Return
}`
instead of
`; Send a key to Spotify.
spotifyKey(key) {
spotifyHwnd := getSpotifyHwnd()
ControlClick, x500 y100, ahk_id %spotifyHwnd%, , Left, 1, U
ControlSend, ahk_parent, %key%, ahk_id %spotifyHwnd%
}
but additional testing revealed that sometimes this method stops working, I am looking for and trying new approaches that can give permanent work in a collapsed state.
https://gist.github.com/drandarov-io/96a5df7d1dee2d545f22fcaddf522284
Thought I'd add something that worked for me after much trial and error.
Yesterday I came to a similar approach) until it seems not stop working
spotifyKey(key) {
IfWinNotActive, ahk_exe Spotify.exe
{
DetectHiddenWindows, on
DetectHiddenText, on
ControlFocus, , , Chrome Legacy Window
ControlSend, ahk_parent , %key%, ahk_class Chrome_WidgetWin_1
return
}
IfWinActive, ahk_exe Spotify.exe
{
Send, %key%
return
}
Return
}
what is in line 23? you can insert this part at the beginning or end of the code
#If OnMy_Close_or_Min_Buttons() LButton:: Winhide #If OnMy_Close_or_Min_Buttons() { Static MyWindowCriteria := "ahk_exe Spotify.exe" ; change to meet your neeeds Critical SetTitleMatchMode, 2 CoordMode, Mouse, Screen MouseGetPos, X, Y, MID ;ToolTip, mid %mid% If (WID := WinExist(MyWindowCriteria)) && (WID = MID) { SendMessage, 0x0084, 0, (X & 0xFFFF) | ((Y & 0xFFFF) << 16) ; WM_NCHITTEST ;Return (ErrorLevel = 20) ; HTCLOSE ;Return (ErrorLevel = 8) ; HTmin ;ToolTip, ErrorLevel %ErrorLevel% if ((ErrorLevel = "20") or (ErrorLevel = "8")) { ;ToolTip, test return true } } Return False }
this
; Send a key to Spotify. spotifyKey(key) { ;spotifyHwnd := getSpotifyHwnd() ; Chromium ignores keys when it isn't focused. ; Focus the document window without bringing the app to the foreground. IfWinNotActive, ahk_exe Spotify.exe { DetectHiddenWindows, on DetectHiddenText, on WinGet, OutputVar1, ID , ahk_exe Spotify.exe ControlFocus, , ahk_id %OutputVar1% ControlSend, ahk_parent , %key%, ahk_class Chrome_WidgetWin_1 return } IfWinActive, ahk_exe Spotify.exe { Send, %key% ;ToolTip, keyssend return } Return }`
instead of
`; Send a key to Spotify. spotifyKey(key) { spotifyHwnd := getSpotifyHwnd() ControlClick, x500 y100, ahk_id %spotifyHwnd%, , Left, 1, U ControlSend, ahk_parent, %key%, ahk_id %spotifyHwnd% }
but additional testing revealed that sometimes this method stops working, I am looking for and trying new approaches that can give permanent work in a collapsed state.
This code works fine for me with Spotify minimized in tray (!), much to my delight (finally! After months of agony!)
DetectHiddenWindows, On
; Get the HWND of the Spotify main window.
getSpotifyHwnd() {
WinGet, spotifyHwnd, ID, ahk_exe spotify.exe
Return spotifyHwnd
}
; Send a key to Spotify.
spotifyKey(key) {
spotifyHwnd := getSpotifyHwnd()
; Chromium ignores keys when it isn't focused.
; Focus the document window without bringing the app to the foreground.
ControlFocus, Chrome_RenderWidgetHostHWND1, ahk_id %spotifyHwnd%
ControlSend, , %key%, ahk_id %spotifyHwnd%
Return
}
; Ctrl+Shift+q: Play/Pause
^+q::
{
spotifyKey("{Space}")
Return
}
; alt+v: Next
!v::
{
spotifyKey("^{Right}")
Return
}
; alt+z: Previous
!z::
{
spotifyKey("^{Left}")
Return
}
; Ctrl+alt+Up: Volume up
^!Up::
{
spotifyKey("^{Up}")
Return
}
; Ctrl+alt+Down: Volume Down
^!Down::
{
spotifyKey("^{Down}")
Return
}
; Ctrl+: Show Spotify ^
::
{
spotifyHwnd := getSpotifyHwnd()
WinGet, style, Style, ahk_id %spotifyHwnd%
if (style & 0x10000000) { ; WS_VISIBLE
WinHide, ahk_id %spotifyHwnd%
} Else {
WinShow, ahk_id %spotifyHwnd%
WinActivate, ahk_id %spotifyHwnd%
}
Return
}
Sometimes it doesn't catch the focus or on the contrary, holds it, but it already trifles for a couple clicks :)
This works great!!! Been finding a solution to this. Thanks!
Been using this for ages and now it no longer seems to be working when the window is hidden using the Win+alt+o: Show Spotify
shortcut.
I assume this is due to some Spotify change, but does anyone else have it still working or know what is necessary to resolve it? I've not been able to figure it out so far.
Been using this for ages and now it no longer seems to be working when the window is hidden using the
Win+alt+o: Show Spotify
shortcut.I assume this is due to some Spotify change, but does anyone else have it still working or know what is necessary to resolve it? I've not been able to figure it out so far.
I have already been disappointed many times in the player itself and in the code, because initially everything worked, but then it stopped.
I experimented as much as I could and realized that the code still works, but on one condition: if you delete the player settings every time and log in again every time you start it. Only then does everything work. When you run it again without deleting the settings, nothing works again
I just figured this out after trying the stuff here and a few other scripts I found on the AHK forum.
The following will work in AutoHotkey v2 to send the shortcuts to the Spotify main window, as long as it isn't hidden/minimized, even if the miniplayer is open.
NOTE: I am using SpotX to banish the adspam. I am a premium subscriber, so I shouldn't be getting slapped in the face regularly on top of my wallet being gouged every month. Google SpotX if you're in the same boat.
Anyway, this should still work with the vanilla Spotify app.
; requires AutoHotkey v2
; auto-execute thread======================================
SetTitleMatchMode("RegEx")
; FUNCTIONS:
HotKeyWait()
{
; make an array to store states of keys that are physically pressed
keysdown := []
; make an array to store list of keys to get state of
static KbdKeys := ["lshift","rshift","lalt","ralt","lctrl","rctrl","lwin","rwin","appskey","lbutton","rbutton","mbutton","xbutton1","xbutton2","joy1","joy2","joy3","joy4","joy5","joy6","joy7","joy8","joy9","joy10","joy11","joy12","joy13","joy14","joy15","joy16","joy17","joy18","joy19","joy20","joy21","joy22","joy23","joy24","joy25","joy26","joy27","joy28","joy29","joy30","joy31","joy32","joyx","joyy","joyz","joyr","joyu","joyv","joypov","joyname","joybuttons","joyaxes","joyinfo","space","tab","enter","esc","backspace","del","insert","pgup","pgdn","home","end","up","down","left","right","printscreen","ctrlbreak","pause","scrolllock","capslock","numlock","numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9","numpadmult","numpadadd","numpadsub","numpaddiv","numpaddot","numpadins","numpadclear","f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16","f17","f18","f19","f20","f21","f22","f23","f24","browser_back","browser_forward","browser_refresh","browser_stop","browser_search","browser_favorites","browser_home","volume_mute","volume_down","volume_up","media_next","media_prev","media_stop","media_play_pause","launch_mail","launch_media","launch_app1","launch_app2","1","2","3","4","5","6","7","8","9","0","-","=","q","w","e","r","t","y","u","i","o","p","[","]","\","a","s","d","f","g","h","j","k","l",";","'","z","x","c","v","b","n","m","`,",".","/","``"]
indx := 1
; iterate through all keys to add any that are physically held down to the array
for k in KbdKeys
{
keystate := GetKeyState(KbdKeys[indx],"P")
if keystate = 1
{
keysdown.push(KbdKeys[indx])
}
indx++
}
; wait (up to 2 second timeout) for physical release of all keys in the array
for kd in keysdown
{
KeyWait(kd,"T2")
}
}
MyTip(aVar, t:=-1500)
{ ; tooltip at mouse cursor, 1.5 sec timeout default
aStr := ""
t := ceil(Abs(t))*-1
if IsObject(aVar){
aStr := StrGet(aVar)
}
else{
aStr := aVar
}
ToolTip(aStr)
SetTimer () => ToolTip(), t
}
; Get the HWND of the Spotify main window and send keys via control focus (the miniplayer uses " • " in it's title, whereas the main window will use " - ", or just "Spotify" when stopped/paused)
; Only works when main window is not minimized/hidden
spotifyKey(key)
{
try ActiveWin := WinGetID("A")
DetectHiddenWindows(true)
spotifyHwnd := WinGetID("(Spotify|. - .) ahk_exe Spotify.exe", , " • ")
BlockInput "On"
ControlFocus("Chrome_RenderWidgetHostHWND1", "ahk_id " spotifyHwnd)
ControlSend(key, , "ahk_id " spotifyHwnd)
DetectHiddenWindows(False)
WinActivate(ActiveWin)
BlockInput "Off"
Return
}
; FUNCTIONS END
; AUTO-EXECUTE THREAD END======================================
; HOTKEYS:
; Play/Pause Track
$^!F8::{
HotKeyWait
spotifyKey("{space}")
MyTip(ThisHotkey ": Spotify - Play/Pause Track")
return
}
; Previous Track
$^!F7::{
HotKeyWait
spotifyKey("{Ctrl down}{left}{Ctrl up}")
MyTip(ThisHotkey ": Spotify - Previous Track")
return
}
; Next Track
$^!F9::{
HotKeyWait
spotifyKey("{Ctrl down}{right}{Ctrl up}")
MyTip(ThisHotkey ": Spotify - Next Track")
return
}
; Volume Up
$^!F12::{
HotKeyWait
spotifyKey("{Ctrl down}{up}{Ctrl up}")
MyTip(ThisHotkey ": Spotify - Volume Up")
return
}
; Volume Down
$^!F11::{
HotKeyWait
spotifyKey("{Ctrl down}{down}{Ctrl up}")
MyTip(ThisHotkey ": Spotify - Volume Down")
return
}
; Seek backward
$+F7::{
HotKeyWait
spotifyKey("{shift down}{left}{shift up}")
MyTip(ThisHotkey ": Spotify - Seek backward")
Return
}
; Seek forward
$+F9::{
HotKeyWait
spotifyKey("{shift down}{right}{shift up}")
MyTip(ThisHotkey ": Spotify - Seek forward")
return
}
; Show/hide Spotify
$^!Numpad0::{
HotKeyWait
DetectHiddenWindows(true)
spotifyHwnd := WinGetID(". - . ahk_exe Spotify.exe", , " • ")
style := WinGetStyle("ahk_id " spotifyHwnd)
if (style & 0x10000000) { ; WS_VISIBLE
WinHide("ahk_id " spotifyHwnd)
} Else {
WinShow("ahk_id " spotifyHwnd)
WinActivate("ahk_id " spotifyHwnd)
}
DetectHiddenWindows(False)
MyTip(ThisHotkey ": Show/hide Spotify")
Return
}
I also have my functions in there for waiting for hotkeys to be physically released before triggering the script they should execute, and for displaying a tooltip showing the hotkey pressed along with a brief description of it.
The functions will need to be at the top of the your ahk script, in the auto-execute thread, as noted.
This should allow you to control Spotify and its volume independently of the master volume of your sytem. And it doesn't rely on the use of "media" keys, so if you have any other media players open, there won't be any mess with those being started/stopped along with or instead of Spotify.
This is what currently works for me using AHK 1.1 (it will not work if you minimize Spotify).
The keybindings are set at the bottom of the script, currently set to use Winkey and Winkey+Alt modifiers.