mirror of
https://github.com/onyx-and-iris/voicemeeter.git
synced 2024-11-22 04:40:53 +00:00
initial commit
interface code + a few tests
This commit is contained in:
parent
2dacfab629
commit
9d16f4c534
16
README.md
16
README.md
@ -1,2 +1,14 @@
|
|||||||
# voicemeeter-api-go
|
# A Go Wrapper for Voicemeeter API
|
||||||
A Go wrapper for the Voiceemeter API
|
|
||||||
|
A WIP...
|
||||||
|
|
||||||
|
## Tested against
|
||||||
|
|
||||||
|
- Basic 1.0.8.2
|
||||||
|
- Banana 2.0.6.2
|
||||||
|
- Potato 3.0.2.2
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [Voicemeeter](https://voicemeeter.com/)
|
||||||
|
- Go 1.18 or greater
|
||||||
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module github.com/onyx-and-iris/voicemeeter-api-go
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664 h1:wEZYwx+kK+KlZ0hpvP2Ls1Xr4+RWnlzGFwPP0aiDjIU=
|
||||||
|
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
51
tests/higher_test.go
Normal file
51
tests/higher_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package voicemeeter_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/onyx-and-iris/voicemeeter-api-go/voicemeeter"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
vmRem = voicemeeter.NewRemote("banana")
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
vmRem.Login()
|
||||||
|
code := m.Run()
|
||||||
|
vmRem.Logout()
|
||||||
|
os.Exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrip0Mute(t *testing.T) {
|
||||||
|
//t.Skip("skipping test")
|
||||||
|
vmRem.Strip[0].SetMute(true)
|
||||||
|
if vmRem.Strip[0].GetMute() != true {
|
||||||
|
t.Error("TestStrip0Mute did not match true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrip2Limit(t *testing.T) {
|
||||||
|
//t.Skip("skipping test")
|
||||||
|
vmRem.Strip[2].SetLimit(-8)
|
||||||
|
if vmRem.Strip[2].GetLimit() != -8 {
|
||||||
|
t.Error("TestStrip3Limit did not match -8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrip4Label(t *testing.T) {
|
||||||
|
//t.Skip("skipping test")
|
||||||
|
vmRem.Strip[4].SetLabel("test0")
|
||||||
|
if vmRem.Strip[4].GetLabel() != "test0" {
|
||||||
|
t.Error("TestStrip4Label did not match test0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrip5Gain(t *testing.T) {
|
||||||
|
//t.Skip("skipping test")
|
||||||
|
vmRem.Strip[4].SetGain(-20.8)
|
||||||
|
if vmRem.Strip[4].GetGain() != -20.8 {
|
||||||
|
t.Error("TestStrip5Gain did not match -20.8")
|
||||||
|
}
|
||||||
|
}
|
264
voicemeeter/base.go
Normal file
264
voicemeeter/base.go
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mod = syscall.NewLazyDLL(getDllPath())
|
||||||
|
|
||||||
|
vmLogin = mod.NewProc("VBVMR_Login")
|
||||||
|
vmLogout = mod.NewProc("VBVMR_Logout")
|
||||||
|
vmRunvm = mod.NewProc("VBVMR_RunVoicemeeter")
|
||||||
|
vmGetvmType = mod.NewProc("VBVMR_GetVoicemeeterType")
|
||||||
|
vmGetvmVersion = mod.NewProc("VBVMR_GetVoicemeeterVersion")
|
||||||
|
vmPdirty = mod.NewProc("VBVMR_IsParametersDirty")
|
||||||
|
getParamFloat = mod.NewProc("VBVMR_GetParameterFloat")
|
||||||
|
getParamString = mod.NewProc("VBVMR_GetParameterStringA")
|
||||||
|
|
||||||
|
//getLevelFloat = mod.NewProc("VBVMR_GetLevel")
|
||||||
|
|
||||||
|
setParamFloat = mod.NewProc("VBVMR_SetParameterFloat")
|
||||||
|
setParameters = mod.NewProc("VBVMR_SetParameters")
|
||||||
|
setParamString = mod.NewProc("VBVMR_SetParameterStringA")
|
||||||
|
|
||||||
|
//getDevNumOut = mod.NewProc("VBVMR_Output_GetDeviceNumber")
|
||||||
|
//getDevDescOut = mod.NewProc("VBVMR_Output_GetDeviceDescA")
|
||||||
|
//getDevNumIn = mod.NewProc("VBVMR_Input_GetDeviceNumber")
|
||||||
|
//getDevDescIn = mod.NewProc("VBVMR_Input_GetDeviceDescA")
|
||||||
|
|
||||||
|
vmMdirty = mod.NewProc("VBVMR_MacroButton_IsDirty")
|
||||||
|
getMacroButtonStatus = mod.NewProc("VBVMR_MacroButton_GetStatus")
|
||||||
|
setMacroButtonStatus = mod.NewProc("VBVMR_MacroButton_SetStatus")
|
||||||
|
)
|
||||||
|
|
||||||
|
// login logs into the API,
|
||||||
|
// then attempts to launch Voicemeeter if it's not running.
|
||||||
|
func login(kind_id string) {
|
||||||
|
res, _, _ := vmLogin.Call()
|
||||||
|
if res == 1 {
|
||||||
|
runVoicemeeter(kind_id)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
} else if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_Login returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Println("Logged into API")
|
||||||
|
sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
// logout logs out of the API,
|
||||||
|
// delayed for 100ms to allow final operation to complete.
|
||||||
|
func logout() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
res, _, _ := vmLogout.Call()
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_Logout returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Println("Logged out of API")
|
||||||
|
}
|
||||||
|
|
||||||
|
// runVoicemeeter attempts to launch a Voicemeeter GUI of a kind.
|
||||||
|
func runVoicemeeter(kind_id string) {
|
||||||
|
vals := map[string]uint64{
|
||||||
|
"basic": 1,
|
||||||
|
"banana": 2,
|
||||||
|
"potato": 3,
|
||||||
|
}
|
||||||
|
res, _, _ := vmRunvm.Call(uintptr(vals[kind_id]))
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_RunVoicemeeter returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getVersion returns the version of Voicemeeter as a string
|
||||||
|
func getVersion() string {
|
||||||
|
var ver uint64
|
||||||
|
res, _, _ := vmGetvmVersion.Call(uintptr(unsafe.Pointer(&ver)))
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_GetVoicemeeterVersion returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
v1 := (ver & 0xFF000000) >> 24
|
||||||
|
v2 := (ver & 0x00FF0000) >> 16
|
||||||
|
v3 := (ver & 0x0000FF00) >> 8
|
||||||
|
v4 := ver & 0x000000FF
|
||||||
|
return fmt.Sprintf("%d.%d.%d.%d", v1, v2, v3, v4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pdirty returns true iff a parameter value has changed
|
||||||
|
func pdirty() bool {
|
||||||
|
res, _, _ := vmPdirty.Call()
|
||||||
|
return int(res) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// mdirty returns true iff a macrobutton value has changed
|
||||||
|
func mdirty() bool {
|
||||||
|
res, _, _ := vmMdirty.Call()
|
||||||
|
return int(res) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func sync() {
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
for pdirty() || mdirty() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getVMType returns the type of Voicemeeter, as a string
|
||||||
|
func getVMType() string {
|
||||||
|
var type_ uint64
|
||||||
|
res, _, _ := vmGetvmType.Call(
|
||||||
|
uintptr(unsafe.Pointer(&type_)),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_GetVoicemeeterType returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
vals := map[uint64]string{
|
||||||
|
1: "basic",
|
||||||
|
2: "banana",
|
||||||
|
3: "potato",
|
||||||
|
}
|
||||||
|
return vals[type_]
|
||||||
|
}
|
||||||
|
|
||||||
|
// getParameterFloat gets the value of a float parameter
|
||||||
|
func getParameterFloat(name string) float64 {
|
||||||
|
var value float32
|
||||||
|
b := append([]byte(name), 0)
|
||||||
|
res, _, _ := getParamFloat.Call(
|
||||||
|
uintptr(unsafe.Pointer(&b[0])),
|
||||||
|
uintptr(unsafe.Pointer(&value)),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_GetParameterFloat returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return math.Round(float64(value)*10) / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// getParameterFloat sets the value of a float parameter
|
||||||
|
func setParameterFloat(name string, value float32) {
|
||||||
|
b1 := append([]byte(name), 0)
|
||||||
|
b2 := math.Float32bits(value)
|
||||||
|
res, _, _ := setParamFloat.Call(
|
||||||
|
uintptr(unsafe.Pointer(&b1[0])),
|
||||||
|
uintptr(b2),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_SetParameterFloat returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getParameterString gets the value of a string parameter
|
||||||
|
func getParameterString(name string) string {
|
||||||
|
b1 := append([]byte(name), 0)
|
||||||
|
var b2 [512]byte
|
||||||
|
res, _, _ := getParamString.Call(
|
||||||
|
uintptr(unsafe.Pointer(&b1[0])),
|
||||||
|
uintptr(unsafe.Pointer(&b2[0])),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_GetParameterStringA returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
str := bytes.Trim(b2[:], "\x00")
|
||||||
|
return string(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getParameterString sets the value of a string parameter
|
||||||
|
func setParameterString(name, value string) {
|
||||||
|
b1 := append([]byte(name), 0)
|
||||||
|
b2 := append([]byte(value), 0)
|
||||||
|
res, _, _ := setParamString.Call(
|
||||||
|
uintptr(unsafe.Pointer(&b1[0])),
|
||||||
|
uintptr(unsafe.Pointer(&b2[0])),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_SetParameterStringA returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
// setParametersMulti sets multiple parameters with a script
|
||||||
|
func setParametersMulti(script string) {
|
||||||
|
b1 := append([]byte(script), 0)
|
||||||
|
res, _, _ := setParameters.Call(
|
||||||
|
uintptr(unsafe.Pointer(&b1[0])),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_SetParameters returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMacroStatus gets a macrobutton value
|
||||||
|
func getMacroStatus(id, mode int) float32 {
|
||||||
|
var state float32
|
||||||
|
res, _, _ := getMacroButtonStatus.Call(
|
||||||
|
uintptr(id),
|
||||||
|
uintptr(unsafe.Pointer(&state)),
|
||||||
|
uintptr(mode),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_MacroButton_GetStatus returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
// setMacroStatus sets a macrobutton value
|
||||||
|
func setMacroStatus(id, state, mode int) {
|
||||||
|
res, _, _ := setMacroButtonStatus.Call(
|
||||||
|
uintptr(id),
|
||||||
|
uintptr(state),
|
||||||
|
uintptr(mode),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_MacroButton_SetStatus returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
time.Sleep(30 * time.Millisecond)
|
||||||
|
sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// getLevel returns a single level value of type type_ for channel[i]
|
||||||
|
func getLevel(type_, i int) float32 {
|
||||||
|
var val float32
|
||||||
|
res, _, _ := getLevelFloat.Call(
|
||||||
|
uintptr(type_),
|
||||||
|
uintptr(i),
|
||||||
|
uintptr(unsafe.Pointer(&val)),
|
||||||
|
)
|
||||||
|
if res != 0 {
|
||||||
|
err := fmt.Errorf("VBVMR_GetLevel returned %d", res)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
*/
|
44
voicemeeter/bus.go
Normal file
44
voicemeeter/bus.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// custom bus type, struct forwarding channel
|
||||||
|
type bus struct {
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBus returns a strip type
|
||||||
|
// it also initializes embedded channel type
|
||||||
|
func newBus(i int, k *kind) bus {
|
||||||
|
return bus{channel{"bus", i, *k}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the stringer interface
|
||||||
|
func (b *bus) String() string {
|
||||||
|
if b.index < b.kind.physOut {
|
||||||
|
return fmt.Sprintf("PhysicalBus%d\n", b.index)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("VirtualBus%d\n", b.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMute returns the value of the Mute parameter
|
||||||
|
func (b *bus) GetMute() bool {
|
||||||
|
return b.getter_bool("Mute")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMute sets the value of the Mute parameter
|
||||||
|
func (b *bus) SetMute(val bool) {
|
||||||
|
b.setter_bool("Mute", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEq returns the value of the Eq.On parameter
|
||||||
|
func (b *bus) GetEq() bool {
|
||||||
|
return b.getter_bool("Eq.On")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEq sets the value of the Eq.On parameter
|
||||||
|
func (b *bus) SetEq(val bool) {
|
||||||
|
b.setter_bool("Eq.On", val)
|
||||||
|
}
|
64
voicemeeter/button.go
Normal file
64
voicemeeter/button.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// custom strip type, struct forwarding channel
|
||||||
|
type button struct {
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter returns the value of a macrobutton parameter
|
||||||
|
func (m *button) getter(mode int) bool {
|
||||||
|
return getMacroStatus(m.index, mode) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// setter sets the value of a macrobutton parameter
|
||||||
|
func (m *button) setter(v bool, mode int) {
|
||||||
|
var value int
|
||||||
|
if v {
|
||||||
|
value = 1
|
||||||
|
} else {
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
setMacroStatus(m.index, value, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newButton returns a button type
|
||||||
|
func newButton(i int) button {
|
||||||
|
return button{i}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the stringer interface
|
||||||
|
func (m *button) String() string {
|
||||||
|
return fmt.Sprintf("MacroButton%d\n", m.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState returns the value of the State parameter
|
||||||
|
func (m *button) GetState() bool {
|
||||||
|
return m.getter(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetState sets the value of the State parameter
|
||||||
|
func (m *button) SetState(val bool) {
|
||||||
|
m.setter(val, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStateOnly returns the value of the StateOnly parameter
|
||||||
|
func (m *button) GetStateOnly() bool {
|
||||||
|
return m.getter(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStateOnly sets the value of the StateOnly parameter
|
||||||
|
func (m *button) SetStateOnly(val bool) {
|
||||||
|
m.setter(val, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrigger returns the value of the Trigger parameter
|
||||||
|
func (m *button) GetTrigger() bool {
|
||||||
|
return m.getter(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTrigger returns the value of the Trigger parameter
|
||||||
|
func (m *button) SetTrigger(val bool) {
|
||||||
|
m.setter(val, 2)
|
||||||
|
}
|
56
voicemeeter/cdll.go
Normal file
56
voicemeeter/cdll.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dllPath returns the Voicemeeter installation path as a string
|
||||||
|
func dllPath() (string, error) {
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
return "", errors.New("only Windows OS supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
var regkey string
|
||||||
|
if strings.Contains(runtime.GOARCH, "64") {
|
||||||
|
regkey = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall`
|
||||||
|
} else {
|
||||||
|
regkey = `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
|
||||||
|
}
|
||||||
|
var vmkey = `\VB:Voicemeeter {17359A74-1236-5467}`
|
||||||
|
|
||||||
|
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey+vmkey, registry.QUERY_VALUE)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("unable to access registry")
|
||||||
|
}
|
||||||
|
defer k.Close()
|
||||||
|
|
||||||
|
path, _, err := k.GetStringValue(`UninstallString`)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("unable to read Voicemeeter path from registry")
|
||||||
|
}
|
||||||
|
|
||||||
|
var dllName string
|
||||||
|
if strings.Contains(runtime.GOARCH, "64") {
|
||||||
|
dllName = `VoicemeeterRemote64.dll`
|
||||||
|
} else {
|
||||||
|
dllName = `VoicemeeterRemote.dll`
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v\\%s", filepath.Dir(path), dllName), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDllPath is a helper function for error handling
|
||||||
|
func getDllPath() string {
|
||||||
|
path, err := dllPath()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
65
voicemeeter/channel.go
Normal file
65
voicemeeter/channel.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type channel struct {
|
||||||
|
identifier string
|
||||||
|
index int
|
||||||
|
kind kind
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter_bool returns the value of a boolean parameter
|
||||||
|
func (c *channel) getter_bool(p string) bool {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
return getParameterFloat(param) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// setter_bool sets the value of a boolean parameter
|
||||||
|
func (c *channel) setter_bool(p string, v bool) {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
var value float32
|
||||||
|
if v {
|
||||||
|
value = 1
|
||||||
|
} else {
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
setParameterFloat(param, float32(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter_int returns the value of an int parameter p
|
||||||
|
func (c *channel) getter_int(p string) int {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
return int(getParameterFloat(param))
|
||||||
|
}
|
||||||
|
|
||||||
|
// setter_int sets the value v of an int parameter p
|
||||||
|
func (c *channel) setter_int(p string, v int) {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
setParameterFloat(param, float32(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter_float returns the value of an int parameter p
|
||||||
|
func (c *channel) getter_float(p string) float64 {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
return getParameterFloat(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setter_float sets the value v of an int parameter p
|
||||||
|
func (c *channel) setter_float(p string, v float32) {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
setParameterFloat(param, float32(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter_string returns the value of a string parameter p
|
||||||
|
func (c *channel) getter_string(p string) string {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
return getParameterString(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setter_string sets the value v of a string parameter p
|
||||||
|
func (c *channel) setter_string(p, v string) {
|
||||||
|
param := fmt.Sprintf("%s[%d].%s", c.identifier, c.index, p)
|
||||||
|
setParameterString(param, v)
|
||||||
|
}
|
44
voicemeeter/kinds.go
Normal file
44
voicemeeter/kinds.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A kind represents a Voicemeeter kinds layout
|
||||||
|
type kind struct {
|
||||||
|
name string
|
||||||
|
physIn int
|
||||||
|
virtIn int
|
||||||
|
physOut int
|
||||||
|
virtOut int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kind) numStrip() int {
|
||||||
|
n := k.physIn + k.virtIn
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kind) numBus() int {
|
||||||
|
n := k.physOut + k.virtOut
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kind) String() string {
|
||||||
|
return fmt.Sprintf("%s%s", strings.ToUpper(k.name[:1]), k.name[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBasicKind returns a basic kind struct address
|
||||||
|
func newBasicKind() *kind {
|
||||||
|
return &kind{"basic", 2, 1, 1, 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBananaKind returns a banana kind struct address
|
||||||
|
func newBananaKind() *kind {
|
||||||
|
return &kind{"banana", 3, 2, 3, 2}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newPotatoKind returns a potato kind struct address
|
||||||
|
func newPotatoKind() *kind {
|
||||||
|
return &kind{"potato", 5, 3, 5, 3}
|
||||||
|
}
|
77
voicemeeter/remote.go
Normal file
77
voicemeeter/remote.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A remote type represents the API for a kind,
|
||||||
|
// comprised of slices representing each member
|
||||||
|
type remote struct {
|
||||||
|
kind *kind
|
||||||
|
Strip []strip
|
||||||
|
Bus []bus
|
||||||
|
Button []button
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the stringer interface
|
||||||
|
func (r *remote) String() string {
|
||||||
|
return fmt.Sprintf("Voicemeeter %s", r.kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remote) Login() {
|
||||||
|
login(r.kind.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remote) Logout() {
|
||||||
|
logout()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remote) Type() string {
|
||||||
|
return getVMType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remote) Version() string {
|
||||||
|
return getVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remote) SendText(script string) {
|
||||||
|
setParametersMulti(script)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRemote returns a remote type of a kind,
|
||||||
|
// this exported method is the interface entry point.
|
||||||
|
func NewRemote(kind_id string) remote {
|
||||||
|
kindMap := map[string]*kind{
|
||||||
|
"basic": newBasicKind(),
|
||||||
|
"banana": newBananaKind(),
|
||||||
|
"potato": newPotatoKind(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_kind, ok := kindMap[kind_id]
|
||||||
|
if !ok {
|
||||||
|
err := fmt.Errorf("unknown Voicemeeter kind '%s'", kind_id)
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
_strip := make([]strip, _kind.numStrip())
|
||||||
|
for i := 0; i < _kind.physIn+_kind.virtIn; i++ {
|
||||||
|
_strip[i] = newStrip(i, _kind)
|
||||||
|
}
|
||||||
|
_bus := make([]bus, _kind.numBus())
|
||||||
|
for i := 0; i < _kind.physOut+_kind.virtOut; i++ {
|
||||||
|
_bus[i] = newBus(i, _kind)
|
||||||
|
}
|
||||||
|
_button := make([]button, 80)
|
||||||
|
for i := 0; i < 80; i++ {
|
||||||
|
_button[i] = newButton(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return remote{
|
||||||
|
kind: _kind,
|
||||||
|
Strip: _strip,
|
||||||
|
Bus: _bus,
|
||||||
|
Button: _button,
|
||||||
|
}
|
||||||
|
}
|
73
voicemeeter/strip.go
Normal file
73
voicemeeter/strip.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package voicemeeter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// custom strip type, struct forwarding channel
|
||||||
|
type strip struct {
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor method for strip
|
||||||
|
func newStrip(i int, k *kind) strip {
|
||||||
|
return strip{channel{"strip", i, *k}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// implement stringer interface in fmt
|
||||||
|
func (s *strip) String() string {
|
||||||
|
if s.index < s.kind.physIn {
|
||||||
|
return fmt.Sprintf("PhysicalStrip%d\n", s.index)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("VirtualStrip%d\n", s.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMute returns the value of the Mute parameter
|
||||||
|
func (s *strip) GetMute() bool {
|
||||||
|
return s.getter_bool("Mute")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMute sets the value of the Mute parameter
|
||||||
|
func (s *strip) SetMute(val bool) {
|
||||||
|
s.setter_bool("Mute", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLimit returns the value of the Limit parameter
|
||||||
|
func (s *strip) GetLimit() int {
|
||||||
|
return s.getter_int("Limit")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLimit sets the value of the Limit parameter
|
||||||
|
func (s *strip) SetLimit(val int) {
|
||||||
|
s.setter_int("Limit", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMc returns the value of the MC parameter
|
||||||
|
func (s *strip) GetMc() bool {
|
||||||
|
return s.getter_bool("MC")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMc sets the value of the MC parameter
|
||||||
|
func (s *strip) SetMc(val bool) {
|
||||||
|
s.setter_bool("MC", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMc returns the value of the MC parameter
|
||||||
|
func (s *strip) GetLabel() string {
|
||||||
|
return s.getter_string("Label")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMc sets the value of the MC parameter
|
||||||
|
func (s *strip) SetLabel(val string) {
|
||||||
|
s.setter_string("Label", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGain returns the value of the Gain parameter
|
||||||
|
func (s *strip) GetGain() float64 {
|
||||||
|
return s.getter_float("Gain")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGain sets the value of the Gain parameter
|
||||||
|
func (s *strip) SetGain(val float32) {
|
||||||
|
s.setter_float("Gain", val)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user