io.ps1
|
class IOControl : IRemote { IOControl ([int]$index, [Object]$remote) : base ($index, $remote) { AddBoolMembers -PARAMS @('mute') AddFloatMembers -PARAMS @('gain') AddStringMembers -PARAMS @('label') } [void] FadeTo ([single]$target, [int]$time) { $this.Setter('FadeTo', "($target, $time)") } [void] FadeBy ([single]$target, [int]$time) { $this.Setter('FadeBy', "($target, $time)") } } class IOLevels : IRemote { IOLevels ([int]$index, [Object]$remote) : base ($index, $remote) { } hidden [single] Convert([single]$val) { if ($val -gt 0) { return [math]::Round(20 * [math]::Log10($val), 1) } else { return -200.0 } } [System.Collections.ArrayList] Getter([int]$mode) { [System.Collections.ArrayList]$vals = @() $this.init..$($this.init + $this.offset - 1) | ForEach-Object { $vals.Add($this.Convert($(Get_Level -MODE $mode -INDEX $_))) } return $vals } } class IOEq : IRemote { [System.Collections.ArrayList]$channel [string]$kindOfEq IOEq ([int]$index, [Object]$remote, [string]$kindOfEq) : base ($index, $remote) { $this.kindOfEq = $kindOfEq AddBoolMembers -PARAMS @('on', 'ab') $this.channel = @() for ($ch = 0; $ch -lt $remote.kind.eq_ch[$this.kindOfEq]; $ch++) { $this.channel.Add([EqChannel]::new($ch, $this)) } } [void] Load ([string]$filename) { $param = 'Command.Load{0}Eq[{1}]' -f $this.kindOfEq, $this.index $this.remote.Setter($param, $filename) } [void] Save ([string]$filename) { $param = 'Command.Save{0}Eq[{1}]' -f $this.kindOfEq, $this.index $this.remote.Setter($param, $filename) } } class EqChannel : IRemote { [System.Collections.ArrayList]$cell [Object]$eq EqChannel ([int]$index, [Object]$eq) : base ($index, $eq.remote) { $this.eq = $eq if ($eq.kindOfEq -eq 'Bus') { AddFloatMembers -PARAMS @('trim', 'delay') } $this.cell = @() $cellCount = $this.remote.kind.cells for ($c = 0; $c -lt $cellCount; $c++) { $this.cell.Add([EqCell]::new($c, $this)) } } [string] identifier () { return '{0}.Channel[{1}]' -f $this.eq.identifier(), $this.index } } class EqCell : IRemote { [Object]$channel EqCell ([int]$index, [Object]$channel) : base ($index, $channel.remote) { $this.channel = $channel AddBoolMembers -PARAMS @('on') AddIntMembers -PARAMS @('type') AddFloatMembers -PARAMS @('f', 'gain', 'q') } [string] identifier () { return '{0}.Cell[{1}]' -f $this.channel.identifier(), $this.index } } class IODevice : IRemote { [string]$kindOfDevice [Hashtable]$drivers IODevice ([int]$index, [Object]$remote, [string]$kindOfDevice) : base ($index, $remote) { $this.kindOfDevice = $kindOfDevice AddStringMembers -WriteOnly -PARAMS @('wdm', 'ks', 'mme') AddStringMembers -ReadOnly -PARAMS @('name') AddIntMembers -ReadOnly -PARAMS @('sr') $this.drivers = @{ '1' = 'mme' '4' = 'wdm' '8' = 'ks' '256' = 'asio' } } [int] EnumCount () { throw [System.NotImplementedException]::new("$($this.GetType().Name) must override EnumCount()") } [PSObject] EnumDevice ([int]$eIndex) { throw [System.NotImplementedException]::new("$($this.GetType().Name) must override EnumDevice()") } [PSObject] Get () { $device = [PSCustomObject]@{ Driver = $this.driver Name = $this.name HardwareId = '' IsOutput = $this.kindOfDevice -eq 'Output' } if (-not [string]::IsNullOrEmpty($device.Name)) { for ($i = 0; $i -lt $this.EnumCount(); $i++) { $eDevice = $this.EnumDevice($i) if ($eDevice.Name -eq $device.Name -and $eDevice.Driver -eq $device.Driver) { $device = $eDevice break } } } return $device } [void] Set ([PSObject]$device) { $required = 'IsOutput', 'Driver', 'Name' $missing = $required | Where-Object { $null -eq $device.PSObject.Properties[$_] } if ($missing) { throw [System.ArgumentException]::new(("Invalid device object. Missing member(s): {0}" -f ($missing -join ', ')), 'device') } $expectsOutput = ($this.kindOfDevice -eq 'Output') if ([bool]$device.IsOutput -ne $expectsOutput) { throw [System.ArgumentException]::new(("Device direction mismatch. Expected IsOutput={0}." -f $expectsOutput), 'device') } $d = $device.Driver $n = $device.Name if (-not ($d -is [string])) { throw [System.ArgumentException]::new('Invalid device object. Driver must be a string.', 'device') } if (-not ($n -is [string])) { throw [System.ArgumentException]::new('Invalid device object. Name must be a string.', 'device') } if ($d -eq '' -and $n -eq '') { $this.Clear(); return } if ($d -notin $this.drivers.Values) { throw [System.ArgumentOutOfRangeException]::new('device.Driver', $d, 'Invalid device driver provided to Set method.') } $this.Setter($d, $n) } [void] Clear () { $this.Setter('mme', '') } hidden $_driver = $($this | Add-Member ScriptProperty 'driver' ` { if ([string]::IsNullOrEmpty($this.name)) { return '' } $type = $null try { $tmp = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "vmrtmp-$(New-Guid).xml") $this.remote.Setter('Command.Save', $tmp) $timeout = New-TimeSpan -Seconds 2 $sw = [Diagnostics.Stopwatch]::StartNew() $line = $null do { if (Test-Path $tmp) { try { $line = Get-Content $tmp | Select-String -Pattern "<$($this.kindOfDevice)Dev index='$($this.index + 1)'" -List if ($line) { break } } catch {} } Start-Sleep -Milliseconds 20 } while ($sw.elapsed -lt $timeout) if ($line -and $line.ToString() -match "type='(?<type>\d+)'") { $type = $matches['type'] } } finally { if (Test-Path $tmp) { Remove-Item $tmp -Force } } if ($type -notin $this.drivers.Keys) { return 'unknown' } return $this.drivers[$type] } ` { Write-Warning ("ERROR: $($this.identifier()).driver is read only") } ) } |