VoiceMeeter-interface/VB.ahk

293 lines
7.0 KiB
AutoHotkey

#NoEnv
#SingleInstance force
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#UseHook
ListLines Off
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetTitleMatchMode RegEx
StringCaseSense Off
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
OnExit("cleanup_before_exit")
SetFormat, Float, 0.3
global VMR_FUNCTIONS := {}
global VMR_DLL_DRIVE := "C:"
global VMR_DLL_DIRPATH := "Program Files (x86)\VB\Voicemeeter"
global VMR_DLL_FILENAME_32 := "VoicemeeterRemote.dll"
global VMR_DLL_FILENAME_64 := "VoicemeeterRemote64.dll"
global VMR_DLL_FULL_PATH := VMR_DLL_DRIVE . "\" . VMR_DLL_DIRPATH . "\"
Sleep, 500
if (A_Is64bitOS) {
VMR_DLL_FULL_PATH .= VMR_DLL_FILENAME_64
} else {
VMR_DLL_FULL_PATH .= VMR_DLL_FILENAME_32
}
; == START OF EXECUTION ==
; ========================
; Load the VoicemeeterRemote DLL:
; This returns a module handle
global VMR_MODULE := DllCall("LoadLibrary", "Str", VMR_DLL_FULL_PATH, "Ptr")
if (ErrorLevel || VMR_MODULE == 0)
die("Attempt to load VoiceMeeter Remote DLL failed.")
; Populate VMR_FUNCTIONS
add_vmr_function("Login")
add_vmr_function("Logout")
add_vmr_function("RunVoicemeeter")
add_vmr_function("SetParameterFloat")
add_vmr_function("GetParameterFloat")
add_vmr_function("IsParametersDirty")
; "Login" to Voicemeeter, by calling the function in the DLL named 'VBVMR_Login()'...
login_result := DllCall(VMR_FUNCTIONS["Login"], "Int")
if (ErrorLevel || login_result < 0)
die("VoiceMeeter Remote login failed.")
; If the login returns 1, that apparently means that Voicemeeter isn't running,
; so we start it; pass 1 to run Voicemeeter, or 2 for Voicemeeter Banana:
if (login_result == 1) {
DllCall(VMR_FUNCTIONS["RunVoicemeeter"], "Int", 2, "Int")
if (ErrorLevel)
die("Attempt to run VoiceMeeter failed.")
Sleep 2000
}
; == HOTKEYS ==
; =============
Volume_Up::
If GetKeyState("ScrollLock", "T") ; Control music volume if scroll lock is on
{
cLvl := readParam("Strip[2]" . ".Gain")
if (cLvl != "")
{
cLvl += 1
adjustVolLvl("Strip[2]" . ".Gain", cLvl)
}
Return
}
b0M := Round(readParam("Bus[0]" . ".Mute"))
b1M := Round(readParam("Bus[1]" . ".Mute"))
if !(b0M)
{
cLvl := readParam("Bus[0]" . ".Gain")
if (cLvl != "")
{
cLvl += 1
adjustVolLvl("Bus[0]" . ".Gain", cLvl)
}
}
if !(b1M)
{
cLvl := readParam("Bus[1]" . ".Gain")
if (cLvl != "")
{
cLvl += 1
adjustVolLvl("Bus[1]" . ".Gain", cLvl)
}
}
return
Volume_Down::
If GetKeyState("ScrollLock", "T") ; Control music volume if scroll lock is on
{
cLvl := readParam("Strip[2]" . ".Gain")
if (cLvl != "")
{
cLvl -= 1
adjustVolLvl("Strip[2]" . ".Gain", cLvl)
}
Return
}
b0M := Round(readParam("Bus[0]" . ".Mute"))
b1M := Round(readParam("Bus[1]" . ".Mute"))
if !(b0M)
{
cLvl := readParam("Bus[0]" . ".Gain")
if (cLvl != "")
{
cLvl -= 1
adjustVolLvl("Bus[0]" . ".Gain", cLvl)
}
}
if !(b1M)
{
cLvl := readParam("Bus[1]" . ".Gain")
if (cLvl != "")
{
cLvl -= 1
adjustVolLvl("Bus[1]" . ".Gain", cLvl)
}
}
return
Volume_Mute::
If (GetKeyState("Media_Stop")) ; Mutes all output. Basically a kill switch
{
b0M := Round(readParam("Bus[0]" . ".Mute")) ; Speakers
b1M := Round(readParam("Bus[1]" . ".Mute")) ; Headphones
cM := b0M + b1M
if (cM = "2")
{ ; Unmute the ones that were unmuted before
adjustMute("Bus[0]" . ".Mute", b0Ms) ; Speakers
adjustMute("Bus[1]" . ".Mute", b1Ms) ; Headphones
} else {
if !(b0M) ; Speakers
{
b0Ms := True
} else {
b0Ms := False
}
if !(b1M) ; Headphones
{
b1Ms := True
} else {
b1Ms := False
}
; Mute
adjustMute("Bus[0]" . ".Mute", "0") ; Speakers
adjustMute("Bus[1]" . ".Mute", "0") ; Headphones
}
Return
}
cM := Round(readParam("Bus[1]" . ".Mute")) ; Toggles between the speakers and headphones being muted, normal operation
if (cM)
{
adjustMute("Bus[0]" . ".Mute", "0") ; Speakers
adjustMute("Bus[1]" . ".Mute", "1") ; Headphones
}
if !(cM)
{
adjustMute("Bus[0]" . ".Mute", "1") ; Speakers
adjustMute("Bus[1]" . ".Mute", "0") ; Headphones
}
return
!m:: ; Mute: No audio out
Send {F23}
b3M := Round(readParam("Bus[3]" . ".Mute")) ; Comms IN
s4M := Round(readParam("Strip[4]" . ".Mute")) ; Comms OUT
If (s4M)
{
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
return
}
If !(b3M)
{
adjustMute("Bus[3]" . ".Mute", "0")
} else {
adjustMute("Bus[3]" . ".Mute", "1")
}
Return
!n:: ; Deafen: No audio in or out
Send {F24}
s4M := Round(readParam("Strip[4]" . ".Mute")) ; Comms OUT
If (s4M)
{
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
} else {
adjustMute("Bus[3]" . ".Mute", "0") ; Comms IN
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
adjustMute("Strip[4]" . ".Mute", "0") ; Comms OUT
}
Return
!j:: ; Mute toggle for meetings on work laptop
Send {F24}
cM := Round(readParam("Bus[2]" . ".Mute"))
if (cM)
{
adjustMute("Bus[2]" . ".Mute", "1") ; Work Laptop
adjustMute("Bus[3]" . ".Mute", "0") ; Comms IN
adjustMute("Strip[3]" . ".Mute", "0") ; Desktop
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
adjustMute("Strip[4]" . ".Mute", "0") ; Comms OUT
}
if !(cM)
{
adjustMute("Bus[2]" . ".Mute", "0") ; Work Laptop
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
adjustMute("Strip[3]" . ".Mute", "1") ; Desktop
}
Return
; == Functions ==
; ===============
readParam(loc){
Loop
{
pDirty := DLLCall(VMR_FUNCTIONS["IsParametersDirty"]) ;Check if parameters have changed.
if (pDirty==0) ;0 = no new paramters.
break
else if (pDirty<0) ;-1 = error, -2 = no server
return ""
else ;1 = New parameters -> update your display. (this only applies if YOU have a display, couldn't find any code to update VM display which can get off sometimes)
if A_Index > 200
return ""
sleep, 20
}
tParamVal := 0.0
NumPut(0.0, tParamVal, 0, "Float")
statusLvl := DllCall(VMR_FUNCTIONS["GetParameterFloat"], "AStr", loc, "Ptr", &tParamVal, "Int")
tParamVal := NumGet(tParamVal, 0, "Float")
if (statusLvl < 0)
return ""
else
return tParamVal
}
adjustVolLvl(loc, tVol) {
if (tVol > 12.0)
tVol := 12.0
else if (tVol < -60.0)
tVol := -60.0
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tVol, "Int")
}
adjustMute(loc, tM) {
if (tM = 0)
tM := 1
else
tM := 0
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tM, "Int")
}
add_vmr_function(func_name) {
VMR_FUNCTIONS[func_name] := DllCall("GetProcAddress", "Ptr", VMR_MODULE, "AStr", "VBVMR_" . func_name, "Ptr")
if (ErrorLevel || VMR_FUNCTIONS[func_name] == 0)
die("Failed to register VMR function " . func_name . ".")
}
cleanup_before_exit(exit_reason, exit_code) {
DllCall(VMR_FUNCTIONS["Logout"], "Int")
; OnExit functions must return 0 to allow the app to exit.
return 0
}
die(die_string:="UNSPECIFIED FATAL ERROR.", exit_status:=254) {
MsgBox 16, FATAL ERROR, %die_string%
ExitApp exit_status
}