Compare commits

...

5 Commits

Author SHA1 Message Date
2ad8118f2c adjust the timings slightly 2023-08-17 00:14:12 +01:00
bc6162cf16 add cmdletbinding to examples for debug, verbose flags
add verbose,debug flags to launch scripts
2023-08-16 16:38:00 +01:00
9b3d9f2250 remove Write-Warning for CAPIErrors.
Allow them to bubble up.
(Might be worth adding a helper function to print stacktrace?)
2023-08-16 16:36:43 +01:00
844eaeabaa ErrorMessage removed from error classes 2023-08-16 15:13:30 +01:00
a78cdf9a99 RunVoicemeeter function added
All CAPIErrors are now logged and rethrown
2023-08-16 15:12:25 +01:00
9 changed files with 126 additions and 151 deletions

14
.vscode/launch.json vendored
View File

@ -16,7 +16,9 @@
"\"!strip[0].mute\",", "\"!strip[0].mute\",",
"\"strip[0].mute\",", "\"strip[0].mute\",",
"\"bus[2].eq.on=1\",", "\"bus[2].eq.on=1\",",
"\"command.lock=1\"" "\"command.lock=1\"",
"-Verbose",
"-Debug"
], ],
"createTemporaryIntegratedConsole": true "createTemporaryIntegratedConsole": true
}, },
@ -26,7 +28,10 @@
"request": "launch", "request": "launch",
"cwd": "${workspaceRoot}/examples/nextbus", "cwd": "${workspaceRoot}/examples/nextbus",
"script": "${workspaceFolder}/examples/nextbus/GoTo-NextBus.ps1", "script": "${workspaceFolder}/examples/nextbus/GoTo-NextBus.ps1",
"args": [], "args": [
"-Verbose",
"-Debug"
],
"createTemporaryIntegratedConsole": true "createTemporaryIntegratedConsole": true
}, },
{ {
@ -35,7 +40,10 @@
"request": "launch", "request": "launch",
"cwd": "${workspaceRoot}/examples/obs", "cwd": "${workspaceRoot}/examples/obs",
"script": "${workspaceFolder}/examples/obs/Vm-Obs-Sync.ps1", "script": "${workspaceFolder}/examples/obs/Vm-Obs-Sync.ps1",
"args": [], "args": [
"-Verbose",
"-Debug"
],
"createTemporaryIntegratedConsole": true "createTemporaryIntegratedConsole": true
}, },
{ {

View File

@ -1,14 +1,12 @@
[cmdletbinding()]
param( param(
[switch]$interactive, [switch]$interactive,
[switch]$output,
[String]$kind = "banana", [String]$kind = "banana",
[String[]]$script = @() [String[]]$script = @()
) )
Import-Module ..\..\lib\Voicemeeter.psm1 Import-Module ..\..\lib\Voicemeeter.psm1
$VerbosePreference = "Continue"
function get-value { function get-value {
param([object]$vmr, [string]$line) param([object]$vmr, [string]$line)
try { try {
@ -24,16 +22,16 @@ function msgHandler {
param([object]$vmr, [string]$line) param([object]$vmr, [string]$line)
$line + " passed to handler" | Write-Debug $line + " passed to handler" | Write-Debug
if ($line[0] -eq "!") { if ($line[0] -eq "!") {
if ($output) { "Toggling " + $line.substring(1) | Write-Host } "Toggling " + $line.substring(1) | Write-Debug
$retval = get-value -vmr $vmr -line $line.substring(1) $retval = get-value -vmr $vmr -line $line.substring(1)
$vmr.Setter($line.substring(1), 1 - $retval) $vmr.Setter($line.substring(1), 1 - $retval)
} }
elseif ($line.Contains("=")) { elseif ($line.Contains("=")) {
if ($output) { "Setting $line" | Write-Host } "Setting $line" | Write-Debug
$vmr.SendText($line) $vmr.SendText($line)
} }
else { else {
if ($output) { "Getting $line" | Write-Host } "Getting $line" | Write-Debug
$retval = get-value -vmr $vmr -line $line $retval = get-value -vmr $vmr -line $line
$line + " = " + $retval | Write-Host $line + " = " + $retval | Write-Host
} }

View File

@ -7,27 +7,30 @@
Credits go to @bobsupercow Credits go to @bobsupercow
#> #>
Import-Module ..\..\lib\Voicemeeter.psm1 [cmdletbinding()]
param()
$VerbosePreference = "Continue" Import-Module ..\..\lib\Voicemeeter.psm1
try { try {
$vmr = Connect-Voicemeeter -Kind "potato" $vmr = Connect-Voicemeeter -Kind "potato"
$buses = @($vmr.bus[1], $vmr.bus[2], $vmr.bus[4], $vmr.bus[6]) $buses = @($vmr.bus[1], $vmr.bus[2], $vmr.bus[4], $vmr.bus[6])
"Buses in selection: $($buses)"
$unmutedIndex = $null $unmutedIndex = $null
# 1) # 1)
"Cycling through bus selection to check for first unmuted Bus..." | Write-Host
foreach ($bus in $buses) { foreach ($bus in $buses) {
# 2) # 2)
if (-not $bus.mute) { if (-not $bus.mute) {
"bus $($bus.index) is unmuted... muting it" | Write-Host "Bus $($bus.index) is unmuted... muting it" | Write-Host
$unmutedIndex = $buses.IndexOf($bus) $unmutedIndex = $buses.IndexOf($bus)
$bus.mute = $true $bus.mute = $true
# 3) # 3)
if ($buses[++$unmutedIndex]) { if ($buses[++$unmutedIndex]) {
"unmuting bus $($buses[$unmutedIndex].index)" | Write-Host "Unmuting Bus $($buses[$unmutedIndex].index)" | Write-Host
$buses[$unmutedIndex].mute = $false $buses[$unmutedIndex].mute = $false
break break
} }
@ -37,7 +40,7 @@ try {
# 4) # 4)
if ($null -eq $unmutedIndex) { if ($null -eq $unmutedIndex) {
$buses[0].mute = $false $buses[0].mute = $false
"unmuting bus $($buses[0].index)" | Write-Host "Unmuting Bus $($buses[0].index)" | Write-Host
} }
} }

View File

@ -1,8 +1,9 @@
[cmdletbinding()]
param()
Import-Module ..\..\lib\Voicemeeter.psm1 Import-Module ..\..\lib\Voicemeeter.psm1
Import-Module obs-powershell Import-Module obs-powershell
$VerbosePreference = "Continue"
function CurrentProgramSceneChanged { function CurrentProgramSceneChanged {
param([System.Object]$data) param([System.Object]$data)
Write-Host "Switched to scene", $data.sceneName Write-Host "Switched to scene", $data.sceneName
@ -10,19 +11,15 @@ function CurrentProgramSceneChanged {
switch ($data.sceneName) { switch ($data.sceneName) {
"START" { "START" {
$vmr.strip[0].mute = !$vmr.strip[0].mute $vmr.strip[0].mute = !$vmr.strip[0].mute
"Toggling Strip 0 mute"
} }
"BRB" { "BRB" {
$vmr.strip[0].gain = -8.3 $vmr.strip[0].gain = -8.3
"Setting Strip 0 gain to -8.3"
} }
"END" { "END" {
$vmr.strip[0].mono = $true $vmr.strip[0].mono = $true
"Setting Strip 0 mono to `$true"
} }
"LIVE" { "LIVE" {
$vmr.strip[0].color_x = 0.3 $vmr.strip[0].color_x = 0.3
"Setting Strip 0 color_x to 0.3"
} }
default { "Expected START, BRB, END or LIVE scene" | Write-Warning; return } default { "Expected START, BRB, END or LIVE scene" | Write-Warning; return }
} }

View File

@ -137,30 +137,20 @@ Function Get-RemotePotato {
Function Connect-Voicemeeter { Function Connect-Voicemeeter {
param([String]$Kind) param([String]$Kind)
try { switch ($Kind) {
switch ($Kind) { "basic" {
"basic" { return Get-RemoteBasic
return Get-RemoteBasic
}
"banana" {
return Get-RemoteBanana
}
"potato" {
return Get-RemotePotato
}
default { throw [LoginError]::new("Unknown Voicemeeter kind `"$Kind`"") }
}
}
catch [LoginError], [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
throw
}
catch [VMRemoteError] {
$_.Exception.ErrorMessage() | Write-Warning
if ($_.Exception.ErrorMessage() -eq "Couldn't get Voicemeeter path") {
Exit -1
} }
} "banana" {
return Get-RemoteBanana
}
"potato" {
return Get-RemotePotato
}
default {
throw [LoginError]::new("Unknown Voicemeeter kind `"$Kind`"")
}
}
} }
Function Disconnect-Voicemeeter { Function Disconnect-Voicemeeter {

View File

@ -5,38 +5,19 @@ function Login {
param( param(
[string]$kindId [string]$kindId
) )
try { $retval = [int][Voicemeeter.Remote]::VBVMR_Login()
$retval = [int][Voicemeeter.Remote]::VBVMR_Login() if ($retval -notin @(0, 1, -2)) {
if ($retval -ne 0) { throw [CAPIError]::new($retval, "VBVMR_Login")
switch ($retval) {
1 {
New-Variable -Name vmExe -Value 0
if ( $kindId -eq "basic" ) { $vmExe = 1 }
elseif ( $kindId -eq "banana" ) { $vmExe = 2 }
elseif ( $kindId -eq "potato" ) {
$vmExe = $(if ([Environment]::Is64BitOperatingSystem) { 6 } else { 3 })
}
$retval = [int][Voicemeeter.Remote]::VBVMR_RunVoicemeeter([int64]$vmExe)
if (-not $retval) {
"Voicemeeter Engine running but GUI not launched. Launching GUI now." | Write-Verbose
Start-Sleep -s 1
}
else {
throw [CAPIError]::new($retval, $MyInvocation.MyCommand)
}
}
-2 {
throw [LoginError]::new('Login may only be called once per session')
}
default { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) }
}
}
} }
catch [LoginError] {
"$($_.Exception.ErrorMessage()). Fatal error, exiting..." | Write-Warning switch ($retval) {
exit -2 1 {
"Voicemeeter Engine running but GUI not launched. Launching GUI now." | Write-Verbose
RunVoicemeeter -kindId $kindId
}
-2 {
throw [LoginError]::new("Login may only be called once per session.")
}
} }
while (P_Dirty -or M_Dirty) { Start-Sleep -m 1 } while (P_Dirty -or M_Dirty) { Start-Sleep -m 1 }
@ -44,23 +25,53 @@ function Login {
} }
function Logout { function Logout {
Start-Sleep -m 20 Start-Sleep -m 100
$retval = [int][Voicemeeter.Remote]::VBVMR_Logout() $retval = [int][Voicemeeter.Remote]::VBVMR_Logout()
if ($retval -eq 0) { "Sucessfully logged out" | Write-Verbose } if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_Logout")
}
if ($retval -eq 0) { "Sucessfully logged out" | Write-Verbose }
}
function RunVoicemeeter {
param(
[string]$kindId
)
$kinds = @{
"basic" = 1
"banana" = 2
"potato" = $(if ([Environment]::Is64BitOperatingSystem) { 6 } else { 3 })
}
$retval = [int][Voicemeeter.Remote]::VBVMR_RunVoicemeeter([int64]$kinds[$kindId])
if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_RunVoicemeeter")
}
Start-Sleep -s 1
} }
function P_Dirty { function P_Dirty {
[bool][Voicemeeter.Remote]::VBVMR_IsParametersDirty() $retval = [Voicemeeter.Remote]::VBVMR_IsParametersDirty()
if ($retval -notin @(0, 1)) {
throw [CAPIError]::new($retval, "VBVMR_RunVoicemeeter")
}
[bool]$retval
} }
function M_Dirty { function M_Dirty {
[bool][Voicemeeter.Remote]::VBVMR_MacroButton_IsDirty() $retval = [Voicemeeter.Remote]::VBVMR_MacroButton_IsDirty()
if ($retval -notin @(0, 1)) {
throw [CAPIError]::new($retval, "VBVMR_RunVoicemeeter")
}
[bool]$retval
} }
function VmType { function VmType {
New-Variable -Name ptr -Value 0 New-Variable -Name ptr -Value 0
$retval = [int][Voicemeeter.Remote]::VBVMR_GetVoicemeeterType([ref]$ptr) $retval = [int][Voicemeeter.Remote]::VBVMR_GetVoicemeeterType([ref]$ptr)
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_GetVoicemeeterType")
}
switch ($ptr) { switch ($ptr) {
1 { return "basic" } 1 { return "basic" }
2 { return "banana" } 2 { return "banana" }
@ -71,7 +82,9 @@ function VmType {
function VmVersion { function VmVersion {
New-Variable -Name ptr -Value 0 New-Variable -Name ptr -Value 0
$retval = [int][Voicemeeter.Remote]::VBVMR_GetVoicemeeterVersion([ref]$ptr) $retval = [int][Voicemeeter.Remote]::VBVMR_GetVoicemeeterVersion([ref]$ptr)
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_GetVoicemeeterVersion")
}
$v1 = ($ptr -band 0xFF000000) -shr 24 $v1 = ($ptr -band 0xFF000000) -shr 24
$v2 = ($ptr -band 0x00FF0000) -shr 16 $v2 = ($ptr -band 0x00FF0000) -shr 16
$v3 = ($ptr -band 0x0000FF00) -shr 8 $v3 = ($ptr -band 0x0000FF00) -shr 8
@ -84,28 +97,22 @@ function Param_Get {
param( param(
[string]$PARAM, [bool]$IS_STRING = $false [string]$PARAM, [bool]$IS_STRING = $false
) )
Start-Sleep -m 50 Start-Sleep -m 30
while (P_Dirty) { Start-Sleep -m 1 } while (P_Dirty) { Start-Sleep -m 1 }
if ($IS_STRING) { if ($IS_STRING) {
$BYTES = [System.Byte[]]::new(512) $BYTES = [System.Byte[]]::new(512)
try { $retval = [int][Voicemeeter.Remote]::VBVMR_GetParameterStringA($PARAM, $BYTES)
$retval = [int][Voicemeeter.Remote]::VBVMR_GetParameterStringA($PARAM, $BYTES) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, "VBVMR_GetParameterStringA")
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
[System.Text.Encoding]::ASCII.GetString($BYTES).Trim([char]0) [System.Text.Encoding]::ASCII.GetString($BYTES).Trim([char]0)
} }
else { else {
New-Variable -Name ptr -Value 0.0 New-Variable -Name ptr -Value 0.0
try { $retval = [int][Voicemeeter.Remote]::VBVMR_GetParameterFloat($PARAM, [ref]$ptr)
$retval = [int][Voicemeeter.Remote]::VBVMR_GetParameterFloat($PARAM, [ref]$ptr) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, "VBVMR_GetParameterFloat")
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
[single]$ptr [single]$ptr
} }
@ -115,17 +122,17 @@ function Param_Set {
param( param(
[string]$PARAM, [Object]$VALUE [string]$PARAM, [Object]$VALUE
) )
try { if ($VALUE -is [string]) {
if ($VALUE -is [string]) { $retval = [int][Voicemeeter.Remote]::VBVMR_SetParameterStringA($PARAM, $VALUE)
$retval = [int][Voicemeeter.Remote]::VBVMR_SetParameterStringA($PARAM, $VALUE) if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_SetParameterStringA")
} }
else {
$retval = [int][Voicemeeter.Remote]::VBVMR_SetParameterFloat($PARAM, $VALUE)
}
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) }
} }
catch [CAPIError] { else {
Write-Warning $_.Exception.ErrorMessage() $retval = [int][Voicemeeter.Remote]::VBVMR_SetParameterFloat($PARAM, $VALUE)
if ($retval -notin @(0)) {
throw [CAPIError]::new($retval, "VBVMR_SetParameterFloat")
}
} }
} }
@ -133,12 +140,9 @@ function MB_Set {
param( param(
[int64]$ID, [single]$SET, [int64]$MODE [int64]$ID, [single]$SET, [int64]$MODE
) )
try { $retval = [int][Voicemeeter.Remote]::VBVMR_MacroButton_SetStatus($ID, $SET, $MODE)
$retval = [int][Voicemeeter.Remote]::VBVMR_MacroButton_SetStatus($ID, $SET, $MODE) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, "VBVMR_MacroButton_SetStatus")
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
} }
@ -150,12 +154,9 @@ function MB_Get {
while (M_Dirty) { Start-Sleep -m 1 } while (M_Dirty) { Start-Sleep -m 1 }
New-Variable -Name ptr -Value 0.0 New-Variable -Name ptr -Value 0.0
try { $retval = [int][Voicemeeter.Remote]::VBVMR_MacroButton_GetStatus($ID, [ref]$ptr, $MODE)
$retval = [int][Voicemeeter.Remote]::VBVMR_MacroButton_GetStatus($ID, [ref]$ptr, $MODE) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, $MyInvocation.MyCommand)
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
[int]$ptr [int]$ptr
} }
@ -187,12 +188,9 @@ function Set_By_Script {
param( param(
[string]$script [string]$script
) )
try { $retval = [int][Voicemeeter.Remote]::VBVMR_SetParameters($script)
$retval = [int][Voicemeeter.Remote]::VBVMR_SetParameters($script) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, "VBVMR_SetParameters")
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
} }
@ -201,12 +199,9 @@ function Get_Level {
[int64]$MODE, [int64]$INDEX [int64]$MODE, [int64]$INDEX
) )
New-Variable -Name ptr -Value 0.0 New-Variable -Name ptr -Value 0.0
try { $retval = [int][Voicemeeter.Remote]::VBVMR_GetLevel($MODE, $INDEX, [ref]$ptr)
$retval = [int][Voicemeeter.Remote]::VBVMR_GetLevel($MODE, $INDEX, [ref]$ptr) if ($retval -notin @(0)) {
if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } throw [CAPIError]::new($retval, "VBVMR_GetLevel")
}
catch [CAPIError] {
Write-Warning $_.Exception.ErrorMessage()
} }
[float]$ptr [float]$ptr
} }

View File

@ -1,17 +1,10 @@
class VMRemoteError : Exception { class VMRemoteError : Exception {
[string]$msg VMRemoteError ([string]$msg) : base ($msg) {
VMRemoteError ([string]$msg) {
$this.msg = $msg
}
[string] ErrorMessage () {
return $this.msg
} }
} }
class LoginError : VMRemoteError { class LoginError : VMRemoteError {
LoginError ([string]$msg) : base ([string]$msg) { LoginError ([string]$msg) : base ($msg) {
} }
} }
@ -19,12 +12,8 @@ class CAPIError : VMRemoteError {
[int]$retval [int]$retval
[string]$caller [string]$caller
CAPIError ([int]$retval, [string]$caller) { CAPIError ([int]$retval, [string]$caller) : base ("$caller returned $retval") {
$this.retval = $retval $this.retval = $retval
$this.caller = $caller $this.caller = $caller
} }
}
[string] ErrorMessage () {
return "CAPI return value: {0} in {1}" -f $this.retval, $this.caller
}
}

View File

@ -8,6 +8,6 @@ function Get_VMPath {
return $(Get-ItemPropertyValue -Path ($REG_KEY + $VM_KEY) -Name UninstallString | Split-Path -Parent) return $(Get-ItemPropertyValue -Path ($REG_KEY + $VM_KEY) -Name UninstallString | Split-Path -Parent)
} }
catch { catch {
throw [VMRemoteError]::new("Couldn't get Voicemeeter path") throw [VMRemoteError]::new("Unable to fetch Voicemeeter path from the Registry.")
} }
} }

View File

@ -24,14 +24,9 @@ function Set_Profile {
param( param(
[Object]$DATA, [string]$CONF [Object]$DATA, [string]$CONF
) )
try { if ($null -eq $DATA -or -not $DATA.$CONF) {
if ($null -eq $DATA -or -not $DATA.$CONF) { throw [VMRemoteErrors]::new("No profile named '$CONF' has been loaded into memory.")
throw [VMRemoteErrors]::new("No profile named $CONF was loaded")
}
Param_Set_Multi -HASH $DATA.$CONF
Start-Sleep -m 1
}
catch [VMRemoteErrors] {
Write-Warning $_.Exception.ErrorMessage()
} }
Param_Set_Multi -HASH $DATA.$CONF
Start-Sleep -m 1
} }