vban x.1.2.0

changes staged
- on, name, ip partial write-only resolved
- simple ranges of consecutive integers moved to AddIntMembers
- audio instream/outstream divergent behavior separated
- midi outstream route, string
- new video outstream
This commit is contained in:
pblivingston 2025-12-10 19:43:36 -05:00
parent c446ad8c93
commit 0d303e20be
5 changed files with 269 additions and 185 deletions

View File

@ -465,22 +465,64 @@ The following Vban.instream | Vban.outstream properties are available:
- on: bool
- name: string
- ip: string
- sr: in, (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
- channel: int from 1 to 8
- bit: int, 16 or 24
- quality: int, from 0 to 4
- route: int, from 0 to 8
for example:
```powershell
$vmr.vban.instream[0].on = $true
$vmr.vban.outstream[3].bit = 16
$vmr.vban.outstream[9].ip = '192.168.1.154'
```
##### audio
The following audio Vban.instream | Vban.outstream properties are available:
- sr: int, (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
- channel: int, from 1 to 8
- bit: int, 16 or 24
- quality: int, from 0 to 4
- route: int, from 0 to 8
SR, channel and bit are defined as readonly for instreams. Attempting to write
to those parameters will throw an error. They are read and write for outstreams.
for example:
```powershell
$vmr.vban.instream[0].route = 4
$vmr.vban.outstream[3].bit = 16
```
##### midi
The following midi Vban.outstream[8] properties are available:
- route: string, ('none', 'midi_in', 'aux_in', 'vban_in', 'all_in', 'midi_out')
for example:
```powershell
$vmr.vban.outstream[8].route = 'aux_in'
```
##### video
The following video Vban.outstream[9] properties are available:
- vfps: int, from 1 to 30
- vformat: string, ('png', 'jpg')
- vquality: int, from 1 to 100
- vcursor: bool
- route: int, from 0 to 4
for example:
```powershell
$vmr.vban.outstream[9].vformat = 'jpg'
$vmr.vban.outstream[9].vquality = 85
$vmr.vban.outstream[9].vcursor = $true
```
### Command
Certain 'special' commands are defined by the API as performing actions rather than setting values.

View File

@ -9,7 +9,7 @@ $KindMap = @{
'asio_out' = 8
'composite' = 0
'insert' = 0
'vban' = @{ 'in' = 4; 'out' = 4; 'midi' = 1; 'text' = 1 }
'vban' = @{ 'in' = 4; 'out' = 4; 'midi' = 1; 'text' = 1; 'video' = 1 }
'eq_ch' = @{ 'strip' = 0; 'bus' = 0 }
'cells' = 0
'gainlayer' = 0
@ -24,7 +24,7 @@ $KindMap = @{
'asio_out' = 8
'composite' = 8
'insert' = 22
'vban' = @{ 'in' = 8; 'out' = 8; 'midi' = 1; 'text' = 1 }
'vban' = @{ 'in' = 8; 'out' = 8; 'midi' = 1; 'text' = 1; 'video' = 1 }
'eq_ch' = @{ 'strip' = 0; 'bus' = 8 }
'cells' = 6
'gainlayer' = 0
@ -39,7 +39,7 @@ $KindMap = @{
'asio_out' = 8
'composite' = 8
'insert' = 34
'vban' = @{ 'in' = 8; 'out' = 8; 'midi' = 1; 'text' = 1 }
'vban' = @{ 'in' = 8; 'out' = 8; 'midi' = 1; 'text' = 1; 'video' = 1 }
'eq_ch' = @{ 'strip' = 2; 'bus' = 8 }
'cells' = 6
'gainlayer' = 8

View File

@ -3,18 +3,14 @@ class Vban : IRemote {
Vban ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote) {
$this.direction = $direction
AddBoolMembers -PARAMS @('on')
AddStringMembers -PARAMS @('name', 'ip')
}
[string] identifier () {
return 'vban.' + $this.direction + 'stream[' + $this.index + ']'
}
}
class VbanAudio : Vban {
VbanAudio ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
AddBoolMembers -PARAMS @('on')
AddStringMembers -PARAMS @('name', 'ip')
}
hidden $_port = $($this | Add-Member ScriptProperty 'port' `
{
@ -30,43 +26,33 @@ class VbanAudio : Vban {
}
}
)
}
hidden $_sr = $($this | Add-Member ScriptProperty 'sr' `
{
[int]$this.Getter('sr')
} `
{
param([int]$arg)
if ($this.direction -eq 'in') { Write-Warning ('Error, read only value') }
else {
$opts = @(11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
if ($opts.Contains($arg)) {
$this._sr = $this.Setter('sr', $arg)
class VbanAudio : Vban {
VbanAudio ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
AddIntMembers -PARAMS @('quality', 'route')
}
else {
Write-Warning ('Expected one of', $opts)
}
}
}
)
}
hidden $_channel = $($this | Add-Member ScriptProperty 'channel' `
{
[int]$this.Getter('channel')
} `
{
param([int]$arg)
if ($this.direction -eq 'in') { Write-Warning ('Error, read only value') }
else {
if ($arg -ge 1 -and $arg -le 8) {
$this._channel = $this.Setter('channel', $arg)
class VbanMidi : Vban {
VbanMidi ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
}
else {
Write-Warning ('Expected value from 1 to 8')
}
class VbanText : Vban {
VbanText ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
}
}
class VbanVideo : Vban {
VbanVideo ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
}
}
class VbanInAudio : VbanAudio {
VbanInAudio ([int]$index, [Object]$remote) : base ($index, $remote, 'in') {
AddIntMembers -ReadOnly -PARAMS @('sr', 'channel')
}
)
hidden $_bit = $($this | Add-Member ScriptProperty 'bit' `
{
@ -74,125 +60,9 @@ class VbanAudio : Vban {
return $val
} `
{
param([int]$arg)
if ($this.direction -eq 'in') { Write-Warning ('Error, read only value') }
else {
if (@(16, 24).Contains($arg)) {
$val = if ($arg -eq 16) { 1 } else { 2 }
$this._bit = $this.Setter('bit', $val)
}
else {
Write-Warning ('Expected value 16 or 24')
}
}
Write-Warning ("ERROR: $($this.identifier()).bit is read only")
}
)
hidden $_quality = $($this | Add-Member ScriptProperty 'quality' `
{
[int]$this.Getter('quality')
} `
{
param([int]$arg)
if ($arg -ge 0 -and $arg -le 4) {
$this._quality = $this.Setter('quality', $arg)
}
else {
Write-Warning ('Expected value from 0 to 4')
}
}
)
hidden $_route = $($this | Add-Member ScriptProperty 'route' `
{
[int]$this.Getter('route')
} `
{
param([int]$arg)
$rt = $this.remote.kind['p_' + $this.direction] + $this.remote.kind['v_' + $this.direction] - 1
if ($arg -ge 0 -and $arg -le $rt) {
$this._route = $this.Setter('route', $arg)
}
else {
Write-Warning ("Expected value from 0 to $rt")
}
}
)
}
class VbanMidi : Vban {
VbanMidi ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
}
hidden $_on = $($this | Add-Member ScriptProperty 'on' `
{
return Write-Warning ("ERROR: $($this.identifier()).on is write only")
} `
{
param([bool]$arg)
$this._on = $this.Setter('on', $arg)
}
)
hidden $_name = $($this | Add-Member ScriptProperty 'name' `
{
return Write-Warning ("ERROR: $($this.identifier()).name is write only")
} `
{
param([string]$arg)
$this._name = $this.Setter('name', $arg)
}
)
hidden $_ip = $($this | Add-Member ScriptProperty 'ip' `
{
return Write-Warning ("ERROR: $($this.identifier()).ip is write only")
} `
{
param([string]$arg)
$this._ip = $this.Setter('ip', $arg)
}
)
}
class VbanText : Vban {
VbanText ([int]$index, [Object]$remote, [string]$direction) : base ($index, $remote, $direction) {
}
hidden $_on = $($this | Add-Member ScriptProperty 'on' `
{
return Write-Warning ("ERROR: $($this.identifier()).on is write only")
} `
{
param([bool]$arg)
$this._on = $this.Setter('on', $arg)
}
)
hidden $_name = $($this | Add-Member ScriptProperty 'name' `
{
return Write-Warning ("ERROR: $($this.identifier()).name is write only")
} `
{
param([string]$arg)
$this._name = $this.Setter('name', $arg)
}
)
hidden $_ip = $($this | Add-Member ScriptProperty 'ip' `
{
return Write-Warning ("ERROR: $($this.identifier()).ip is write only")
} `
{
param([string]$arg)
$this._ip = $this.Setter('ip', $arg)
}
)
}
class VbanInAudio : VbanAudio {
VbanInAudio ([int]$index, [Object]$remote) : base ($index, $remote, 'in') {
}
}
class VbanInMidi : VbanMidi {
@ -207,12 +77,103 @@ class VbanInText : VbanText {
class VbanOutAudio : VbanAudio {
VbanOutAudio ([int]$index, [Object]$remote) : base ($index, $remote, 'out') {
AddIntMembers -PARAMS @('channel')
}
hidden $_sr = $($this | Add-Member ScriptProperty 'sr' `
{
[int]$this.Getter('sr')
} `
{
param([int]$arg)
$opts = @(11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
if ($opts.Contains($arg)) {
$this._sr = $this.Setter('sr', $arg)
}
else {
Write-Warning ('Expected one of', $opts)
}
}
)
hidden $_bit = $($this | Add-Member ScriptProperty 'bit' `
{
$val = if ($this.Getter('bit') -eq 1) { 16 } else { 24 }
return $val
} `
{
param([int]$arg)
if (@(16, 24).Contains($arg)) {
$val = if ($arg -eq 16) { 1 } else { 2 }
$this._bit = $this.Setter('bit', $val)
}
else {
Write-Warning ('Expected value 16 or 24')
}
}
)
}
class VbanOutMidi : VbanMidi {
VbanOutMidi ([int]$index, [Object]$remote) : base ($index, $remote, 'out') {
}
hidden $_route = $($this | Add-Member ScriptProperty 'route' `
{
[string]$val = ''
switch ($this.Getter('route')) {
0 { $val = 'none' }
1 { $val = 'midi_in' }
2 { $val = 'aux_in' }
4 { $val = 'vban_in' }
7 { $val = 'all_in' }
8 { $val = 'midi_out' }
}
return $val
} `
{
param([string]$arg)
[int]$val = 0
switch ($arg) {
'none' { $val = 0 }
'midi_in' { $val = 1 }
'aux_in' { $val = 2 }
'vban_in' { $val = 4 }
'all_in' { $val = 7 }
'midi_out' { $val = 8 }
default { Write-Warning ("route got: $arg, expected one of 'none', 'midi_in', 'aux_in', 'vban_in', 'all_in', 'midi_out'") }
}
$this._route = $this.Setter('route', $val)
}
)
}
class VbanOutVideo : VbanVideo {
VbanOutVideo ([int]$index, [Object]$remote) : base ($index, $remote, 'out') {
AddIntMembers -PARAMS @('vfps', 'vquality', 'route')
AddBoolMembers -PARAMS @('vcursor')
}
hidden $_vformat = $($this | Add-Member ScriptProperty 'vformat' `
{
[string]$val = ''
switch ($this.Getter('vformat')) {
1 { $val = 'png' }
2 { $val = 'jpg' }
}
return $val
} `
{
param([string]$arg)
[int]$val = 0
switch ($arg) {
'png' { $val = 1 }
'jpg' { $val = 2 }
default { Write-Warning ("vformat got: $arg, expected one of 'png', 'jpg'") }
}
$this._vformat = $this.Setter('vformat', $val)
}
)
}
function Make_Vban ([Object]$remote) {
@ -220,7 +181,7 @@ function Make_Vban ([Object]$remote) {
[System.Collections.ArrayList]$outstream = @()
$totalInstreams = $remote.kind.vban.in + $remote.kind.vban.midi + $remote.kind.vban.text
$totalOutstreams = $remote.kind.vban.out + $remote.kind.vban.midi
$totalOutstreams = $remote.kind.vban.out + $remote.kind.vban.midi + $remote.kind.vban.video
for ($i = 0; $i -lt $totalInstreams; $i++) {
if ($i -lt $remote.kind.vban.in) {
@ -237,9 +198,12 @@ function Make_Vban ([Object]$remote) {
if ($i -lt $remote.kind.vban.out) {
[void]$outstream.Add([VbanOutAudio]::new($i, $remote))
}
else {
elseif ($i -lt ($remote.kind.vban.out + $remote.kind.vban.midi)) {
[void]$outstream.Add([VbanOutMidi]::new($i, $remote))
}
else {
[void]$outstream.Add([VbanOutVideo]::new($i, $remote))
}
}
$CustomObject = [pscustomobject]@{

View File

@ -150,10 +150,10 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
$vmr.vban.enable | Should -Be $expected
}
Context 'Instream' -ForEach @(
Context 'Instream, audio, midi, text' -ForEach @(
@{ Index = $vban_inA }
# @{ Index = $vban_inM }
# @{ Index = $vban_inT }
@{ Index = $vban_inM }
@{ Index = $vban_inT }
) {
It "Should set vban.instream[$index].on" {
$vmr.vban.instream[$index].on = $value
@ -161,15 +161,25 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
}
}
Context 'Outstream' -ForEach @(
Context 'Outstream, audio, midi, video' -ForEach @(
@{ Index = $vban_outA }
# @{ Index = $vban_outM }
@{ Index = $vban_outM }
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].on" {
$vmr.vban.outstream[$index].on = $value
$vmr.vban.outstream[$index].on | Should -Be $expected
}
}
Context 'Outstream, video only' -ForEach @(
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].vcursor" {
$vmr.vban.outstream[$index].vcursor = $value
$vmr.vban.outstream[$index].vcursor | Should -Be $expected
}
}
}
Context 'Recorder' -Skip:$ifBasic {
@ -596,8 +606,10 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
$vmr.vban.port | Should -Be $expected
}
Context 'Instream' -ForEach @(
Context 'Instream, audio, midi, text' -ForEach @(
@{ Index = $vban_inA }
@{ Index = $vban_inM }
@{ Index = $vban_inT }
) {
It "Should set vban.instream[$index].port" -ForEach @(
@{ Value = 1024; Expected = 1024 }
@ -608,16 +620,21 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
Start-Sleep -Milliseconds 2000
$vmr.vban.instream[$index].port | Should -Be $expected
}
}
It "Should set vban.instream[$index].sr" {
Context 'Instream, audio only' -ForEach @(
@{ Index = $vban_inA }
) {
It "Should get vban.instream[$index].sr" {
$vmr.vban.instream[$index].sr | Should -BeOfType [int]
}
It "Should set vban.instream[$index].channel" {
It "Should get vban.instream[$index].channel" {
$vmr.vban.instream[$index].channel | Should -BeOfType [int]
}
It "Should set vban.instream[$index].bit" {
It "Should get vban.instream[$index].bit" {
$vmr.vban.instream[$index].bit | Should -BeOfType [int]
}
@ -639,8 +656,10 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
}
}
Context 'Outstream' -ForEach @(
Context 'Outstream, audio, midi, video' -ForEach @(
@{ Index = $vban_outA }
@{ Index = $vban_outM }
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].port" -ForEach @(
@{ Value = 1024; Expected = 1024 }
@ -651,6 +670,11 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
Start-Sleep -Milliseconds 2000
$vmr.vban.outstream[$index].port | Should -Be $expected
}
}
Context 'Outstream, audio only' -ForEach @(
@{ Index = $vban_outA }
) {
It "Should set vban.outstream[$index].sr" -ForEach @(
@{ Value = 44100; Expected = 44100 }
@ -693,6 +717,46 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
$vmr.vban.outstream[$index].route | Should -Be $expected
}
}
Context 'Outstream, midi only' -ForEach @(
@{ Index = $vban_outM }
) {
It "Should set vban.outstream[$index].route" -ForEach @(
@{ Value = 7; Expected = 7 }
@{ Value = 3; Expected = 3 }
) {
$vmr.vban.outstream[$index].route = $value
$vmr.vban.outstream[$index].route | Should -Be $expected
}
}
Context 'Outstream, video only' -ForEach @(
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].vfps" -ForEach @(
@{ Value = 6; Expected = 6 }
@{ Value = 24; Expected = 24 }
) {
$vmr.vban.outstream[$index].vfps = $value
$vmr.vban.outstream[$index].vfps | Should -Be $expected
}
It "Should set vban.outstream[$index].vquality" -ForEach @(
@{ Value = 80; Expected = 80 }
@{ Value = 100; Expected = 100 }
) {
$vmr.vban.outstream[$index].vquality = $value
$vmr.vban.outstream[$index].vquality | Should -Be $expected
}
It "Should set vban.outstream[$index].route" -ForEach @(
@{ Value = 1; Expected = 1 }
@{ Value = 4; Expected = 4 }
) {
$vmr.vban.outstream[$index].route = $value
$vmr.vban.outstream[$index].route | Should -Be $expected
}
}
}
Context 'Patch' {
@ -980,10 +1044,10 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
}
Describe 'Vban' {
Context 'Instream' -ForEach @(
Context 'Instream, audio, midi, text' -ForEach @(
@{ Index = $vban_inA }
# @{ Index = $vban_inM }
# @{ Index = $vban_inT }
@{ Index = $vban_inM }
@{ Index = $vban_inT }
) {
It "Should set vban.instream[$index].name" -ForEach @(
@{ Value = 'TestIn0'; Expected = 'TestIn0' }
@ -1001,9 +1065,10 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
}
}
Context 'Outstream' -ForEach @(
Context 'Outstream, audio, midi, video' -ForEach @(
@{ Index = $vban_outA }
# @{ Index = $vban_outM }
@{ Index = $vban_outM }
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].name" -ForEach @(
@{ Value = 'TestOut0'; Expected = 'TestOut0' }
@ -1020,6 +1085,18 @@ Describe -Tag 'higher', -TestName 'All Higher Tests' {
$vmr.vban.outstream[$index].ip | Should -Be $expected
}
}
Context 'Outstream, video only' -ForEach @(
@{ Index = $vban_outV }
) {
It "Should set vban.outstream[$index].vformat" -ForEach @(
@{ Value = 'png'; Expected = 'png' }
@{ Value = 'jpg'; Expected = 'jpg' }
) {
$vmr.vban.outstream[$index].vformat = $value
$vmr.vban.outstream[$index].vformat | Should -Be $expected
}
}
}
Context 'Recorder' -Skip:$ifBasic {

View File

@ -53,6 +53,7 @@ function main() {
$vban_inT = $vmr.kind.vban.in + $vmr.kind.vban.midi + $vmr.kind.vban.text - 1
$vban_outA = $vmr.kind.vban.out - 1
$vban_outM = $vmr.kind.vban.out + $vmr.kind.vban.midi - 1
$vban_outV = $vmr.kind.vban.out + $vmr.kind.vban.midi + $vmr.kind.vban.video - 1
$insert = $vmr.kind.insert - 1
$composite = $vmr.kind.composite - 1
$strip_ch = $vmr.kind.eq_ch['strip'] - 1