mirror of
				https://github.com/onyx-and-iris/voicemeeter.git
				synced 2025-10-30 22:31:44 +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 the Voiceemeter API  | ||||
| # A Go Wrapper for Voicemeeter 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user