diff --git a/voicemeeter/base.go b/voicemeeter/base.go index 917f209..63501ca 100644 --- a/voicemeeter/base.go +++ b/voicemeeter/base.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "os" + "strings" "syscall" "time" "unsafe" @@ -28,10 +29,10 @@ var ( vmSetParameters = mod.NewProc("VBVMR_SetParameters") vmSetParamString = mod.NewProc("VBVMR_SetParameterStringA") - //vmGetDevNumOut = mod.NewProc("VBVMR_Output_GetDeviceNumber") - //vmGetDevDescOut = mod.NewProc("VBVMR_Output_GetDeviceDescA") - //vmGetDevNumIn = mod.NewProc("VBVMR_Input_GetDeviceNumber") - //vmGetDevDescIn = mod.NewProc("VBVMR_Input_GetDeviceDescA") + vmGetDevNumIn = mod.NewProc("VBVMR_Input_GetDeviceNumber") + vmGetDevDescIn = mod.NewProc("VBVMR_Input_GetDeviceDescA") + vmGetDevNumOut = mod.NewProc("VBVMR_Output_GetDeviceNumber") + vmGetDevDescOut = mod.NewProc("VBVMR_Output_GetDeviceDescA") vmMdirty = mod.NewProc("VBVMR_MacroButton_IsDirty") vmGetMacroStatus = mod.NewProc("VBVMR_MacroButton_GetStatus") @@ -245,6 +246,50 @@ func setMacroStatus(id, state, mode int) { sync() } +func get_num_devices(dir string) uint64 { + if strings.Compare(dir, "in") == 0 { + res, _, _ := vmGetDevNumIn.Call() + return uint64(res) + } else { + res, _, _ := vmGetDevNumOut.Call() + return uint64(res) + } +} + +func get_device_description(i int, dir string) (string, uint64, string) { + var t_ uint64 + var b1 [512]byte + var b2 [512]byte + if strings.Compare(dir, "in") == 0 { + res, _, _ := vmGetDevDescIn.Call( + uintptr(i), + uintptr(unsafe.Pointer(&t_)), + uintptr(unsafe.Pointer(&b1[0])), + uintptr(unsafe.Pointer(&b2[0])), + ) + if res != 0 { + err := fmt.Errorf("VBVMR_Input_GetDeviceDescA returned %d", res) + fmt.Println(err) + os.Exit(1) + } + } else { + res, _, _ := vmGetDevDescOut.Call( + uintptr(i), + uintptr(unsafe.Pointer(&t_)), + uintptr(unsafe.Pointer(&b1[0])), + uintptr(unsafe.Pointer(&b2[0])), + ) + if res != 0 { + err := fmt.Errorf("VBVMR_Output_GetDeviceDescA returned %d", res) + fmt.Println(err) + os.Exit(1) + } + } + name := bytes.Trim(b1[:], "\x00") + hwid := bytes.Trim(b2[:], "\x00") + return string(name), t_, string(hwid) +} + /* // getLevel returns a single level value of type type_ for channel[i] func getLevel(type_, i int) float32 { diff --git a/voicemeeter/device.go b/voicemeeter/device.go new file mode 100644 index 0000000..a6648d8 --- /dev/null +++ b/voicemeeter/device.go @@ -0,0 +1,44 @@ +package voicemeeter + +type devDesc struct { + Name, Type, Hwid string +} + +type device struct { +} + +func newDevice() *device { + return &device{} +} + +// Ins returns the total number of physical input devices +func (d *device) Ins() uint64 { + return get_num_devices("in") +} + +// Ins returns the total number of physical input devices +func (d *device) Outs() uint64 { + return get_num_devices("out") +} + +func (d *device) Input(i int) devDesc { + n, t_, id := get_device_description(i, "in") + vals := map[uint64]string{ + 1: "mme", + 3: "wdm", + 4: "ks", + 5: "asio", + } + return devDesc{Name: n, Type: vals[t_], Hwid: id} +} + +func (d *device) Output(i int) devDesc { + n, t_, id := get_device_description(i, "out") + vals := map[uint64]string{ + 1: "mme", + 3: "wdm", + 4: "ks", + 5: "asio", + } + return devDesc{Name: n, Type: vals[t_], Hwid: id} +} diff --git a/voicemeeter/device_test.go b/voicemeeter/device_test.go new file mode 100644 index 0000000..6fd9755 --- /dev/null +++ b/voicemeeter/device_test.go @@ -0,0 +1,15 @@ +package voicemeeter + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetDevice(t *testing.T) { + //t.Skip("skipping test") + __dev := newDevice() + t.Run("Should return a button type", func(t *testing.T) { + assert.NotNil(t, __dev) + }) +} diff --git a/voicemeeter/remote.go b/voicemeeter/remote.go index c7d454a..ea8bc05 100644 --- a/voicemeeter/remote.go +++ b/voicemeeter/remote.go @@ -14,6 +14,7 @@ type remote struct { Button []button Command *command Vban *vban + Device *device Recorder *recorder pooler *pooler @@ -67,6 +68,7 @@ type remoteBuilder interface { makeButton() remoteBuilder makeCommand() remoteBuilder makeVban() remoteBuilder + makeDevice() remoteBuilder makeRecorder() remoteBuilder Build() remoteBuilder Get() *remote @@ -145,21 +147,28 @@ func (b *genericBuilder) makeButton() remoteBuilder { return b } -// makeCommand makes a Command type and assignss it to remote.Command +// makeCommand makes a Command type and assigns it to remote.Command func (b *genericBuilder) makeCommand() remoteBuilder { fmt.Println("building command") b.r.Command = newCommand() return b } -// makeVban makes a Vban type and assignss it to remote.Vban +// makeVban makes a Vban type and assigns it to remote.Vban func (b *genericBuilder) makeVban() remoteBuilder { fmt.Println("building vban") b.r.Vban = newVban(b.k) return b } -// makeVban makes a Vban type and assignss it to remote.Vban +// makeVban makes a Vban type and assigns it to remote.Vban +func (b *genericBuilder) makeDevice() remoteBuilder { + fmt.Println("building recorder") + b.r.Device = newDevice() + return b +} + +// makeRecorder makes a recorder type and assigns it to remote.Vban func (b *genericBuilder) makeRecorder() remoteBuilder { fmt.Println("building recorder") b.r.Recorder = newRecorder() @@ -177,7 +186,7 @@ type basicBuilder struct { // Build defines the steps required to build a basic type func (basb *genericBuilder) Build() remoteBuilder { - return basb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban() + return basb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban().makeDevice() } type bananaBuilder struct { @@ -186,7 +195,7 @@ type bananaBuilder struct { // Build defines the steps required to build a banana type func (banb *bananaBuilder) Build() remoteBuilder { - return banb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban().makeRecorder() + return banb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban().makeDevice().makeRecorder() } type potatoBuilder struct { @@ -195,7 +204,7 @@ type potatoBuilder struct { // Build defines the steps required to build a potato type func (potb *potatoBuilder) Build() remoteBuilder { - return potb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban().makeRecorder() + return potb.setKind().makeStrip().makeBus().makeButton().makeCommand().makeVban().makeDevice().makeRecorder() } // GetRemote returns a remote type for a kind