port of Audio Vista library for v2?

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
Cornelius-Figgle
Posts: 5
Joined: 20 Mar 2023, 13:44
Contact:

port of Audio Vista library for v2?

Post by Cornelius-Figgle » 21 Mar 2023, 12:49

I am writing a script to skip the adverts on Spotify via relaunching (ik this has been done before, but I want to do it as well ツ)

In the checking of whether or not an advert is playing, I use the following function:

Code: Select all

DetermineWhetherToSkip() {
	Sleep(1000)
	if WinExist("Spotify Free")
		and WinExist("ahk_exe spotify.exe")
		and WinGetID("ahk_exe spotify.exe") == WinGetID("Spotify Free")
		and RunWait("av_checks_v1.exe", , "HIDE") { 

		SkipViaRestart()
	}
}
Which as you can see, runs an exe. This exe uses the following function to determine whether audio is actually playing or not, which in turn uses (a condensed version of) Lexikos' AudioVista library

Original AV lib: https://www.autohotkey.com/board/topic/21984-vista-audio-control-functions/
Condensed Version: viewtopic.php?t=41872

Code: Select all

exitapp, IsAudioPlaying()  ; boolean exit code

IsAudioPlaying() {
    AudioLevel := 0.0
    VA_IAudioMeterInformation_GetPeakValue(VA_GetAudioMeter(), AudioLevel)
    return (Round(AudioLevel, 4) > 0)
}
Now because this was written in AHK v1.1, I compiled it to exe to be called in the main script - because I didn't understand any of it enough to manually convert it, and the convert I found didn't fully work (undeclared vars etc)

Converter Link: https://github.com/mmikeww/AHK-v2-script-converter

But then I realised that I would need to check whether the output is coming from Spotify or another app, as currently, if Spotify is paused the title conditions are met, and if I start playing audio from another window (ie YouTube) but with Spotify open in the background/minimized/whatever, the audio conditions are met and it restarts Spotify, which obviously we do not want. I think I should be able to work out how to check where the audio is coming from using AV (as detailed below)

Find Processes with Audio: viewtopic.php?&t=94843
Find Which Process is Audio: viewtopic.php?t=113539

So, long story short, I need a copy of the AV library for AHK v2. If anyone has a working copy, or can point me in the right direction for converting it, please let me know

TL;DR: I need the AV lib in AHK v2

Thanks in advance :)

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: port of Audio Vista library for v2?

Post by malcev » 21 Mar 2023, 13:52

Here We discussed about spotify:
viewtopic.php?f=76&t=114207
But it is for V1.
Also You can create events when spotify starts and stops playing, but You need to implement interfaces by Yourself.

User avatar
Cornelius-Figgle
Posts: 5
Joined: 20 Mar 2023, 13:44
Contact:

Re: port of Audio Vista library for v2?

Post by Cornelius-Figgle » 23 Mar 2023, 13:13

Thanks for the link, I didn't find that thread at all when searching ¯\( ツ )/¯

Can you explain to me what the code is actually doing?

Code: Select all

DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+9*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", GlobalSystemMediaTransportControlsSessionPlaybackInfo)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionPlaybackInfo+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionPlaybackInfo, "int*", PlaybackStatus)
ObjReleaseClose(GlobalSystemMediaTransportControlsSessionPlaybackInfo)
msgbox % PlaybackStatus
The above appears to be the relevant lines, however I just get a lot of undefined variable errors (specifically GlobalSystemMediaTransportControlsSession and GlobalSystemMediaTransportControlsSessionPlaybackInfo

I converted it to v2 (using the convert I mentioned earlier) which produced the following:

Code: Select all

DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0, "UPtr")+9*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", &GlobalSystemMediaTransportControlsSessionPlaybackInfo)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionPlaybackInfo+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionPlaybackInfo, "int*", &PlaybackStatus)
ObjRelease(GlobalSystemMediaTransportControlsSessionPlaybackInfo)
MsgBox(PlaybackStatus)
I ran both the v2 code and the original code (using ahk v1.1) and they both produced similar errors

Do I need to download the data from the GitHub repo mentioned, or add other libraries? Sorry but I have never done system stuff like this before, and consequently have no idea what any of it means sorry :/

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: port of Audio Vista library for v2?

Post by malcev » 23 Mar 2023, 13:49

This code will run only on windows 10.

User avatar
Cornelius-Figgle
Posts: 5
Joined: 20 Mar 2023, 13:44
Contact:

Re: port of Audio Vista library for v2?

Post by Cornelius-Figgle » 23 Mar 2023, 13:52

I did run it on Windows 10...

malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: port of Audio Vista library for v2?

Post by malcev » 23 Mar 2023, 15:16

Then You shouldnot get errors on this code.
viewtopic.php?p=512253#p512253
But You need run it in ahk v1.

User avatar
Cornelius-Figgle
Posts: 5
Joined: 20 Mar 2023, 13:44
Contact:

Re: port of Audio Vista library for v2?

Post by Cornelius-Figgle » 25 Mar 2023, 04:06

Thanks for the relink, I didn't realised the code at the bottom was an addition to the top code (the short replies on that thread make it kinda hard to understand what is what)

I think I am beginning to understand this code now - it looks like the DllCalls and ptr stuff is actually sharing variables between the ahk script and (I'm guessing) Spotify and Windows (and other Dlls)

Whats weird is that, ignoring my attempts at the v2 conversions etc, there are still some issues, namely:
  • I can run it from source (ie just the code) in the sandbox (I'm using the sandbox here so I don't have to reinstall AHK v1.1 on my pc, as multiple versions of programs generally doesn't end well - idk about AHK specifically tho)
  • I can run a compiled copy on my pc without any (reported) errors, however the MsgBox just comes up with blank spaces (ie it isnt outputting the variables)
  • I can run the exact same exe (copy-pasted in) in the the sandbox (ie as the exe, should be fully independent) and it runs perfectly, same as running from source in the sandbox
    • This would suggest that either the program needs admin permissions, however it shouldn't do as Spotify doesn't need admin permissions to run, and I didn't specify running as admin in the sandbox (normal double-click launch)
    • Or that it has some dependencies from the v1.1 program that are not present on my pc - but I couldn't find anything besides gdiplus, which I removed all the references I could see to as I don't need the album art for my script
  • I haven't tried running from source on my pc bc I dont have AHK v1.1 installed anymore and would rather not have multiple versions (for now at least)
The scripts I am using are below, as they are modified from the original ones in your post:

Code: Select all

; v1 script (works in sandbox)

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

app := "spotify.exe"
CreateClass("Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager", IGlobalSystemMediaTransportControlsSessionManagerStatics := "{2050c4ee-11a0-57de-aed7-c97c70338245}", GlobalSystemMediaTransportControlsSessionManagerStatics)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManagerStatics+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManagerStatics, "ptr*", GlobalSystemMediaTransportControlsSessionManager)   ; GlobalSystemMediaTransportControlsSessionManager.RequestAsync
WaitForAsync(GlobalSystemMediaTransportControlsSessionManager)
return

F11::Goto, SongInfo

SongInfo: 
	title := artist := ""
	DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManager, "ptr*", GlobalSystemMediaTransportControlsSessionList)   ; GlobalSystemMediaTransportControlsSessionManager.GetSessions
	DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int*", count)   ; count
	loop % count {
		DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int", A_Index-1, "ptr*", GlobalSystemMediaTransportControlsSession)
		DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", SourceAppUserModelId)   ; GlobalSystemMediaTransportControlsSession.get_SourceAppUserModelId
		buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", SourceAppUserModelId, "uint*", length, "ptr")
		if (StrGet(buffer, "UTF-16") = app) {
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", GlobalSystemMediaTransportControlsSessionMediaProperties)   ; GlobalSystemMediaTransportControlsSession.TryGetMediaPropertiesAsync
			WaitForAsync(GlobalSystemMediaTransportControlsSessionMediaProperties)
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Title
			buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", length, "ptr")
			title := StrGet(buffer, "UTF-16")
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0)+9*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Artist
			buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", length, "ptr")
			artist := StrGet(buffer, "UTF-16")

			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+9*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", GlobalSystemMediaTransportControlsSessionPlaybackInfo)
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionPlaybackInfo+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionPlaybackInfo, "int*", PlaybackStatus)
			ObjReleaseClose(GlobalSystemMediaTransportControlsSessionPlaybackInfo)

			ObjReleaseClose(RandomAccessStreamReference)
			ObjReleaseClose(GlobalSystemMediaTransportControlsSessionMediaProperties)
			ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
			break
		}
		ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
	}
	ObjReleaseClose(GlobalSystemMediaTransportControlsSessionList)
	Msgbox % "title: " title "`nartist: " artist "`nstatus: " PlaybackStatus
return

CreateClass(string, interface := "", ByRef Class := "") {
	CreateHString(string, hString)
	if (interface = "")
		result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
	else {
		VarSetCapacity(GUID, 16)
		DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
		result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
	}
	if (result != 0) {
		if (result = 0x80004002)
			msgbox No such interface supported
		else if (result = 0x80040154)
			msgbox Class not registered
		else
			msgbox error: %result%
		ExitApp
	}
	DeleteHString(hString)
}

CreateHString(string, ByRef hString) {
	DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString) {
	DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object) {
	AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
	loop {
		DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
		if (status != 0) {
			if (status != 1) {
				DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
				msgbox AsyncInfo status error: %ErrorCode%
				ExitApp
			}
			ObjRelease(AsyncInfo)
			break
		}
		sleep 10
	}
	DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
	ObjReleaseClose(Object)
	Object := ObjectResult
}

ObjReleaseClose(ByRef Object) {
	if Object {
		if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")) {
			DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
			ObjRelease(Close)
		}
		ObjRelease(Object)
	}
	Object := ""
}

Code: Select all

; v2 script (doesn't work)

#Requires AutoHotkey v2.0
#SingleInstance Force

app := "spotify.exe"
CreateClass("Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager", IGlobalSystemMediaTransportControlsSessionManagerStatics := "{2050c4ee-11a0-57de-aed7-c97c70338245}", &GlobalSystemMediaTransportControlsSessionManagerStatics)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManagerStatics+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionManagerStatics, "ptr*", &GlobalSystemMediaTransportControlsSessionManager)   ; GlobalSystemMediaTransportControlsSessionManager.RequestAsync
WaitForAsync(&GlobalSystemMediaTransportControlsSessionManager)
return

F11:: { ; V1toV2: Added bracket
	global
	title := artist := ""
	DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionManager, "ptr*", &GlobalSystemMediaTransportControlsSessionList)   ; GlobalSystemMediaTransportControlsSessionManager.GetSessions
	DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionList, "int*", &count)   ; count
	Loop count {
		DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionList, "int", A_Index-1, "ptr*", &GlobalSystemMediaTransportControlsSession)
		DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", &SourceAppUserModelId)   ; GlobalSystemMediaTransportControlsSession.get_SourceAppUserModelId
		buffer_ := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", SourceAppUserModelId, "uint*", &length, "ptr")
		if (StrGet(buffer_, "UTF-16") = app)    {
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", &GlobalSystemMediaTransportControlsSessionMediaProperties)   ; GlobalSystemMediaTransportControlsSession.TryGetMediaPropertiesAsync
			WaitForAsync(&GlobalSystemMediaTransportControlsSessionMediaProperties)
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", &hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Title
			buffer_ := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", &length, "ptr")
			title := StrGet(buffer_, "UTF-16")
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0, "UPtr")+9*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", &hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Artist
			buffer_ := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", &length, "ptr")
			artist := StrGet(buffer_, "UTF-16")

			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0, "UPtr")+9*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", &GlobalSystemMediaTransportControlsSessionPlaybackInfo)
			DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionPlaybackInfo+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", GlobalSystemMediaTransportControlsSessionPlaybackInfo, "int*", &PlaybackStatus)
			ObjReleaseClose(&GlobalSystemMediaTransportControlsSessionPlaybackInfo)

			ObjReleaseClose(&RandomAccessStreamReference)
			ObjReleaseClose(&GlobalSystemMediaTransportControlsSessionMediaProperties)
			ObjReleaseClose(&GlobalSystemMediaTransportControlsSession)
			break
		}
		ObjReleaseClose(&GlobalSystemMediaTransportControlsSession)
	}
	ObjReleaseClose(&GlobalSystemMediaTransportControlsSessionList)
	MsgBox("title: " title "`nartist: " artist "`nstatus: " PlaybackStatus)
} ; Added bracket before function

CreateClass(string, interface := "", &Class := "") {
	global
	CreateHString(string, &hString)
	if (interface = "")
		result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", &Class, "uint")
	else {
		VarSetStrCapacity(&GUID, 16) ; V1toV2: if 'GUID' is NOT a UTF-16 string, use 'GUID := Buffer(16)'
		DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", GUID)
		result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", GUID, "ptr*", &Class, "uint")
	}
	if (result != 0) {
		if (result = 0x80004002)
			MsgBox("No such interface supported")
		else if (result = 0x80040154)
			MsgBox("Class not registered")
		else
			MsgBox("error: " result)
		ExitApp()
	}
	DeleteHString(hString)
}

CreateHString(string, &hString) {
	global
	DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", &hString)
}

DeleteHString(hString) {
	global
	DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(&Object) {
	global
	AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
	Loop {
		DllCall(NumGet(NumGet(AsyncInfo+0, "UPtr")+7*A_PtrSize, "UPtr"), "ptr", AsyncInfo, "uint*", &status)   ; IAsyncInfo.Status
		if (status != 0) {
			if (status != 1) {
				DllCall(NumGet(NumGet(AsyncInfo+0, "UPtr")+8*A_PtrSize, "UPtr"), "ptr", AsyncInfo, "uint*", &ErrorCode)   ; IAsyncInfo.ErrorCode
				MsgBox("AsyncInfo status error: " ErrorCode)
				ExitApp()
			}
			ObjRelease(AsyncInfo)
			break
		}
		Sleep(10)
	}
	DllCall(NumGet(NumGet(Object+0, "UPtr")+8*A_PtrSize, "UPtr"), "ptr", Object, "ptr*", &ObjectResult)   ; GetResults
	ObjReleaseClose(&Object)
	Object := ObjectResult
}

ObjReleaseClose(&Object) {
	global
	if Object {
		if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")) {
			DllCall(NumGet(NumGet(Close+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", Close)   ; Close
			ObjRelease(Close)
		}
		ObjRelease(Object)
	}
	Object := ""
}
I also have the following error list from the AHK v2 script:
And incase it is relevant, here is the Windows version info from both machines:
My PCs Version Info
Sandbox Version Info
Last edited by gregster on 25 Mar 2023, 04:34, edited 1 time in total.
Reason: Removed img-tags/fixed broken links. You can only use those tags with direct image links.

Post Reply

Return to “Ask for Help (v2)”