Code: Select all
; Big thanks to Acc.ahk ~ "https://www.autohotkey.com/board/topic/77303-acc-library-ahk-l-updated-09272012/"
; And jeeswg ~ "https://www.autohotkey.com/boards/viewtopic.php?f=6&t=40615"
#SingleInstance, Force
SetBatchLines, -1
SetWinDelay, 0
;------------------------------------------------- Options --------------------------------------------------;
Hotkey, F1, Action ; For key names go to ~ "https://www.autohotkey.com/docs/KeyList.htm"
HideGuiTime := "3000" ; Amount of time the gui will be displayed in milliseconds
GuiAlpha := "200"
GuiColor := "ffffff"
TextColor := "000000"
TextMargin := "6" ; Padding above and below text
FontSize := "10"
FontFamily := "Verdana"
FontWeight := "" ; Bold, italic, underline etc or a number between 1 and 1000 (400 is normal and 700 is bold)
;------------------------------------------------------------------------------------------------------------;
Gui, +hwndGuiHwnd -Caption +AlwaysOnTop +E0x20 +ToolWindow
Gui, Color, %GuiColor%
Gui, Margin, 0, %TextMargin%
Gui, Font, S%FontSize% W%FontWeight%, %FontFamily%
Gui, Add, Text, +hwndTextHwnd w%A_ScreenWidth% c%TextColor% +Center, Added to playlist
Gui, Show, x0 y0 w%A_ScreenWidth% NA
WinSet, Transparent, 0, ahk_id %GuiHwnd%
Return
Action:
Result := LikeCurrentSong()
if (StrLen(Result.Song) > 50)
Result.Song := SubStr(Result.Song, 1, 50) "..."
if (Result = "Error")
ShowGui("Error... is spotify running?", 4000)
else {
if (Result.Song = "") {
ShowGui("An ad is playing!", HideGuiTime)
Return
}
if (Result.State = True)
ShowGui("Added """ Result.Song """ to liked songs.", HideGuiTime)
else if (Result.State = False)
ShowGui("Removed """ Result.Song """ from liked songs.", HideGuiTime)
else
ShowGui("Unknown error... contact MiM#9148 on discord!", HideGuiTime)
}
Return
ShowGui(Text, Time) {
Global
WinSet, Transparent, %GuiAlpha%, ahk_id %GuiHwnd%
GuiControl,, % TextHwnd, % Text
SetTimer, HideGui, -%Time%
}
HideGui:
WinSet, Transparent, 0, ahk_id %GuiHwnd%
Return
LikeCurrentSong() {
Critical
DetectHiddenWindows, % (_:=A_DetectHiddenWindows)?"On":
oMem := {}, oPos := {}
oMem[1, 1] := Acc_ObjectFromWindow(WinExist("ahk_exe Spotify.exe"), 0x0)
oPos[1] := 1, vLevel := 1
Loop {
if !vLevel
Return "Error"
if !oMem[vLevel].HasKey(oPos[vLevel]) {
oMem.Delete(vLevel)
oPos.Delete(vLevel)
vLevelLast := vLevel, vLevel -= 1
oPos[vLevel]++
continue
}
oKey := oMem[vLevel, oPos[vLevel]]
vName := "", vValue := ""
if IsObject(oKey) {
vRoleText := Acc_GetRoleText(oKey.accRole(0))
vName := oKey.accName(0)
vValue := oKey.accValue(0)
}
oChildren := Acc_Children(oKey)
vLevelLast := vLevel, vLevel += 1
oMem[vLevel] := oChildren
oPos[vLevel] := 1
if InStr(vName, "Now playing:") && !Song
Song := RegExReplace(vName, "Now playing: ", "")
if (vName = "Remove from Your Library") || (vName = "Save to Your Library") {
if (Song != "")
oKey.accDoDefaultAction(0)
DetectHiddenWindows, % _
Return {State:(vName="Save to Your Library"?True:False), Song:Song}
}
}
}
Acc_Init() {
Static h
If Not h
h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
Static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
AccObj := IsObject(WinTitle)? WinTitle
: Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
if ComObjType(AccObj, "Name") != "IAccessible"
ErrorLevel := "Could not access an IAccessible Object"
else {
StringReplace, ChildPath, ChildPath, _, %A_Space%, All
AccError:=Acc_Error(), Acc_Error(true)
Loop Parse, ChildPath, ., %A_Space%
try {
if A_LoopField is digit
Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
else
RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
if Not Children.HasKey(m2)
throw
AccObj := Children[m2]
} catch {
ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
if Acc_Error()
throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
return
}
Acc_Error(AccError)
StringReplace, Cmd, Cmd, %A_Space%, , All
properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
try {
if (Cmd = "Location")
AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
, ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
else if (Cmd = "Object")
ret_val := AccObj
else if Cmd in Role,State
ret_val := Acc_%Cmd%(AccObj, ChildID+0)
else if Cmd in ChildCount,Selection,Focus
ret_val := AccObj["acc" Cmd]
else
ret_val := AccObj["acc" Cmd](ChildID+0)
} catch {
ErrorLevel := """" Cmd """ Cmd Not Implemented"
if Acc_Error()
throw Exception("Cmd Not Implemented", -1, Cmd)
return
}
return ret_val, ErrorLevel:=0
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_ObjectFromWindow(hWnd, idObject = -4) {
Acc_Init()
if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
Return ComObjEnwrap(9,pacc,1)
}
Acc_GetRoleText(nRole) {
nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
Return sRole
}
Acc_Children(Acc) {
if ComObjType(Acc,"Name") != "IAccessible"
ErrorLevel := "Invalid IAccessible Object"
else {
Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
Loop %cChildren%
i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
return Children.MaxIndex()?Children:
}
else
ErrorLevel := "AccessibleChildren DllCall Failed"
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_Error(p="") {
Static setting:=0
return p=""?setting:setting:=p
}
Acc_ChildrenByRole(Acc, Role) {
if ComObjType(Acc,"Name")!="IAccessible"
ErrorLevel := "Invalid IAccessible Object"
else {
Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
Loop %cChildren% {
i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
if NumGet(varChildren,i-8)=9
AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
else
Acc_Role(Acc, child)=Role?Children.Insert(child):
}
return Children.MaxIndex()?Children:, ErrorLevel:=0
}
else
ErrorLevel := "AccessibleChildren DllCall Failed"
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Role(Acc, ChildId=0) {
try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_GetStateText(nState) {
nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
Return sState
}
Ugly gui, ugly syntax, ugly logic, a lot of things can be cleaned up but i don't care enough, just posting this in case someone finds it useful.