Compare commits

..

No commits in common. "1ad91b455ab232fa386eb72e0f96eca62ff3af81" and "f40e0afb0d3b4a3dd20c9fff2b0e773ebb15ef1c" have entirely different histories.

6 changed files with 160 additions and 555 deletions

View File

@ -15,9 +15,6 @@ AddActionMembers now adds ScriptMethods instead of ScriptProperties:
- See Command section of README for details on using special commands - See Command section of README for details on using special commands
- See Recorder section of README for details on using playback/record actions - See Recorder section of README for details on using playback/record actions
Deprecated Recorder.Loop removed: use Recorder.Mode.Loop
Recorder.FileType changed from method to write-only property
### Added ### Added
- IRemote base class - IRemote base class
@ -34,15 +31,6 @@ Recorder.FileType changed from method to write-only property
- ip, write-only - ip, write-only
- Bus.Sel, Bus.Monitor, Bus.Vaio - Bus.Sel, Bus.Monitor, Bus.Vaio
- Bus.Mode.Set($mode) - Bus.Mode.Set($mode)
- Recorder.Armedbus
- Recorder.PreRecTime
- Recorder.Prefix
- Recorder.Eject() references 'Command.Eject'
- Recorder.State
- Command.Reset()
- Command.Save($filepath)
- Command.StorePreset()
- Command.RecallPreset()
### Changed ### Changed
@ -55,8 +43,6 @@ Recorder.FileType changed from method to write-only property
- Bus.Levels.Convert return type [float] -> [single] for naming consistency, no functional change - Bus.Levels.Convert return type [float] -> [single] for naming consistency, no functional change
- Meta: AddBoolMembers, AddIntMembers $arg types for consistency - Meta: AddBoolMembers, AddIntMembers $arg types for consistency
- Device: explicit $arg types for consistency - Device: explicit $arg types for consistency
- Recorder.Armstrip|Armbus -> BoolArrayMember: now have .Get()
- Cast Recorder getters to types for consistency
### Fixed ### Fixed
@ -67,7 +53,6 @@ Recorder.FileType changed from method to write-only property
- vban.stream.port: [string]$arg -> [int]$arg - vban.stream.port: [string]$arg -> [int]$arg
- vban route range (API documentation is incorrect) - vban route range (API documentation is incorrect)
- vban.stream.sr: $this._port -> $this._sr - vban.stream.sr: $this._port -> $this._sr
- Recorder.channel values: 1..8 -> (2, 4, 6, 8)
## [3.3.0] - 2024-06-29 ## [3.3.0] - 2024-06-29

View File

@ -418,44 +418,33 @@ $vmr.vban.outstream[3].bit = 16
Certain 'special' commands are defined by the API as performing actions rather than setting values. Certain 'special' commands are defined by the API as performing actions rather than setting values.
The following commands are available:
- hide
- showvbanchat: bool, (write only)
- lock: bool, (write only)
The following methods are available: The following methods are available:
- Show() - Show()
- Hide()
- Lock()
- Unlock()
- ShowVBANChat()
- HideVBANChat()
- Restart() - Restart()
- Shutdown() - Shutdown()
- Reset(): Reset all config
- Save($filepath): string
- Load($filepath): string - Load($filepath): string
- StorePreset($index, $name): (int, string)
- RecallPreset($index or $name): (int or string)
- RunMacrobuttons(): Launches the macrobuttons app - RunMacrobuttons(): Launches the macrobuttons app
- CloseMacrobuttons(): Closes the macrobuttons app - CloseMacrobuttons(): Closes the macrobuttons app
example: example:
```powershell ```powershell
$vmr.command.Show() $vmr.command.show()
$vmr.command.Lock()
$vmr.command.lock = $true
$vmr.command.Load("path/to/filename.xml") $vmr.command.Load("path/to/filename.xml")
$vmr.command.RunMacrobuttons() $vmr.command.RunMacrobuttons()
$vmr.command.StorePreset(63, 'example')
$vmr.command.StorePreset('example')
$vmr.command.StorePreset(63) # same as StorePreset(63, '')
$vmr.command.StorePreset() # same as StorePreset(''), overwrites last recalled
$vmr.command.RecallPreset('example')
$vmr.command.RecallPreset(63)
$vmr.command.RecallPreset() # same as RecallPreset(''), recalls last recalled
``` ```
StorePreset('') and RecallPreset('') interact with the 'selected' preset. This is highlighted green in the GUI. Recalling a preset selects it. Storing a preset via GUI also selects it. Storing a preset with StorePreset does not select it.
### Fx ### Fx
The following Fx commands are available: The following Fx commands are available:
@ -538,15 +527,9 @@ The following commands are available:
- A1 - A5: bool - A1 - A5: bool
- B1 - B3: bool - B1 - B3: bool
- gain: float, from -60.0 to 12.0
- armedbus: int, from 0 to bus index
- state: string, ('play', 'stop', 'record', 'pause')
- prerectime: int, from 0 to 20 seconds
- prefix: string, write-only
- filetype: string, write-only, ('wav', 'aiff', 'bwf', 'mp3')
- samplerate: int, (22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000) - samplerate: int, (22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000)
- bitresolution: int, (8, 16, 24, 32) - bitresolution: int, (8, 16, 24, 32)
- channel: int, (2, 4, 6, 8) - channel: int, from 1 to 8
- kbps: int, (32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320) - kbps: int, (32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)
The following methods are available: The following methods are available:
@ -558,9 +541,9 @@ The following methods are available:
- Rew() - Rew()
- Record() - Record()
- Pause() - Pause()
- Eject()
- Load($filepath): string - Load($filepath): string
- GoTo($timestring): string, must match the format 'hh:mm:ss' - GoTo($timestring): string, must match the format 'hh:mm:ss'
- FileType($format): string, ('wav', 'aiff', 'bwf', 'mp3')
example: example:
@ -588,10 +571,9 @@ $vmr.recorder.mode.loop = $true
#### ArmStrip[i]|ArmBus[i] #### ArmStrip[i]|ArmBus[i]
The following methods are available: The following method is available:
- Set($val): bool - Set($val): bool
- Get()
example: example:

View File

@ -1,6 +1,6 @@
class Special : IRemote { class Special : IRemote {
Special ([Object]$remote) : base ($remote) { Special ([Object]$remote) : base ($remote) {
AddActionMembers -PARAMS @('restart', 'shutdown', 'show', 'lock', 'reset') AddActionMembers -PARAMS @('restart', 'shutdown', 'show')
} }
[string] identifier () { [string] identifier () {
@ -17,57 +17,36 @@ class Special : IRemote {
Stop-Process -Name 'VoicemeeterMacroButtons' Stop-Process -Name 'VoicemeeterMacroButtons'
} }
[void] Hide () { hidden $_hide = $($this | Add-Member ScriptProperty 'hide' `
$this.Setter('show', $false) {
} $this._hide = $this.Setter('show', $false)
} `
{}
)
[void] Unlock () { hidden $_showvbanchat = $($this | Add-Member ScriptProperty 'showvbanchat' `
$this.Setter('lock', $false) {
} $this.Getter('DialogShow.VBANCHAT')
} `
{
param([bool]$arg)
$this._showvbanchat = $this.Setter('DialogShow.VBANCHAT', $arg)
}
)
[void] ShowVBANChat () { hidden $_lock = $($this | Add-Member ScriptProperty 'lock' `
$this.Setter('DialogShow.VBANCHAT', $true) {
} $this._lock = $this.Getter('lock')
} `
[void] HideVBANChat () { {
$this.Setter('DialogShow.VBANCHAT', $false) param([bool]$arg)
} $this._lock = $this.Setter('lock', $arg)
}
)
[void] Load ([string]$filename) { [void] Load ([string]$filename) {
$this.Setter('load', $filename) $this.Setter('load', $filename)
} }
[void] Save ([string]$filename) {
$this.Setter('save', $filename)
}
[void] StorePreset () {
$this.Setter('updatepreset', '')
}
[void] StorePreset ([string]$name) {
$this.Setter('updatepreset', $name)
}
[void] StorePreset ([int]$index) {
$this.Setter('preset[{0}].store' -f $index, '')
}
[void] StorePreset ([int]$index, [string]$name) {
$this.Setter('preset[{0}].store' -f $index, $name)
}
[void] RecallPreset () {
$this.Setter('recallpreset', '')
}
[void] RecallPreset ([string]$name) {
$this.Setter('recallpreset', $name)
}
[void] RecallPreset ([int]$index) {
$this.Setter('preset[{0}].recall' -f $index, 1)
}
} }
function Make_Command([Object]$remote) { function Make_Command([Object]$remote) {

View File

@ -2,30 +2,20 @@ class Recorder : IRemote {
[Object]$mode [Object]$mode
[System.Collections.ArrayList]$armstrip [System.Collections.ArrayList]$armstrip
[System.Collections.ArrayList]$armbus [System.Collections.ArrayList]$armbus
[System.Collections.ArrayList]$states
Recorder ([Object]$remote) : base ($remote) { Recorder ([Object]$remote) : base ($remote) {
$this.mode = [RecorderMode]::new($remote) $this.mode = [RecorderMode]::new($remote)
$this.armstrip = @() $this.armstrip = @()
$stripCount = $($remote.kind.p_in + $remote.kind.v_in) 0..($remote.kind.p_in + $remote.kind.v_in - 1) | ForEach-Object {
for ($i = 0; $i -lt $stripCount; $i++) { $this.armstrip.Add([RecorderArmStrip]::new($_, $remote))
$this.armstrip.Add([BoolArrayMember]::new($i, 'armstrip', $this))
} }
$this.armbus = @() $this.armbus = @()
$busCount = $($remote.kind.p_out + $remote.kind.v_out) 0..($remote.kind.p_out + $remote.kind.v_out - 1) | ForEach-Object {
for ($i = 0; $i -lt $busCount; $i++) { $this.armbus.Add([RecorderArmBus]::new($_, $remote))
$this.armbus.Add([BoolArrayMember]::new($i, 'armbus', $this))
} }
$this.states = @('play', 'stop', 'record', 'pause') AddActionMembers -PARAMS @('play', 'stop', 'pause', 'replay', 'record', 'ff', 'rew')
AddActionMembers -PARAMS $this.states
AddActionMembers -PARAMS @('replay', 'ff', 'rew')
AddFloatMembers -PARAMS @('gain') AddFloatMembers -PARAMS @('gain')
AddIntMembers -PARAMS @('prerectime')
AddChannelMembers AddChannelMembers
} }
@ -33,9 +23,78 @@ class Recorder : IRemote {
return 'Recorder' return 'Recorder'
} }
[void] Eject () { hidden $_loop = $($this | Add-Member ScriptProperty 'loop' `
$this.remote.Setter('Command.Eject', 1) {
} [bool]$this.mode.loop
} `
{
param($arg)
$this.mode.loop = $arg
}
)
hidden $_samplerate = $($this | Add-Member ScriptProperty 'samplerate' `
{
$this.Getter('samplerate')
} `
{
param([int]$arg)
$opts = @(22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000)
if ($opts.Contains($arg)) {
$this._samplerate = $this.Setter('samplerate', $arg)
}
else {
"samplerate got: $arg, expected one of $opts" | Write-Warning
}
}
)
hidden $_bitresolution = $($this | Add-Member ScriptProperty 'bitresolution' `
{
$this.Getter('bitresolution')
} `
{
param([int]$arg)
$opts = @(8, 16, 24, 32)
if ($opts.Contains($arg)) {
$this._bitresolution = $this.Setter('bitresolution', $arg)
}
else {
"bitresolution got: $arg, expected one of $opts" | Write-Warning
}
}
)
hidden $_channel = $($this | Add-Member ScriptProperty 'channel' `
{
$this.Getter('channel')
} `
{
param([int]$arg)
if ($arg -ge 1 -and $arg -le 8) {
$this._channel = $this.Setter('channel', $arg)
}
else {
"channel got: $arg, expected value from 1 to 8" | Write-Warning
}
}
)
hidden $_kbps = $($this | Add-Member ScriptProperty 'kbps' `
{
$this.Getter('kbps')
} `
{
param([int]$arg)
$opts = @(32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)
if ($opts.Contains($arg)) {
$this._kbps = $this.Setter('kbps', $arg)
}
else {
"kbps got: $arg, expected one of $opts" | Write-Warning
}
}
)
[void] Load ([string]$filename) { [void] Load ([string]$filename) {
$this.Setter('load', $filename) $this.Setter('load', $filename)
@ -53,142 +112,17 @@ class Recorder : IRemote {
} }
} }
hidden $_samplerate = $($this | Add-Member ScriptProperty 'samplerate' ` [void] FileType($format) {
{ [int]$val = 0
[int]$this.Getter('samplerate') switch ($format) {
} ` 'wav' { $val = 1 }
{ 'aiff' { $val = 2 }
param([int]$arg) 'bwf' { $val = 3 }
$opts = @(22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000) 'mp3' { $val = 100 }
if ($opts.Contains($arg)) { default { "Filetype() got: $format, expected one of 'wav', 'aiff', 'bwf', 'mp3'" }
$this._samplerate = $this.Setter('samplerate', $arg)
}
else {
"samplerate got: $arg, expected one of $opts" | Write-Warning
}
} }
) $this.Setter('filetype', $val)
}
hidden $_bitresolution = $($this | Add-Member ScriptProperty 'bitresolution' `
{
[int]$this.Getter('bitresolution')
} `
{
param([int]$arg)
$opts = @(8, 16, 24, 32)
if ($opts.Contains($arg)) {
$this._bitresolution = $this.Setter('bitresolution', $arg)
}
else {
"bitresolution got: $arg, expected one of $opts" | Write-Warning
}
}
)
hidden $_channel = $($this | Add-Member ScriptProperty 'channel' `
{
[int]$this.Getter('channel')
} `
{
param([int]$arg)
$opts = @(2, 4, 6, 8)
if ($opts.Contains($arg)) {
$this._channel = $this.Setter('channel', $arg)
}
else {
"channel got: $arg, expected one of $opts" | Write-Warning
}
}
)
hidden $_kbps = $($this | Add-Member ScriptProperty 'kbps' `
{
[int]$this.Getter('kbps')
} `
{
param([int]$arg)
$opts = @(32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)
if ($opts.Contains($arg)) {
$this._kbps = $this.Setter('kbps', $arg)
}
else {
"kbps got: $arg, expected one of $opts" | Write-Warning
}
}
)
hidden $_prefix = $($this | Add-Member ScriptProperty 'prefix' `
{
return Write-Warning ("ERROR: $($this.identifier()).prefix is write only")
} `
{
param([string]$arg)
$this._prefix = $this.Setter('prefix', $arg)
}
)
hidden $_filetype = $($this | Add-Member ScriptProperty 'filetype' `
{
return Write-Warning ("ERROR: $($this.identifier()).filetype is write only")
} `
{
param([string]$arg)
[int]$val = 0
switch ($arg) {
'wav' { $val = 1 }
'aiff' { $val = 2 }
'bwf' { $val = 3 }
'mp3' { $val = 100 }
default { "Filetype() got: $arg, expected one of 'wav', 'aiff', 'bwf', 'mp3'" }
}
$this._filetype = $this.Setter('filetype', $val)
}
)
hidden $_armedbus = $($this | Add-Member ScriptProperty 'armedbus' `
{
foreach ($bus in 0..$($this.remote.kind.p_out + $this.remote.kind.v_out - 1)) {
if ($this.remote.Getter("Recorder.ArmBus[$bus]")) {
break
}
}
return $bus
} `
{
param([int]$arg)
$busMax = $this.remote.kind.p_out + $this.remote.kind.v_out - 1
if ($arg -ge 0 -and $arg -le $busMax) {
$this._armedbus = $this.remote.Setter("Recorder.ArmBus[$arg]", 1)
}
else {
Write-Warning ("Expected a bus index between 0 and $busMax")
}
}
)
hidden $_state = $($this | Add-Member ScriptProperty 'state' `
{
if ($this.Getter('pause')) { return 'pause' }
foreach ($state in $this.states) {
if ($this.Getter($state)) {
break
}
}
return $state
} `
{
param([string]$arg)
if (-not $this.states.Contains($arg)) {
Write-Warning ("Recorder.State got: $arg, expected one of $($this.states)")
return
}
if ($arg -eq 'pause' -and -not $this.Getter('record')) {
Write-Warning ("Recorder.State can only be set to 'pause' when recording")
return
}
$this._state = $this.Setter($arg, 1)
}
)
} }
class RecorderMode : IRemote { class RecorderMode : IRemote {
@ -201,6 +135,33 @@ class RecorderMode : IRemote {
} }
} }
class RecorderArm : IRemote {
RecorderArm ([int]$index, [Object]$remote) : base ($index, $remote) {
}
Set ([bool]$val) {
$this.Setter('', $(if ($val) { 1 } else { 0 }))
}
}
class RecorderArmStrip : RecorderArm {
RecorderArmStrip ([int]$index, [Object]$remote) : base ($index, $remote) {
}
[string] identifier () {
return "Recorder.ArmStrip[$($this.index)]"
}
}
class RecorderArmBus : RecorderArm {
RecorderArmBus ([int]$index, [Object]$remote) : base ($index, $remote) {
}
[string] identifier () {
return "Recorder.ArmBus[$($this.index)]"
}
}
function Make_Recorder ([Object]$remote) { function Make_Recorder ([Object]$remote) {
return [Recorder]::new($remote) return [Recorder]::new($remote)
} }

View File

@ -157,30 +157,14 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
$vmr.recorder.B1 | Should -Be $expected $vmr.recorder.B1 | Should -Be $expected
} }
It 'Should set and get Recorder.armstrip[i]' -ForEach @( It 'Should set and get Recorder.loop' {
@{ Index = $phys_in }, @{ Index = $virt_in } $vmr.recorder.loop = $value
) {
$vmr.recorder.armstrip[$index].set($value)
$vmr.recorder.armstrip[$index].get() | Should -Be $value
} }
}
It 'Should set and get Recorder.armbus[i]' -ForEach @( Context 'Command' {
@{ Index = $phys_out }, @{ Index = $virt_out } It 'Should set command.lock' {
) { $vmr.command.lock = $value
$vmr.recorder.armbus[$index].set($value)
$vmr.recorder.armbus[$index].get() | Should -Be $value
}
Context 'Mode' {
It 'Should set and get Recorder.mode.multitrack' {
$vmr.recorder.mode.multitrack = $value
$vmr.recorder.mode.multitrack | Should -Be $expected
}
It 'Should set and get Recorder.mode.loop' {
$vmr.recorder.mode.loop = $value
$vmr.recorder.mode.loop | Should -Be $expected
}
} }
} }
@ -619,43 +603,6 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
} }
} }
} }
Context 'Recorder' -Skip:$ifBasic {
It 'Should set and get Recorder.armedbus' -ForEach @(
@{ Value = $phys_out }, @{ Value = $virt_out }
) {
$vmr.recorder.armedbus = $value
$vmr.recorder.armedbus | Should -Be $value
}
It 'Should set and get Recorder.prerectime' -ForEach @(
@{ Value = 5 }, @{ Value = 20 }
) {
$vmr.recorder.prerectime = $value
$vmr.recorder.prerectime | Should -Be $value
}
It 'Should set and get Recorder.samplerate' -ForEach @(
@{ Value = 44100 }, @{ Value = 48000 }
) {
$vmr.recorder.samplerate = $value
$vmr.recorder.samplerate | Should -Be $value
}
It 'Should set and get Recorder.bitresolution' -ForEach @(
@{ Value = 24 }, @{ Value = 16 }
) {
$vmr.recorder.bitresolution = $value
$vmr.recorder.bitresolution | Should -Be $value
}
It 'Should set and get Recorder.kbps' -ForEach @(
@{ Value = 96 }, @{ Value = 192 }
) {
$vmr.recorder.kbps = $value
$vmr.recorder.kbps | Should -Be $value
}
}
} }
Describe 'String Tests' -Tag 'string' { Describe 'String Tests' -Tag 'string' {
@ -898,211 +845,5 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
} }
} }
} }
Context 'Recorder' -Skip:$ifBasic {
It 'Should record a test file, eject, and load it back' -Skip:$ifCustomDir {
try {
$prefix = 'stringtest'
$filetype = 'wav'
$vmr.recorder.prefix = $prefix
$vmr.recorder.filetype = $filetype
$vmr.recorder.state = 'record'
Start-Sleep -Milliseconds 100
$stamp = '{0:yyyy-MM-dd} at {0:HH}h{0:mm}m{0:ss}s' -f (Get-Date)
$vmr.recorder.state | Should -Be 'record'
Start-Sleep -Milliseconds 2000
$tmp = [System.IO.Path]::Combine($recDir, ("{0} {1}.{2}" -f $prefix, $stamp, $filetype))
$vmr.recorder.state = 'stop'
$vmr.recorder.eject()
Start-Sleep -Milliseconds 500
$vmr.recorder.state = 'play'
$vmr.recorder.state | Should -Be 'stop' # because no file is loaded
$vmr.recorder.load($tmp)
Start-Sleep -Milliseconds 500
if (-not $vmr.recorder.mode.playonload) {
$vmr.recorder.state = 'play'
}
$vmr.recorder.state | Should -Be 'play'
}
finally {
$vmr.recorder.state = 'stop'
$vmr.recorder.eject()
Start-Sleep -Milliseconds 500
if (Test-Path $tmp) {
Remove-Item -Path $tmp -Force
}
else {
throw "Recording file $tmp was not found."
}
}
}
}
Context 'Command' {
It 'Should save, reset, then load config' -ForEach @(
@{ Gain = -27.1; Mode = 'composite'; Bit = 24; Port = 1044 }
) {
$tmp = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "vmrconfig-$(New-Guid).xml")
try {
# set some values
$vmr.strip[$virt_in].gain = $gain
$vmr.bus[$phys_out].mode.set($mode)
$vmr.vban.outstream[$vban_outA].bit = $bit
$vmr.vban.port = $port
# save config
$vmr.command.save($tmp)
Start-Sleep -Milliseconds 100
Test-Path $tmp | Should -BeTrue
# reset config
$vmr.command.reset()
Start-Sleep -Milliseconds 500
# verify default values
$vmr.strip[$virt_in].gain | Should -Be 0.0
$vmr.bus[$phys_out].mode.get() | Should -Be 'normal'
$vmr.vban.outstream[$vban_outA].bit | Should -Be 16
$vmr.vban.port | Should -Be 6980
# load config
$vmr.command.load($tmp)
Start-Sleep -Milliseconds 500
# verify values
$vmr.strip[$virt_in].gain | Should -Be $gain
$vmr.bus[$phys_out].mode.get() | Should -Be $mode
$vmr.vban.outstream[$vban_outA].bit | Should -Be $bit
$vmr.vban.port | Should -Be $port
}
finally {
if (Test-Path $tmp) {
Remove-Item $tmp -Force
}
}
}
}
}
Describe 'Action Tests' -Tag 'action' {
Context 'Recorder' -Skip:$ifBasic {
Context 'Recording/Playback' -Skip:$ifCustomDir {
BeforeAll {
$prefix = 'actiontest'
$filetype = 'wav'
$vmr.recorder.prefix = $prefix
$vmr.recorder.filetype = $filetype
}
BeforeEach {
$vmr.recorder.record()
Start-Sleep -Milliseconds 100
$stamp = '{0:yyyy-MM-dd} at {0:HH}h{0:mm}m{0:ss}s' -f (Get-Date)
Start-Sleep -Milliseconds 2000
$tmp = [System.IO.Path]::Combine($recDir, ("{0} {1}.{2}" -f $prefix, $stamp, $filetype))
$vmr.recorder.pause()
Start-Sleep -Milliseconds 500
}
AfterEach {
$vmr.recorder.stop()
$vmr.recorder.eject()
Start-Sleep -Milliseconds 500
if (Test-Path $tmp) {
Remove-Item -Path $tmp -Force
}
else {
throw "Recording file $tmp was not found."
}
}
It 'Should call Recorder.record()' {
$vmr.recorder.record()
$vmr.recorder.state | Should -Be 'record'
}
It 'Should call Recorder.pause()' {
$vmr.recorder.record()
Start-Sleep -Milliseconds 500
$vmr.recorder.pause()
$vmr.recorder.state | Should -Be 'pause'
}
It 'Should call Recorder.play()' {
$vmr.recorder.stop()
Start-Sleep -Milliseconds 500
$vmr.recorder.play()
$vmr.recorder.state | Should -Be 'play'
}
}
}
Context 'Command' {
Context 'Preset Scene' -ForEach @(
@{ Index = 0; Name = 'Test Scene 1' }
@{ Index = 63; Name = 'Test Scene 64' }
) {
It "Should store preset at index '$index' with name '$name'" -ForEach @(
@{ Value = -15.5 }, @{ Value = -52.9 }
) {
$vmr.bus[$phys_out].gain = $value
$vmr.command.storepreset($index, $name)
$vmr.bus[$phys_out].gain = 0.0
$vmr.command.recallpreset($name)
Start-Sleep -Milliseconds 500
$vmr.bus[$phys_out].gain | Should -Be $value
}
It "Should update preset at index '$index'" -ForEach @(
@{ Value = $false }, @{ Value = $true }
) {
$vmr.strip[$virt_in].B1 = $value
$vmr.command.storepreset($index)
$vmr.strip[$virt_in].B1 = -not $value
$vmr.command.recallpreset($index)
Start-Sleep -Milliseconds 500
$vmr.strip[$virt_in].B1 | Should -Be $value
}
It "Should update preset with name '$name'" -ForEach @(
@{ Value = 2 }, @{ Value = 1 }
) {
$vmr.bus[$virt_out].mono = $value
$vmr.command.storepreset($name)
$vmr.bus[$virt_out].mono = 0
$vmr.command.recallpreset($name)
Start-Sleep -Milliseconds 500
$vmr.bus[$virt_out].mono | Should -Be $value
}
It "Should update last recalled preset ($index`: $(($index + 1).ToString('00')) - $name)" -ForEach @(
@{ Value = 0.8 }, @{ Value = 0.3 }
) {
$vmr.strip[$phys_in].color_y = $value
$vmr.command.storepreset()
$vmr.strip[$phys_in].color_y = 0.0
$vmr.command.recallpreset()
Start-Sleep -Milliseconds 500
$vmr.strip[$phys_in].color_y | Should -Be $value
}
}
}
} }
} }

View File

@ -1,42 +1,8 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Target = "variablename")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Target = "variablename")]
Param([String]$tag, [string]$kind = 'potato', [string]$recDir = (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'Voicemeeter')) Param([String]$tag, [string]$kind = 'potato')
Import-Module (Join-Path (Split-Path $PSScriptRoot -Parent) 'lib\Voicemeeter.psm1') -Force Import-Module (Join-Path (Split-Path $PSScriptRoot -Parent) 'lib\Voicemeeter.psm1') -Force
function Test-RecDir ([object]$vmr, [string]$recDir) {
$prefix = 'temp'
$filetype = 'wav'
$vmr.recorder.prefix = $prefix
$vmr.recorder.filetype = $filetype
try {
$vmr.recorder.record()
Start-Sleep -Milliseconds 100
$stamp = '{0:yyyy-MM-dd} at {0:HH}h{0:mm}m{0:ss}s' -f (Get-Date)
Start-Sleep -Milliseconds 2000
$tmp = Join-Path $recDir ("{0} {1}.{2}" -f $prefix, $stamp, $filetype)
$vmr.recorder.stop()
$vmr.recorder.eject()
Start-Sleep -Milliseconds 500
}
catch {
Write-Warning "Failed to record pre-check clip: $_"
}
if (Test-Path $tmp) {
Remove-Item -Path $tmp -Force
return $false
}
else {
Write-Warning "Recorder output not found at given path: $tmp"
Write-Warning "Skipping Recording/Playback tests. Provide custom path with -recDir"
return $true
}
}
function main() { function main() {
try { try {
$vmr = Connect-Voicemeeter -Kind $kind $vmr = Connect-Voicemeeter -Kind $kind
@ -64,15 +30,6 @@ function main() {
$ifNotBasic = $vmr.kind.name -ne 'basic' $ifNotBasic = $vmr.kind.name -ne 'basic'
$ifNotPotato = $vmr.kind.name -ne 'potato' $ifNotPotato = $vmr.kind.name -ne 'potato'
# recording directory: default ~/My Documents/Voicemeeter, override if custom
$recDir = [System.IO.Path]::GetFullPath($recDir)
if ($ifBasic) {
$ifCustomDir = $ifBasic # basic can't record, so skip the test
}
else {
$ifCustomDir = Test-RecDir -vmr $vmr -recDir $recDir # avoid creating files we can't delete
}
Invoke-Pester -Tag $tag -PassThru | Out-Null Invoke-Pester -Tag $tag -PassThru | Out-Null
} }
finally { Disconnect-Voicemeeter } finally { Disconnect-Voicemeeter }