bus.ps1

class Bus : IOControl {
    [Object]$mode
    [Object]$eq
    [Object]$levels

    Bus ([int]$index, [Object]$remote) : base ($index, $remote) {
        AddBoolMembers -PARAMS @('sel', 'monitor')
        AddIntMembers -PARAMS @('mono')
        AddFloatMembers -PARAMS @('returnreverb', 'returndelay', 'returnfx1', 'returnfx2')

        $this.mode = [BusMode]::new($index, $remote)
        $this.eq = [BusEq]::new($index, $remote)
        $this.levels = [BusLevels]::new($index, $remote)
    }

    [string] identifier () {
        return 'Bus[' + $this.index + ']'
    }
}

class BusLevels : IOLevels {
    [int]$init
    [int]$offset

    BusLevels ([int]$index, [Object]$remote) : base ($index, $remote) {
        $this.init = $index * 8
        $this.offset = 8            
    }

    [System.Collections.ArrayList] All() {
        return $this.Getter(3)
    }
}

class BusMode : IRemote {
    [System.Collections.ArrayList]$modes

    BusMode ([int]$index, [Object]$remote) : base ($index, $remote) {
        $this.modes = @(
            'normal', 'amix', 'bmix', 'repeat', 'composite', 'tvmix', 'upmix21', 'upmix41', 'upmix61', 
            'centeronly', 'lfeonly', 'rearonly'
        )

        AddBoolMembers -PARAMS $this.modes
    }

    [string] identifier () {
        return 'Bus[' + $this.index + '].mode'
    }

    [string] Get () {
        foreach ($mode in $this.modes) {
            if ($this.$mode) {
                break
            }
        }
        return $mode
    }

    [void] Set ([string]$mode) {
        if ($this.modes.Contains($mode)) {
            $this.Setter($mode, $true)
        }
        else {
            throw [System.ArgumentException]::new("Invalid mode: $mode")
        }
    }
}

class BusEq : IOEq {
    BusEq ([int]$index, [Object]$remote) : base ($index, $remote, 'Bus') {
    }

    [string] identifier () {
        return 'Bus[' + $this.index + '].EQ'
    }
}

class PhysicalBus : Bus {
    [Object]$device

    PhysicalBus ([int]$index, [Object]$remote) : base ($index, $remote) {
        $this.device = [BusDevice]::new($index, $remote)

        AddBoolMembers -PARAMS @('vaio')
    }
}

class VirtualBus : Bus {
    [Object]$device
    
    VirtualBus ([int]$index, [Object]$remote) : base ($index, $remote) {
        if ($this.remote.kind.name -eq 'basic') {
            $this.device = [BusDevice]::new($index, $remote)
        }
    }
}

class BusDevice : IODevice {
    BusDevice ([int]$index, [Object]$remote) : base ($index, $remote) {
        if ($this.index -eq 0) {
            AddStringMembers -PARAMS @('asio') -WriteOnly
        }
    }

    [string] identifier () {
        return 'Bus[' + $this.index + '].Device'
    }
}

function Make_Buses ([Object]$remote) {
    [System.Collections.ArrayList]$bus = @()
    0..$($remote.kind.p_out + $remote.kind.v_out - 1) | ForEach-Object {
        if ($_ -lt $remote.kind.p_out) { [void]$bus.Add([PhysicalBus]::new($_, $remote)) }
        else { [void]$bus.Add([VirtualBus]::new($_, $remote)) }
    }
    $bus
}