47 Commits
v1.5.0 ... main

Author SHA1 Message Date
onyx-and-iris
38973810d7 add variadic example in events section 2022-10-16 17:24:51 +01:00
onyx-and-iris
be6a49e3bc event Add() and Remove() now variadic.
in strip, vban, log warning then return zero value instead of panic.

update readme
2022-10-10 18:51:30 +01:00
onyx-and-iris
76ed3320d3 when parsing, notify of errors but do not exit
return scanner.err if not nil
2022-10-06 11:31:39 +01:00
onyx-and-iris
8f630d52e7 upd dep files for hotkeys, obs examples 2022-10-05 21:35:13 +01:00
onyx-and-iris
174db162c8 add verbosePrinter to vm-cli example
add info exit from interactive in README
2022-10-05 21:34:59 +01:00
onyx-and-iris
c7a265fb33 fix bug in togglecmd 2022-10-05 13:12:12 +01:00
onyx-and-iris
8bb8336599 interactive mode added to vm-cli example
toggle, get and set refactored into separate functions

flag vars moved from global  scope

-i flag added to README
2022-10-04 20:56:38 +01:00
onyx-and-iris
5b3f10c4b8 print bus level values in observer example 2022-10-04 20:18:48 +01:00
onyx-and-iris
7022c5dacf fix type error in getLevel 2022-10-04 20:18:26 +01:00
onyx-and-iris
5bb7eb9668 remove logrus from vm-cli 2022-09-29 19:04:32 +01:00
onyx-and-iris
5e5a82f198 upd -v flag description 2022-09-29 18:31:15 +01:00
onyx-and-iris
d8de82b90e add note to install in vm-cli 2022-09-29 18:27:26 +01:00
onyx-and-iris
5b4592f484 upd dep ver for obs, hotkeys examples 2022-09-29 18:25:23 +01:00
onyx-and-iris
b2dd96abc4 add install to vm-cli readme 2022-09-29 18:17:23 +01:00
onyx-and-iris
6605d6e62d set log level to info in examples
add verbose flag to vm-cli example

update readme for vm-cli example
2022-09-29 18:05:21 +01:00
onyx-and-iris
3ab5daa61c update install instructions in readme. 2022-09-29 18:04:13 +01:00
onyx-and-iris
0d06098af8 now using logrus package
logrus added to go.mod
2022-09-29 18:02:11 +01:00
onyx-and-iris
9df10d939d clean up installation in readme 2022-09-23 18:17:56 +01:00
onyx-and-iris
d82e6a39f5 fix package name in readme 2022-09-22 23:24:54 +01:00
onyx-and-iris
10d7cea523 Merge branch 'dev' of https://github.com/onyx-and-iris/voicemeeter-api-go into dev 2022-09-22 22:55:24 +01:00
onyx-and-iris
8a9b5f9a97 rename dir structure to match package name
update examples, readme
2022-09-22 22:55:08 +01:00
norm
8a611e39aa change func and var names 2022-09-21 07:30:14 +01:00
norm
ff56dd16f5 upd readme with new default delay 2022-09-19 03:05:02 +01:00
norm
440c3b8eec increae default delay to 20 2022-09-19 03:03:51 +01:00
onyx-and-iris
a5f653f569 add error message if config not found 2022-09-18 20:57:59 +01:00
onyx-and-iris
73893209a1 upd dependency ver 2022-09-18 05:53:08 +01:00
onyx-and-iris
303f1a871c md fix 2022-09-18 05:45:09 +01:00
onyx-and-iris
2c6baf20e4 vm-cli reworked.
now accepts -kind and -delay flags.

arg parsing moved into separate run_commands function.

README added to vm-cli example
2022-09-18 05:39:42 +01:00
onyx-and-iris
c05bf500ee obs example now reads conn info from toml.
vm, obs connect logic moved into separate functions.

README added for obs example.
2022-09-18 05:38:22 +01:00
onyx-and-iris
2533f1c162 refactor observer example.
newObserver factory method added
2022-09-18 05:37:10 +01:00
onyx-and-iris
21fb2ad597 refactor example in readme 2022-09-18 05:36:24 +01:00
onyx-and-iris
1284c92680 refactor hotkeys example. 2022-09-18 05:35:53 +01:00
onyx-and-iris
a87c11099c config.toml added to gitignore 2022-09-18 05:35:27 +01:00
onyx-and-iris
00f66e8f9e GetFloat, SetFloat now return error type on error
GetString, SetString now return error type on error

SendText now returns error type on error

remote_test updated.
2022-09-18 05:35:04 +01:00
onyx-and-iris
e16a51c0da Fade and App methods added to readme. 2022-09-17 03:47:54 +01:00
onyx-and-iris
8a03904ab8 add readme to vm-cli example 2022-09-17 03:21:04 +01:00
onyx-and-iris
5fb7f5e4db remove redundant files 2022-09-17 03:13:50 +01:00
onyx-and-iris
915e3a9609 add vm-cli example 2022-09-17 03:11:53 +01:00
onyx-and-iris
0a7b8e0662 fix whitespace 2022-09-14 21:17:20 +01:00
onyx-and-iris
c32e3995db add hotkeys example 2022-09-14 21:16:29 +01:00
onyx-and-iris
07218472df obs example updated 2022-09-14 16:43:04 +01:00
onyx-and-iris
db7826dab6 reword in readme 2022-09-14 16:11:34 +01:00
onyx-and-iris
32780f11e4 changelog, readme updated to reflect changes
minor bump.
2022-09-14 16:05:49 +01:00
onyx-and-iris
8ca545b1c4 NewRemote now accepts delay param
getters clear dirty params sync enabled.

examples and tests updated
2022-09-14 16:05:15 +01:00
onyx-and-iris
a4b84f289e higher methods/functions now accept/return float64
update tests

update readme, changelog
2022-09-14 00:58:05 +01:00
onyx-and-iris
67cb8509b4 Update README.md 2022-09-07 22:32:37 +01:00
onyx-and-iris
e4de1d49cb upd go.mod for obs example 2022-09-07 21:10:42 +01:00
30 changed files with 795 additions and 289 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,9 @@
# quick tests
quick
#config
config.toml
# Binaries for programs and plugins
*.exe
*.exe~

View File

@@ -11,6 +11,18 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
- [x]
## [1.7.0] - 2022-09-14
### Added
- voicemeeter.NewRemote now accepts a delay int argument (milliseconds).
- vm.Sync() can now be used to force the dirty parameters to clear.
### Changed
- higher level methods/functions now accept/return float64
- tests updated to reflect changes.
## [1.5.0] - 2022-09-07
### Changed

116
README.md
View File

@@ -1,4 +1,4 @@
[![Go Reference](https://pkg.go.dev/badge/github.com/onyx-and-iris/voicemeeter-api-go.svg)](https://pkg.go.dev/github.com/onyx-and-iris/voicemeeter-api-go)
[![Go Reference](https://pkg.go.dev/badge/github.com/onyx-and-iris/voicemeeter.svg)](https://pkg.go.dev/github.com/onyx-and-iris/voicemeeter)
# A Go Wrapper for Voicemeeter API
@@ -19,19 +19,12 @@ For an outline of past/future changes refer to: [CHANGELOG](CHANGELOG.md)
## Installation
#### GO.MOD
Initialize your own module then `go get`
Add to your `go.mod` file:
`require github.com/onyx-and-iris/voicemeeter-api-go vX.X.X`
where `vX.X.X` is the version you require.
#### GO GET
Install voicemeeter-api-go package from your console to download the latest version.
`go get github.com/onyx-and-iris/voicemeeter-api-go`
```
go mod init github.com/x/y
go get github.com/onyx-and-iris/voicemeeter
```
## `Use`
@@ -44,17 +37,11 @@ import (
"fmt"
"log"
"github.com/onyx-and-iris/voicemeeter-api-go"
"github.com/onyx-and-iris/voicemeeter"
)
func main() {
kindId := "banana"
vm, err := voicemeeter.NewRemote(kindId)
if err != nil {
log.Fatal(err)
}
err = vm.Login()
vm, err := vmConnect()
if err != nil {
log.Fatal(err)
}
@@ -64,9 +51,25 @@ func main() {
vm.Strip[0].SetMute(true)
fmt.Printf("Strip 0 (%s) mute was set to %v\n", vm.Strip[0].GetLabel(), vm.Strip[0].GetMute())
}
func vmConnect() (*voicemeeter.Remote, error) {
vm, err := voicemeeter.NewRemote("banana", 20)
if err != nil {
return nil, err
}
err = vm.Login()
if err != nil {
return nil, err
}
return vm, nil
}
```
## `kindId`
## `voicemeeter.NewRemote(<kindId>, <delay>)`
### `kindId`
Pass the kind of Voicemeeter as an argument. kindId may be:
@@ -74,6 +77,12 @@ Pass the kind of Voicemeeter as an argument. kindId may be:
- `banana`
- `potato`
### `delay`
Pass a delay in milliseconds to force the getters to wait for dirty parameters to clear.
Useful if not running callbacks.
## `Remote Type`
#### `vm.Strip`
@@ -138,19 +147,19 @@ sets many parameters in script format eg. ("Strip[0].Mute=1;Bus[3].Gain=3.6")
#### `vm.Register(o observer)`
register an object as an observer
register an observer type as an observer
#### `vm.Deregister(o observer)`
deregister an object as an observer
deregister an observer type as an observer
#### `vm.EventAdd(<event>)`
#### `vm.EventAdd(<events>)`
adds an event to the pooler eg. vm.EventAdd("ldirty")
adds a single or multiple events to the pooler. Accepts a string or slice of strings.
#### `vm.EventRemove(<event>)`
#### `vm.EventRemove(<events>)`
removes an event to the pooler eg. vm.EventRemove("pdirty")
removes a single or multiple events from the pooler. Accepts a string or slice of strings.
#### `vm.Pdirty()`
@@ -160,6 +169,10 @@ returns True iff a GUI parameter has changed
returns True iff a macrobutton parameter has changed
#### `vm.Sync()`
Use this to force dirty parameters to clear after a delay in milliseconds.
## `Available commands`
### Strip
@@ -177,17 +190,19 @@ The following methods are available
- `GetLabel() string`
- `SetLabel(val string)`
- `GetGain() float64`
- `SetGain(val float32)` from -60.0 to 12.0
- `SetGain(val float64)` from -60.0 to 12.0
- `GetMc() bool`
- `SetMc(val bool)`
- `GetComp() float64`
- `SetComp(val float32)` from 0.0 to 10.0
- `SetComp(val float64)` from 0.0 to 10.0
- `GetGate() float64`
- `SetGate(val float32)` from 0.0 to 10.0
- `SetGate(val float64)` from 0.0 to 10.0
- `GetAudibility() float64`
- `SetAudibility(val float32)` from 0.0 to 10.0
- `SetAudibility(val float64)` from 0.0 to 10.0
- `GetA1() bool - GetA5() bool`
- `SetA1(val bool) - SetA5(val bool)`
- `AppGain(name string, gain float64)`
- `AppMute(name string, val bool)`
example:
@@ -195,6 +210,9 @@ example:
vm.Strip[3].SetGain(3.7)
fmt.Println(vm.Strip[0].GetLabel())
vm.Strip[4].SetA1(true)
vm.Strip[5].AppGain("Spotify", 0.5)
vm.Strip[5].AppMute("Spotify", true)
```
##### Gainlayers
@@ -204,7 +222,7 @@ vm.Strip[4].SetA1(true)
The following methods are available
- `Get() float64`
- `Set(val float32)`
- `Set(val float64)`
example:
@@ -218,9 +236,9 @@ vm.Strip[6].GainLayer()[3].Set(-13.6)
The following methods are available
- `PreFader() []float32`
- `PostFader() []float32`
- `PostMute() []float32`
- `PreFader() []float64`
- `PostFader() []float64`
- `PostMute() []float64`
example:
@@ -242,7 +260,7 @@ The following methods are available
- `GetLabel() string`
- `SetLabel(val string)`
- `GetGain() float64`
- `SetGain(val float32)` from -60.0 to 12.0
- `SetGain(val float64)` from -60.0 to 12.0
```go
vm.Bus[3].SetEq(true)
@@ -293,7 +311,7 @@ vm.Bus[4].Mode().SetCenterOnly(true)
The following methods are available
- `All() []float32`
- `All() []float64`
example:
@@ -301,6 +319,22 @@ example:
fmt.Println(vm.Bus[1].Levels().All())
```
### Strip | Bus
The following methods are available.
- `FadeTo(target float64, time_ int)`: float, int
- `FadeBy(change float64, time_ int)`: float, int
Modify gain to or by the selected amount in db over a time interval in ms.
example:
```go
vm.Strip[3].FadeBy(-8.3, 500)
vm.Bus[3].FadeTo(-12.8, 500)
```
### Button
The following methods are available
@@ -447,9 +481,11 @@ By default level updates are disabled. Any event may be enabled or disabled. The
example:
```go
vm.EventAdd("ldirty")
events := []string{"ldirty", "mdirty", "pdirty"}
vm.EventRemove("pdirty")
vm.EventAdd(events...)
vm.EventRemove(events...)
```
### Run tests

37
base.go
View File

@@ -8,6 +8,8 @@ import (
"syscall"
"time"
"unsafe"
log "github.com/sirupsen/logrus"
)
var (
@@ -52,7 +54,7 @@ func login(kindId string) error {
err := fmt.Errorf("VBVMR_Login returned %d", res)
return err
}
fmt.Printf("Logged into Voicemeeter %s\n", kindId)
log.Info("Logged into Voicemeeter ", kindId)
for pdirty() || mdirty() {
}
return nil
@@ -67,7 +69,7 @@ func logout(kindId string) error {
err := fmt.Errorf("VBVMR_Logout returned %d", res)
return err
}
fmt.Printf("Logged out of Voicemeeter %s\n", kindId)
log.Info("Logged out of Voicemeeter ", kindId)
return nil
}
@@ -115,8 +117,8 @@ func mdirty() bool {
// ldirty returns true iff a level value has changed
func ldirty(k *kind) bool {
_levelCache.stripLevelsBuff = make([]float32, (2*k.PhysIn)+(8*k.VirtIn))
_levelCache.busLevelsBuff = make([]float32, 8*k.NumBus())
_levelCache.stripLevelsBuff = make([]float64, (2*k.PhysIn)+(8*k.VirtIn))
_levelCache.busLevelsBuff = make([]float64, 8*k.NumBus())
for i := 0; i < (2*k.PhysIn)+(8*k.VirtIn); i++ {
val, _ := getLevel(_levelCache.stripMode, i)
@@ -151,6 +153,11 @@ func getVMType() (string, error) {
// getParameterFloat gets the value of a float parameter
func getParameterFloat(name string) (float64, error) {
if vmsync {
time.Sleep(time.Duration(vmdelay) * time.Millisecond)
for pdirty() || mdirty() {
}
}
var value float32
b := append([]byte(name), 0)
res, _, _ := vmGetParamFloat.Call(
@@ -165,9 +172,9 @@ func getParameterFloat(name string) (float64, error) {
}
// setParameterFloat sets the value of a float parameter
func setParameterFloat(name string, value float32) error {
func setParameterFloat(name string, value float64) error {
b1 := append([]byte(name), 0)
b2 := math.Float32bits(value)
b2 := math.Float32bits(float32(value))
res, _, _ := vmSetParamFloat.Call(
uintptr(unsafe.Pointer(&b1[0])),
uintptr(b2),
@@ -181,6 +188,11 @@ func setParameterFloat(name string, value float32) error {
// getParameterString gets the value of a string parameter
func getParameterString(name string) (string, error) {
if vmsync {
time.Sleep(time.Duration(vmdelay) * time.Millisecond)
for pdirty() || mdirty() {
}
}
b1 := append([]byte(name), 0)
var b2 [512]byte
res, _, _ := vmGetParamString.Call(
@@ -224,7 +236,12 @@ func setParametersMulti(script string) error {
}
// getMacroStatus gets a macrobutton value
func getMacroStatus(id, mode int) (float32, error) {
func getMacroStatus(id, mode int) (float64, error) {
if vmsync {
time.Sleep(time.Duration(vmdelay) * time.Millisecond)
for pdirty() || mdirty() {
}
}
var state float32
res, _, _ := vmGetMacroStatus.Call(
uintptr(id),
@@ -235,7 +252,7 @@ func getMacroStatus(id, mode int) (float32, error) {
err := fmt.Errorf("VBVMR_MacroButton_GetStatus returned %d", res)
return 0, err
}
return state, nil
return float64(state), nil
}
// setMacroStatus sets a macrobutton value
@@ -297,7 +314,7 @@ func getDeviceDescription(i int, dir string) (string, uint64, string, error) {
}
// getLevel returns a single level value of type type_ for channel[i]
func getLevel(type_, i int) (float32, error) {
func getLevel(type_, i int) (float64, error) {
var val float32
res, _, _ := vmGetLevelFloat.Call(
uintptr(type_),
@@ -308,7 +325,7 @@ func getLevel(type_, i int) (float32, error) {
err := fmt.Errorf("VBVMR_GetLevel returned %d", res)
return 0, err
}
return val, nil
return float64(val), nil
}
// getMidiMessage gets midi channel, pitch and velocity for a single midi input

12
bus.go
View File

@@ -17,7 +17,7 @@ type iBus interface {
GetLabel() string
SetLabel(val string)
GetGain() float64
SetGain(val float32)
SetGain(val float64)
Mode() iBusMode
Levels() *levels
FadeTo(target float32, time_ int)
@@ -77,7 +77,7 @@ func (b *bus) GetGain() float64 {
}
// SetGain sets the value of the Gain parameter
func (b *bus) SetGain(val float32) {
func (b *bus) SetGain(val float64) {
b.setter_float("Gain", val)
}
@@ -103,7 +103,7 @@ func (b *bus) FadeBy(change float32, time_ int) {
time.Sleep(time.Millisecond)
}
//physicalBus represents a single physical bus
// physicalBus represents a single physical bus
type physicalBus struct {
bus
}
@@ -122,7 +122,7 @@ func (p *physicalBus) String() string {
return fmt.Sprintf("PhysicalBus%d", p.index)
}
//virtualBus represents a single virtual bus
// virtualBus represents a single virtual bus
type virtualBus struct {
bus
}
@@ -305,8 +305,8 @@ func newBusLevels(i int, k *kind) levels {
}
// All returns the level values for a bus
func (l *levels) All() []float32 {
var levels []float32
func (l *levels) All() []float64 {
var levels []float64
for i := l.init; i < l.init+l.offset; i++ {
levels = append(levels, convertLevel(_levelCache.busLevels[i]))
}

View File

@@ -1,6 +1,6 @@
package voicemeeter
//command represents command (action) type parameters
// command represents command (action) type parameters
type command struct {
iRemote
}
@@ -32,7 +32,7 @@ func (c *command) Restart() {
// Lock locks or unlocks the Voiceemeter GUI
func (c *command) Lock(val bool) {
var value float32
var value float64
if val {
value = 1
} else {

11
examples/hotkeys/go.mod Normal file
View File

@@ -0,0 +1,11 @@
module main
go 1.19
require (
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
github.com/onyx-and-iris/voicemeeter v1.10.1
github.com/sirupsen/logrus v1.9.0
)
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect

19
examples/hotkeys/go.sum Normal file
View File

@@ -0,0 +1,19 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg=
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg=
github.com/onyx-and-iris/voicemeeter v1.10.1 h1:kpPN/cTYe1JG2aLUD+/m/bMUbp7wXrqrk1fL+sV8yko=
github.com/onyx-and-iris/voicemeeter v1.10.1/go.mod h1:LayUoN/MWSqKXSOGQ7AcLvwoefsL+zQ9CjncLs3WqsU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

71
examples/hotkeys/main.go Normal file
View File

@@ -0,0 +1,71 @@
package main
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/eiannone/keyboard"
"github.com/onyx-and-iris/voicemeeter"
)
func init() {
log.SetLevel(log.InfoLevel)
}
func main() {
if err := keyboard.Open(); err != nil {
log.Fatal(err)
}
defer func() {
_ = keyboard.Close()
}()
vm, err := vmConnect()
if err != nil {
log.Fatal(err)
}
defer vm.Logout()
fmt.Println("Press ESC to quit")
Loop:
for {
char, key, err := keyboard.GetKey()
if err != nil {
panic(err)
}
switch char {
case '0':
fmt.Printf("Logged into Voicemeeter %s, version %s\n", vm.Type(), vm.Version())
case '1':
vm.Strip[0].SetMute(!vm.Strip[0].GetMute())
case '2':
if vm.Strip[3].GetGain() == -12.8 {
vm.Strip[3].FadeBy(-8.3, 500)
} else {
vm.Strip[3].FadeTo(-12.8, 500)
}
case '3':
vm.Strip[5].AppMute("Spotify", true)
default:
if key == keyboard.KeyEsc {
break Loop
}
}
}
}
func vmConnect() (*voicemeeter.Remote, error) {
vm, err := voicemeeter.NewRemote("potato", 0)
if err != nil {
return nil, err
}
err = vm.Login()
if err != nil {
return nil, err
}
return vm, nil
}

19
examples/obs/README.md Normal file
View File

@@ -0,0 +1,19 @@
## Requirements
- [OBS Studio](https://obsproject.com/)
- [GOOBS Go Client for Websocket v5](https://github.com/andreykaipov/goobs)
## About
A simple demonstration showing how to sync OBS scene switches to Voicemeeter states. The script assumes you have connection info saved in
a config file named `config.toml` placed next to `main.go`. It also assumes you have scenes named `START` `BRB` `END` and `LIVE`.
A valid `config.toml` file might look like this:
```toml
[connection]
Host="localhost"
Port=4455
Password="mystrongpass"
```

View File

@@ -3,8 +3,10 @@ module main
go 1.18
require (
github.com/BurntSushi/toml v1.2.0
github.com/andreykaipov/goobs v0.10.0
github.com/onyx-and-iris/voicemeeter-api-go v1.4.1
github.com/onyx-and-iris/voicemeeter v1.10.1
github.com/sirupsen/logrus v1.9.0
)
require (
@@ -12,5 +14,5 @@ require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
)

View File

@@ -1,18 +1,29 @@
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/andreykaipov/goobs v0.10.0 h1:wa4CxbYu/NqwUmx5E4/baDqYRYEmfHwg2T23RAg3jlU=
github.com/andreykaipov/goobs v0.10.0/go.mod h1:EqG73Uu/4npyhXIWWszgRelNkEeIz+d0slUT6NKWYs4=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/onyx-and-iris/voicemeeter-api-go v1.4.1 h1:2vGaRGCPwN9PlWspbdkDelsfxWHHkZqxozkd6FOcl28=
github.com/onyx-and-iris/voicemeeter-api-go v1.4.1/go.mod h1:zAdBhHXQ9n37CUbLizbOPmAutyZI8Ncqeu5e9u1Fy14=
github.com/onyx-and-iris/voicemeeter v1.10.1 h1:kpPN/cTYe1JG2aLUD+/m/bMUbp7wXrqrk1fL+sV8yko=
github.com/onyx-and-iris/voicemeeter v1.10.1/go.mod h1:LayUoN/MWSqKXSOGQ7AcLvwoefsL+zQ9CjncLs3WqsU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -2,13 +2,17 @@ package main
import (
"fmt"
"log"
"os"
"time"
"github.com/onyx-and-iris/voicemeeter-api-go"
log "github.com/sirupsen/logrus"
"github.com/onyx-and-iris/voicemeeter"
"github.com/andreykaipov/goobs"
"github.com/andreykaipov/goobs/api/events"
"github.com/BurntSushi/toml"
)
func onStart(vm *voicemeeter.Remote) {
@@ -38,19 +42,18 @@ func onEnd(vm *voicemeeter.Remote) {
vm.Vban.InStream[0].SetOn(false)
}
func main() {
vm, err := voicemeeter.NewRemote("potato")
if err != nil {
log.Fatal(err)
}
func init() {
log.SetLevel(log.InfoLevel)
}
err = vm.Login()
func main() {
vm, err := vmConnect()
if err != nil {
log.Fatal(err)
}
defer vm.Logout()
obs, err := goobs.New("localhost:4455", goobs.WithPassword("mystrongpass"))
obs, err := obsConnect()
if err != nil {
log.Fatal(err)
}
@@ -79,3 +82,50 @@ func main() {
time.Sleep(30 * time.Second)
}
func vmConnect() (*voicemeeter.Remote, error) {
vm, err := voicemeeter.NewRemote("potato", 0)
if err != nil {
return nil, err
}
err = vm.Login()
if err != nil {
return nil, err
}
return vm, nil
}
func obsConnect() (*goobs.Client, error) {
type (
connection struct {
Host string
Port int
Password string
}
config struct {
Connection map[string]connection
}
)
f := "config.toml"
if _, err := os.Stat(f); err != nil {
err := fmt.Errorf("unable to locate %s", f)
return nil, err
}
var c config
_, err := toml.DecodeFile(f, &c.Connection)
if err != nil {
return nil, err
}
conn := c.Connection["connection"]
obs, err := goobs.New(fmt.Sprintf("%s:%d", conn.Host, conn.Port), goobs.WithPassword(conn.Password))
if err != nil {
return nil, err
}
return obs, nil
}

View File

@@ -2,24 +2,36 @@ package main
import (
"fmt"
"log"
"time"
"github.com/onyx-and-iris/voicemeeter-api-go"
log "github.com/sirupsen/logrus"
"github.com/onyx-and-iris/voicemeeter"
)
// observer represents a single receiver of updates
type observer struct {
vm *voicemeeter.Remote
}
func (o observer) Register() {
// newObserver add ldirty events to the eventlist and returns an observer type
func newObserver(vm *voicemeeter.Remote) *observer {
vm.EventAdd("ldirty")
return &observer{vm}
}
// register registers this observer to receive updates
func (o observer) register() {
o.vm.Register(o)
}
func (o observer) Deregister() {
// deregister deregisters this observer to receive updates
func (o observer) deregister() {
o.vm.Deregister(o)
}
// OnUpdate satisfies the observer interface defined in publisher.go
// for each event type an action is triggered when the event occurs.
func (o observer) OnUpdate(subject string) {
if subject == "pdirty" {
fmt.Println("pdirty!")
@@ -30,35 +42,44 @@ func (o observer) OnUpdate(subject string) {
var val = o.vm.Midi.Get(current)
fmt.Printf("Value of midi button %d: %d\n", current, val)
} else if subject == "ldirty" {
fmt.Printf("%v %v %v %v %v %v %v %v\n",
o.vm.Bus[0].Levels().IsDirty(),
o.vm.Bus[1].Levels().IsDirty(),
o.vm.Bus[2].Levels().IsDirty(),
o.vm.Bus[3].Levels().IsDirty(),
o.vm.Bus[4].Levels().IsDirty(),
o.vm.Bus[5].Levels().IsDirty(),
o.vm.Bus[6].Levels().IsDirty(),
o.vm.Bus[7].Levels().IsDirty(),
)
for _, bus := range o.vm.Bus {
if bus.Levels().IsDirty() {
fmt.Println(bus, bus.Levels().All())
}
}
}
}
func main() {
vm, err := voicemeeter.NewRemote("potato")
if err != nil {
log.Fatal(err)
}
func init() {
log.SetLevel(log.InfoLevel)
}
err = vm.Login()
// main connects to Voiceemeter, registers observer for updates
// runs updates for 30 seconds and then deregisters observer.
func main() {
vm, err := vmConnect()
if err != nil {
log.Fatal(err)
}
defer vm.Logout()
// enable level updates (disabled by default)
vm.EventAdd("ldirty")
o := observer{vm}
o.Register()
o := newObserver(vm)
o.register()
time.Sleep(30 * time.Second)
o.Deregister()
o.deregister()
}
// vmConnect connects to Voicemeeter potato and logs into the API
func vmConnect() (*voicemeeter.Remote, error) {
vm, err := voicemeeter.NewRemote("potato", 0)
if err != nil {
return nil, err
}
err = vm.Login()
if err != nil {
return nil, err
}
return vm, nil
}

35
examples/vm-cli/README.md Normal file
View File

@@ -0,0 +1,35 @@
## About
A simple voicemeeter-cli program. Offers ability to toggle, get and set parameters.
## Install
First build and install it with `go install` (skip this step if using binary from [Releases](https://github.com/onyx-and-iris/voicemeeter/releases))
## Use
Toggle with `!` prefix, get by excluding `=` and set by including `=`. Mix and match arguments.
You may pass the following optional flags:
- -v: (-verbose) to toggle console output.
- -i: (-interactive) to toggle interactive mode.
- -k: (-kind) to set the kind of Voicemeeter. Defaults to banana.
- -d: (-delay) to set a delay on the getters. Defaults to 20ms.
for example:
`vm-cli.exe -v -k=potato -d=25 strip[0].mute=0 strip[0].mute !strip[0].mute strip[0].mute bus[0].gain=-8.8 command.lock=1`
Expected output:
```
Running command strip[0].mute=0
Value of strip[0].mute is: 0
Toggling strip[0].mute
Value of strip[0].mute is: 1
Running command bus[0].gain=-8.8
Running command command.lock=1
```
If running in interactive mode enter `q`, `quit` or `<Enter>` to exit.

176
examples/vm-cli/main.go Normal file
View File

@@ -0,0 +1,176 @@
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"strings"
"github.com/onyx-and-iris/voicemeeter"
)
type (
verbosePrinter struct {
verbose bool
}
)
func newVerbosePrinter() *verbosePrinter {
return &verbosePrinter{}
}
func (v *verbosePrinter) printf(format string, a ...interface{}) {
if v.verbose {
fmt.Printf(format+"\n", a...)
}
}
var (
vPrinter *verbosePrinter
)
func init() {
vPrinter = newVerbosePrinter()
}
func main() {
var (
kind string
delay int
interactive bool
)
flag.StringVar(&kind, "kind", "banana", "kind of voicemeeter")
flag.StringVar(&kind, "k", "banana", "kind of voicemeeter (shorthand)")
flag.IntVar(&delay, "delay", 20, "delay between commands")
flag.IntVar(&delay, "d", 20, "delay between commands (shorthand)")
flag.BoolVar(&vPrinter.verbose, "verbose", false, "toggle console output")
flag.BoolVar(&vPrinter.verbose, "v", false, "toggle console output (shorthand)")
flag.BoolVar(&interactive, "interactive", false, "toggle interactive mode")
flag.BoolVar(&interactive, "i", false, "toggle interactive mode (shorthand)")
flag.Parse()
vm, err := vmConnect(kind, delay)
if err != nil {
log.Fatal(err)
}
defer vm.Logout()
err = runCommands(vm, interactive)
if err != nil {
fmt.Println(err)
}
}
func vmConnect(kind string, delay int) (*voicemeeter.Remote, error) {
vm, err := voicemeeter.NewRemote(kind, delay)
if err != nil {
return nil, err
}
err = vm.Login()
if err != nil {
return nil, err
}
return vm, nil
}
func runCommands(vm *voicemeeter.Remote, interactive bool) error {
if interactive {
return interactiveMode(vm)
}
args := flag.Args()
if len(args) == 0 {
err := fmt.Errorf("must provide some commands to run")
return err
}
for _, arg := range args {
err := parse(vm, arg)
if err != nil {
vPrinter.printf(err.Error())
}
}
return nil
}
func interactiveMode(vm *voicemeeter.Remote) error {
vPrinter.printf("running in interactive mode... waiting for input")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input := scanner.Text()
if input == "q" || input == "quit" || input == "" {
return nil
}
for _, cmd := range strings.Split(input, " ") {
err := parse(vm, cmd)
if err != nil {
vPrinter.printf(err.Error())
}
}
}
if scanner.Err() != nil {
return scanner.Err()
}
return nil
}
func parse(vm *voicemeeter.Remote, cmd string) error {
if cmd[0] == '!' {
err := toggleCmd(vm, cmd[1:])
if err != nil {
return err
}
} else {
if strings.Contains(cmd, "=") {
err := setCmd(vm, cmd)
if err != nil {
return err
}
} else {
err := getCmd(vm, cmd)
if err != nil {
return err
}
}
}
return nil
}
func toggleCmd(vm *voicemeeter.Remote, cmd string) error {
val, err := vm.GetFloat(cmd)
if err != nil {
err = fmt.Errorf("unable to toggle %s", cmd)
return err
}
vm.SetFloat(cmd, 1-val)
vPrinter.printf("Toggling %s", cmd)
return nil
}
func setCmd(vm *voicemeeter.Remote, cmd string) error {
vPrinter.printf("Running command %s", cmd)
err := vm.SendText(cmd)
if err != nil {
err = fmt.Errorf("unable to set %s", cmd)
return err
}
return nil
}
func getCmd(vm *voicemeeter.Remote, cmd string) error {
valF, err := vm.GetFloat(cmd)
if err != nil {
valS, err := vm.GetString(cmd)
if err != nil {
err = fmt.Errorf("unable to get %s", cmd)
return err
}
vPrinter.printf("Value of %s is: %s", cmd, valS)
} else {
vPrinter.printf("Value of %s is: %v", cmd, valF)
}
return nil
}

11
go.mod
View File

@@ -1,15 +1,14 @@
module github.com/onyx-and-iris/voicemeeter-api-go
module github.com/onyx-and-iris/voicemeeter
go 1.18
retract (
// package files moved into root of repository
[v1.0.0, v1.1.0]
)
// package files moved into root of repository
retract [v1.0.0, v1.1.0]
require (
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.0
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8
)
require (

7
go.sum
View File

@@ -3,13 +3,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -4,11 +4,10 @@ import (
"log"
"os"
"testing"
"time"
)
var (
vm, err = NewRemote("potato")
vm, err = NewRemote("potato", 30)
)
func TestMain(m *testing.M) {
@@ -21,9 +20,3 @@ func TestMain(m *testing.M) {
vm.Logout()
os.Exit(code)
}
func sync() {
time.Sleep(30 * time.Millisecond)
for vm.Pdirty() || vm.Mdirty() {
}
}

View File

@@ -35,7 +35,7 @@ func (ir *iRemote) setter_bool(p string, v bool) {
} else {
value = 0
}
err := setParameterFloat(param, float32(value))
err := setParameterFloat(param, float64(value))
if err != nil {
fmt.Println(err)
}
@@ -54,7 +54,7 @@ func (ir *iRemote) getter_int(p string) int {
// setter_int sets the value v of an int parameter p
func (ir *iRemote) setter_int(p string, v int) {
param := fmt.Sprintf("%s.%s", ir.identifier(), p)
err := setParameterFloat(param, float32(v))
err := setParameterFloat(param, float64(v))
if err != nil {
fmt.Println(err)
}
@@ -71,9 +71,9 @@ func (ir *iRemote) getter_float(p string) float64 {
}
// setter_float sets the value v of an int parameter p
func (ir *iRemote) setter_float(p string, v float32) {
func (ir *iRemote) setter_float(p string, v float64) {
param := fmt.Sprintf("%s.%s", ir.identifier(), p)
err := setParameterFloat(param, float32(v))
err := setParameterFloat(param, float64(v))
if err != nil {
fmt.Println(err)
}

View File

@@ -25,18 +25,18 @@ var _levelCache *levelCache
// levelCache defines level slices used by the pooler to track updates
type levelCache struct {
stripMode int
stripLevels []float32
busLevels []float32
stripLevelsBuff []float32
busLevelsBuff []float32
stripLevels []float64
busLevels []float64
stripLevelsBuff []float64
busLevelsBuff []float64
stripComp []bool
busComp []bool
}
// newLevelCache returns a levelCache struct address
func newLevelCache(k *kind) *levelCache {
stripLevels := make([]float32, (2*k.PhysIn)+(8*k.VirtIn))
busLevels := make([]float32, 8*k.NumBus())
stripLevels := make([]float64, (2*k.PhysIn)+(8*k.VirtIn))
busLevels := make([]float64, 8*k.NumBus())
stripComp := make([]bool, (2*k.PhysIn)+(8*k.VirtIn))
busComp := make([]bool, 8*k.NumBus())
if _levelCache == nil {

View File

@@ -2,6 +2,8 @@ package voicemeeter
import (
"time"
log "github.com/sirupsen/logrus"
)
// observer defines the interface any registered observers must satisfy
@@ -51,8 +53,9 @@ func newEvent() *event {
return &event{true, true, true, false}
}
func (e *event) Add(ev string) {
switch ev {
func (e *event) Add(events ...string) {
for _, event := range events {
switch event {
case "pdirty":
e.pdirty = true
case "mdirty":
@@ -62,10 +65,13 @@ func (e *event) Add(ev string) {
case "ldirty":
e.ldirty = true
}
log.Info(event, " added to the pooler")
}
}
func (e *event) Remove(ev string) {
switch ev {
func (e *event) Remove(events ...string) {
for _, event := range events {
switch event {
case "pdirty":
e.pdirty = false
case "mdirty":
@@ -75,6 +81,8 @@ func (e *event) Remove(ev string) {
case "ldirty":
e.ldirty = false
}
log.Info(event, " removed from the pooler")
}
}
// pooler continuously polls the dirty paramters

105
remote.go
View File

@@ -2,9 +2,13 @@ package voicemeeter
import (
"fmt"
"os"
"time"
log "github.com/sirupsen/logrus"
)
// A Remote type represents the API for a kind
// Remote represents the API for a kind
type Remote struct {
Kind *kind
Strip []iStrip
@@ -74,37 +78,56 @@ func (r *Remote) Mdirty() bool {
return mdirty()
}
// Gets a float parameter value
func (r *Remote) GetFloat(name string) float64 {
// Sync is a helper method that waits for dirty parameters to clear
func (r *Remote) Sync() {
time.Sleep(time.Duration(vmdelay) * time.Millisecond)
for r.Pdirty() || r.Mdirty() {
}
}
// GetFloat gets a float parameter value
func (r *Remote) GetFloat(name string) (float64, error) {
val, err := getParameterFloat(name)
if err != nil {
fmt.Println(err)
return 0, err
}
return val
return val, nil
}
// Sets a float paramter value
func (r *Remote) SetFloat(name string, value float32) {
setParameterFloat(name, value)
// SetFloat sets a float paramter value
func (r *Remote) SetFloat(name string, value float64) error {
err := setParameterFloat(name, value)
if err != nil {
return err
}
return nil
}
// Gets a string parameter value
func (r *Remote) GetString(name string) string {
// GetString gets a string parameter value
func (r *Remote) GetString(name string) (string, error) {
val, err := getParameterString(name)
if err != nil {
fmt.Println(err)
return "", err
}
return val
return val, nil
}
// Sets a string paramter value
func (r *Remote) SetString(name, value string) {
setParameterString(name, value)
// SetString sets a string parameter value
func (r *Remote) SetString(name, value string) error {
err := setParameterString(name, value)
if err != nil {
return err
}
return nil
}
// SendText sets multiple parameters by script
func (r *Remote) SendText(script string) {
setParametersMulti(script)
func (r *Remote) SendText(script string) error {
err := setParametersMulti(script)
if err != nil {
return err
}
return nil
}
// Register forwards the register method to Pooler
@@ -117,14 +140,14 @@ func (r *Remote) Deregister(o observer) {
r.pooler.Deregister(o)
}
// EventAdd adds an event to the Pooler
func (r *Remote) EventAdd(event string) {
r.pooler.event.Add(event)
// EventAdd adds events to the Pooler
func (r *Remote) EventAdd(events ...string) {
r.pooler.event.Add(events...)
}
// EventRemove removes an event from the Pooler
func (r *Remote) EventRemove(event string) {
r.pooler.event.Remove(event)
// EventRemove removes events from the Pooler
func (r *Remote) EventRemove(events ...string) {
r.pooler.event.Remove(events...)
}
// remoteBuilder defines the interface builder types must satisfy
@@ -142,7 +165,7 @@ type remoteBuilder interface {
Get() *Remote
}
// directory is responsible for directing the genericBuilder
// director is responsible for directing the genericBuilder
type director struct {
builder remoteBuilder
}
@@ -177,7 +200,7 @@ func (b *genericBuilder) setKind() remoteBuilder {
// makeStrip makes a strip slice and assigns it to remote.Strip
// []iStrip comprises of both physical and virtual strip types
func (b *genericBuilder) makeStrip() remoteBuilder {
fmt.Println("building strip")
log.Info("building strip")
_strip := make([]iStrip, b.k.NumStrip())
for i := 0; i < b.k.NumStrip(); i++ {
if i < b.k.PhysIn {
@@ -193,7 +216,7 @@ func (b *genericBuilder) makeStrip() remoteBuilder {
// makeBus makes a bus slice and assigns it to remote.Bus
// []t_bus comprises of both physical and virtual bus types
func (b *genericBuilder) makeBus() remoteBuilder {
fmt.Println("building bus")
log.Info("building bus")
_bus := make([]iBus, b.k.NumBus())
for i := 0; i < b.k.NumBus(); i++ {
if i < b.k.PhysOut {
@@ -208,7 +231,7 @@ func (b *genericBuilder) makeBus() remoteBuilder {
// makeButton makes a button slice and assigns it to remote.Button
func (b *genericBuilder) makeButton() remoteBuilder {
fmt.Println("building button")
log.Info("building button")
_button := make([]button, 80)
for i := 0; i < 80; i++ {
_button[i] = newButton(i)
@@ -219,35 +242,35 @@ func (b *genericBuilder) makeButton() remoteBuilder {
// makeCommand makes a command type and assigns it to remote.Command
func (b *genericBuilder) makeCommand() remoteBuilder {
fmt.Println("building command")
log.Info("building command")
b.r.Command = newCommand()
return b
}
// makeVban makes a vban type and assigns it to remote.Vban
func (b *genericBuilder) makeVban() remoteBuilder {
fmt.Println("building vban")
log.Info("building vban")
b.r.Vban = newVban(b.k)
return b
}
// makeDevice makes a device type and assigns it to remote.Device
func (b *genericBuilder) makeDevice() remoteBuilder {
fmt.Println("building device")
log.Info("building device")
b.r.Device = newDevice()
return b
}
// makeRecorder makes a recorder type and assigns it to remote.Recorder
func (b *genericBuilder) makeRecorder() remoteBuilder {
fmt.Println("building recorder")
log.Info("building recorder")
b.r.Recorder = newRecorder()
return b
}
// makeMidi makes a midi type and assigns it to remote.Midi
func (b *genericBuilder) makeMidi() remoteBuilder {
fmt.Println("building midi")
log.Info("building midi")
b.r.Midi = newMidi()
return b
}
@@ -310,14 +333,30 @@ func (potb *potatoBuilder) Build() remoteBuilder {
makeMidi()
}
var (
vmsync bool
vmdelay int
)
func init() {
log.SetOutput(os.Stdout)
log.SetLevel(log.WarnLevel)
}
// NewRemote returns a Remote type for a kind
// this is the interface entry point
func NewRemote(kindId string) (*Remote, error) {
func NewRemote(kindId string, delay int) (*Remote, error) {
_kind, ok := kindMap[kindId]
if !ok {
err := fmt.Errorf("unknown Voicemeeter kind '%s'", kindId)
return nil, err
}
if delay < 0 {
err := fmt.Errorf("invalid delay value. should be >= 0")
return nil, err
}
vmsync = delay > 0
vmdelay = delay
director := director{}
switch _kind.Name {

View File

@@ -8,7 +8,7 @@ import (
func TestGetBasicRemote(t *testing.T) {
//t.Skip("skipping test")
__rem, _ := NewRemote("basic")
__rem, _ := NewRemote("basic", 0)
t.Run("Should return a remote basic type", func(t *testing.T) {
assert.NotNil(t, __rem)
})
@@ -34,7 +34,7 @@ func TestGetBasicRemote(t *testing.T) {
func TestGetBananaRemote(t *testing.T) {
//t.Skip("skipping test")
__rem, _ := NewRemote("banana")
__rem, _ := NewRemote("banana", 0)
t.Run("Should return a remote banana type", func(t *testing.T) {
assert.NotNil(t, __rem)
})
@@ -60,7 +60,7 @@ func TestGetBananaRemote(t *testing.T) {
func TestGetPotatoRemote(t *testing.T) {
//t.Skip("skipping test")
__rem, _ := NewRemote("potato")
__rem, _ := NewRemote("potato", 0)
t.Run("Should return a remote basic type", func(t *testing.T) {
assert.NotNil(t, __rem)
})
@@ -87,20 +87,21 @@ func TestGetPotatoRemote(t *testing.T) {
func TestSetAndGetFloatParameter(t *testing.T) {
//t.Skip("skipping test")
var param = "strip[0].mute"
var exp = float64(1)
vm.SetFloat(param, 1)
sync()
t.Run("Should get a float parameter", func(t *testing.T) {
assert.Equal(t, float64(1), vm.GetFloat(param))
val, _ := vm.GetFloat(param)
assert.Equal(t, exp, val)
})
}
func TestSetAndGetStringParameter(t *testing.T) {
//t.Skip("skipping test")
var param = "strip[0].label"
var val = "test0"
vm.SetString(param, val)
sync()
var exp = "test0"
vm.SetString(param, exp)
t.Run("Should get a string parameter", func(t *testing.T) {
assert.Equal(t, val, vm.GetString(param))
val, _ := vm.GetString(param)
assert.Equal(t, exp, val)
})
}

View File

@@ -3,9 +3,11 @@ package voicemeeter
import (
"fmt"
"time"
log "github.com/sirupsen/logrus"
)
// iStrip defines the interface bus types must satisfy
// iStrip defines the interface strip types must satisfy
type iStrip interface {
String() string
GetMute() bool
@@ -19,20 +21,20 @@ type iStrip interface {
GetLabel() string
SetLabel(val string)
GetGain() float64
SetGain(val float32)
SetGain(val float64)
GetMc() bool
SetMc(val bool)
GetComp() float64
SetComp(val float32)
SetComp(val float64)
GetGate() float64
SetGate(val float32)
SetGate(val float64)
GetAudibility() float64
SetAudibility(val float32)
SetAudibility(val float64)
GainLayer() []gainLayer
Levels() *levels
FadeTo(target float32, time_ int)
FadeBy(change float32, time_ int)
AppGain(name string, gain float32)
FadeTo(target float64, time_ int)
FadeBy(change float64, time_ int)
AppGain(name string, gain float64)
AppMute(name string, val bool)
iOutputs
}
@@ -101,7 +103,7 @@ func (s *strip) GetGain() float64 {
}
// SetGain sets the value of the Gain parameter
func (s *strip) SetGain(val float32) {
func (s *strip) SetGain(val float64) {
s.setter_float("Gain", val)
}
@@ -116,18 +118,18 @@ func (s *strip) Levels() *levels {
}
// FadeTo sets the value of gain to target over at time interval of time_
func (s *strip) FadeTo(target float32, time_ int) {
func (s *strip) FadeTo(target float64, time_ int) {
s.setter_string("FadeTo", fmt.Sprintf("(\"%f\", %d)", target, time_))
time.Sleep(time.Millisecond)
}
// FadeBy adjusts the value of gain by change over a time interval of time_
func (s *strip) FadeBy(change float32, time_ int) {
func (s *strip) FadeBy(change float64, time_ int) {
s.setter_string("FadeBy", fmt.Sprintf("(\"%f\", %d)", change, time_))
time.Sleep(time.Millisecond)
}
//physicalStrip represents a single physical strip
// physicalStrip represents a single physical strip
type physicalStrip struct {
strip
}
@@ -155,7 +157,7 @@ func (p *physicalStrip) GetComp() float64 {
}
// SetComp sets the value of the Comp parameter
func (p *physicalStrip) SetComp(val float32) {
func (p *physicalStrip) SetComp(val float64) {
p.setter_float("Comp", val)
}
@@ -165,7 +167,7 @@ func (p *physicalStrip) GetGate() float64 {
}
// SetGate sets the value of the Gate parameter
func (p *physicalStrip) SetGate(val float32) {
func (p *physicalStrip) SetGate(val float64) {
p.setter_float("Gate", val)
}
@@ -175,21 +177,23 @@ func (p *physicalStrip) GetAudibility() float64 {
}
// SetAudibility sets the value of the Audibility parameter
func (p *physicalStrip) SetAudibility(val float32) {
func (p *physicalStrip) SetAudibility(val float64) {
p.setter_float("Audibility", val)
}
// GetMc panics reason invalid parameter
// GetMc logs a warning reason invalid parameter
// it always returns zero value
func (p *physicalStrip) GetMc() bool {
panic("invalid parameter MC for physicalStrip")
log.Warn("invalid parameter MC for physicalStrip")
return false
}
// SetMc panics reason invalid parameter
// SetMc logs a warning reason invalid parameter
func (p *physicalStrip) SetMc(val bool) {
panic("invalid parameter MC for physicalStrip")
log.Warn("invalid parameter MC for physicalStrip")
}
//virtualStrip represents a single virtual strip
// virtualStrip represents a single virtual strip
type virtualStrip struct {
strip
}
@@ -221,38 +225,44 @@ func (v *virtualStrip) SetMc(val bool) {
v.setter_bool("MC", val)
}
// GetComp panics reason invalid parameter
// GetComp logs a warning reason invalid parameter
// it always returns zero value
func (v *virtualStrip) GetComp() float64 {
panic("invalid parameter Comp for virtualStrip")
log.Warn("invalid parameter Comp for virtualStrip")
return 0
}
// SetComp panics reason invalid parameter
func (v *virtualStrip) SetComp(val float32) {
panic("invalid parameter Comp for virtualStrip")
// SetComp logs a warning reason invalid parameter
func (v *virtualStrip) SetComp(val float64) {
log.Warn("invalid parameter Comp for virtualStrip")
}
// GetGate panics reason invalid parameter
// GetGate logs a warning reason invalid parameter
// it always returns zero value
func (v *virtualStrip) GetGate() float64 {
panic("invalid parameter Gate for virtualStrip")
log.Warn("invalid parameter Gate for virtualStrip")
return 0
}
// SetGate panics reason invalid parameter
func (v *virtualStrip) SetGate(val float32) {
panic("invalid parameter Gate for virtualStrip")
// SetGate logs a warning reason invalid parameter
func (v *virtualStrip) SetGate(val float64) {
log.Warn("invalid parameter Gate for virtualStrip")
}
// GetAudibility panics reason invalid parameter
// GetAudibility logs a warning reason invalid parameter
// it always returns zero value
func (v *virtualStrip) GetAudibility() float64 {
panic("invalid parameter Audibility for virtualStrip")
log.Warn("invalid parameter Audibility for virtualStrip")
return 0
}
// SetAudibility panics reason invalid parameter
func (v *virtualStrip) SetAudibility(val float32) {
panic("invalid parameter Audibility for virtualStrip")
// SetAudibility logs a warning reason invalid parameter
func (v *virtualStrip) SetAudibility(val float64) {
log.Warn("invalid parameter Audibility for virtualStrip")
}
// AppGain sets the gain in db by val for the app matching name.
func (v *strip) AppGain(name string, val float32) {
func (v *strip) AppGain(name string, val float64) {
v.setter_string("AppGain", fmt.Sprintf("(\"%s\", %f)", name, val))
}
@@ -264,7 +274,7 @@ func (v *strip) AppMute(name string, val bool) {
} else {
value = 0
}
v.setter_string("AppMute", fmt.Sprintf("(\"%s\", %f)", name, float32(value)))
v.setter_string("AppMute", fmt.Sprintf("(\"%s\", %f)", name, float64(value)))
}
// gainLayer represents the 8 gainlayers for a single strip
@@ -284,7 +294,7 @@ func (gl *gainLayer) Get() float64 {
}
// Set sets the gain value for a single gainlayer
func (gl *gainLayer) Set(val float32) {
func (gl *gainLayer) Set(val float64) {
gl.setter_float(fmt.Sprintf("gainlayer[%d]", gl.index), val)
}
@@ -303,9 +313,9 @@ func newStripLevels(i int, k *kind) levels {
}
// PreFader returns the level values for this strip, PREFADER mode
func (l *levels) PreFader() []float32 {
func (l *levels) PreFader() []float64 {
_levelCache.stripMode = 0
var levels []float32
var levels []float64
for i := l.init; i < l.init+l.offset; i++ {
levels = append(levels, convertLevel(_levelCache.stripLevels[i]))
}
@@ -313,9 +323,9 @@ func (l *levels) PreFader() []float32 {
}
// PostFader returns the level values for this strip, POSTFADER mode
func (l *levels) PostFader() []float32 {
func (l *levels) PostFader() []float64 {
_levelCache.stripMode = 1
var levels []float32
var levels []float64
for i := l.init; i < l.init+l.offset; i++ {
levels = append(levels, convertLevel(_levelCache.stripLevels[i]))
}
@@ -323,9 +333,9 @@ func (l *levels) PostFader() []float32 {
}
// PostMute returns the level values for this strip, POSTMUTE mode
func (l *levels) PostMute() []float32 {
func (l *levels) PostMute() []float64 {
_levelCache.stripMode = 2
var levels []float32
var levels []float64
for i := l.init; i < l.init+l.offset; i++ {
levels = append(levels, convertLevel(_levelCache.stripLevels[i]))
}

View File

@@ -2,31 +2,25 @@ package voicemeeter_test
import (
"log"
"os"
"testing"
"time"
"github.com/onyx-and-iris/voicemeeter-api-go"
"github.com/onyx-and-iris/voicemeeter"
)
var (
vm, err = voicemeeter.NewRemote("potato")
vm, err = voicemeeter.NewRemote("potato", 30)
)
func TestMain(m *testing.M) {
if err != nil {
log.Fatal(err)
}
err = vm.Login()
if err != nil {
log.Fatal(err)
}
defer vm.Logout()
vm.Login()
code := m.Run()
vm.Logout()
os.Exit(code)
}
func sync() {
time.Sleep(30 * time.Millisecond)
for vm.Pdirty() || vm.Mdirty() {
}
m.Run()
}

View File

@@ -9,13 +9,11 @@ import (
func TestStrip0Mute(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[0].SetMute(true)
sync()
t.Run("Should return true when SetMute(true)", func(t *testing.T) {
assert.True(t, vm.Strip[0].GetMute())
})
vm.Strip[0].SetMute(false)
sync()
t.Run("Should return false when SetMute(false)", func(t *testing.T) {
assert.False(t, vm.Strip[0].GetMute())
})
@@ -24,13 +22,11 @@ func TestStrip0Mute(t *testing.T) {
func TestStrip3A1(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[3].SetA1(true)
sync()
t.Run("Should return true when SetA1(true)", func(t *testing.T) {
assert.True(t, vm.Strip[3].GetA1())
})
vm.Strip[3].SetA1(false)
sync()
t.Run("Should return false when SetA1(false)", func(t *testing.T) {
assert.False(t, vm.Strip[3].GetA1())
})
@@ -39,13 +35,11 @@ func TestStrip3A1(t *testing.T) {
func TestStrip2Limit(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[2].SetLimit(-8)
sync()
t.Run("Should return -8 when SetLimit(-8)", func(t *testing.T) {
assert.Equal(t, vm.Strip[2].GetLimit(), -8)
})
vm.Strip[2].SetLimit(-32)
sync()
t.Run("Should return -32 when SetLimit(-8)", func(t *testing.T) {
assert.Equal(t, vm.Strip[2].GetLimit(), -32)
})
@@ -55,13 +49,11 @@ func TestStrip2Limit(t *testing.T) {
func TestStrip4Label(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[4].SetLabel("test0")
sync()
t.Run("Should return test0 when SetLimit('test0')", func(t *testing.T) {
assert.Equal(t, "test0", vm.Strip[4].GetLabel())
})
vm.Strip[4].SetLabel("test1")
sync()
t.Run("Should return test1 when SetLimit('test1')", func(t *testing.T) {
assert.Equal(t, "test1", vm.Strip[4].GetLabel())
})
@@ -70,13 +62,11 @@ func TestStrip4Label(t *testing.T) {
func TestStrip5Gain(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[4].SetGain(-20.8)
sync()
t.Run("Should return -20.8 when SetGain(-20.8)", func(t *testing.T) {
assert.Equal(t, vm.Strip[4].GetGain(), -20.8)
})
vm.Strip[4].SetGain(-3.6)
sync()
t.Run("Should return -3.6 when SetGain(-3.6)", func(t *testing.T) {
assert.Equal(t, vm.Strip[4].GetGain(), -3.6)
})
@@ -85,13 +75,11 @@ func TestStrip5Gain(t *testing.T) {
func TestStrip3Comp(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[4].SetComp(8.1)
sync()
t.Run("Should return 8.1 when SetGain(8.1)", func(t *testing.T) {
assert.Equal(t, vm.Strip[4].GetComp(), 8.1)
})
vm.Strip[4].SetComp(1.6)
sync()
t.Run("Should return 1.6 when SetGain(1.6)", func(t *testing.T) {
assert.Equal(t, vm.Strip[4].GetComp(), 1.6)
})
@@ -100,13 +88,11 @@ func TestStrip3Comp(t *testing.T) {
func TestStrip5Mc(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[5].SetMc(true)
sync()
t.Run("Should return true when SetMc(true)", func(t *testing.T) {
assert.True(t, vm.Strip[5].GetMc())
})
vm.Strip[5].SetMc(false)
sync()
t.Run("Should return false when SetMc(false)", func(t *testing.T) {
assert.False(t, vm.Strip[5].GetMc())
})
@@ -115,13 +101,11 @@ func TestStrip5Mc(t *testing.T) {
func TestStrip2GainLayer3(t *testing.T) {
//t.Skip("skipping test")
vm.Strip[2].GainLayer()[3].Set(-18.3)
sync()
t.Run("Should return -18.3 when SetMc(true)", func(t *testing.T) {
assert.Equal(t, vm.Strip[2].GainLayer()[3].Get(), -18.3)
})
vm.Strip[2].GainLayer()[3].Set(-25.6)
sync()
t.Run("Should return -25.6 when SetMc(true)", func(t *testing.T) {
assert.Equal(t, vm.Strip[2].GainLayer()[3].Get(), -25.6)
})
@@ -130,13 +114,11 @@ func TestStrip2GainLayer3(t *testing.T) {
func TestBus3Eq(t *testing.T) {
//t.Skip("skipping test")
vm.Bus[3].SetEq(true)
sync()
t.Run("Should return true when SetEq(true)", func(t *testing.T) {
assert.True(t, vm.Bus[3].GetEq())
})
vm.Bus[3].SetEq(false)
sync()
t.Run("Should return false when SetEq(false)", func(t *testing.T) {
assert.False(t, vm.Bus[3].GetEq())
})
@@ -145,13 +127,11 @@ func TestBus3Eq(t *testing.T) {
func TestBus4Label(t *testing.T) {
//t.Skip("skipping test")
vm.Bus[4].SetLabel("test0")
sync()
t.Run("Should return test0 when SetEq('test0')", func(t *testing.T) {
assert.Equal(t, "test0", vm.Bus[4].GetLabel())
})
vm.Bus[4].SetLabel("test1")
sync()
t.Run("Should return test1 when SetEq('test1')", func(t *testing.T) {
assert.Equal(t, "test1", vm.Bus[4].GetLabel())
})
@@ -160,7 +140,6 @@ func TestBus4Label(t *testing.T) {
func TestBus3ModeAmix(t *testing.T) {
//t.Skip("skipping test")
vm.Bus[3].Mode().SetAmix(true)
sync()
t.Run("Should return true when Mode().SetAmix(true)", func(t *testing.T) {
assert.True(t, vm.Bus[3].Mode().GetAmix())
})
@@ -169,13 +148,11 @@ func TestBus3ModeAmix(t *testing.T) {
func TestVbanInStream0On(t *testing.T) {
//t.Skip("skipping test")
vm.Vban.InStream[0].SetOn(true)
sync()
t.Run("Should return true when SetOn(true)", func(t *testing.T) {
assert.True(t, vm.Vban.InStream[0].GetOn())
})
vm.Vban.InStream[0].SetOn(false)
sync()
t.Run("Should return false when SetOn(false)", func(t *testing.T) {
assert.False(t, vm.Vban.InStream[0].GetOn())
})
@@ -184,13 +161,11 @@ func TestVbanInStream0On(t *testing.T) {
func TestVbanOutStream6On(t *testing.T) {
//t.Skip("skipping test")
vm.Vban.OutStream[6].SetOn(true)
sync()
t.Run("Should return true when SetOn(true)", func(t *testing.T) {
assert.True(t, vm.Vban.OutStream[6].GetOn())
})
vm.Vban.OutStream[6].SetOn(false)
sync()
t.Run("Should return false when SetOn(false)", func(t *testing.T) {
assert.False(t, vm.Vban.OutStream[6].GetOn())
})
@@ -199,13 +174,11 @@ func TestVbanOutStream6On(t *testing.T) {
func TestVbanOutStream3Name(t *testing.T) {
t.Skip("skipping test")
vm.Vban.OutStream[3].SetName("test0")
sync()
t.Run("Should return test0 when SetName('test0')", func(t *testing.T) {
assert.Equal(t, "test0", vm.Vban.OutStream[3].GetName())
})
vm.Vban.OutStream[3].SetName("test1")
sync()
t.Run("Should return test1 when SetName('test1')", func(t *testing.T) {
assert.Equal(t, "test1", vm.Vban.OutStream[3].GetName())
})
@@ -226,13 +199,11 @@ func TestVbanInStream4Bit(t *testing.T) {
func TestVbanOutStream4Bit(t *testing.T) {
//t.Skip("skipping test")
vm.Vban.OutStream[4].SetBit(16)
sync()
t.Run("Should return 16 when SetBit(16)", func(t *testing.T) {
assert.Equal(t, vm.Vban.OutStream[4].GetBit(), 16)
})
vm.Vban.OutStream[4].SetBit(24)
sync()
t.Run("Should return 24 when SetBit(24)", func(t *testing.T) {
assert.Equal(t, vm.Vban.OutStream[4].GetBit(), 24)
})

View File

@@ -13,7 +13,7 @@ func allTrue(s []bool, sz int) bool {
}
// update copies the contents of one float slice into another
func update(s1 []float32, s2 []float32, sz int) {
func update(s1 []float64, s2 []float64, sz int) {
for i := 0; i < sz; i++ {
s1[i] = s2[i]
}
@@ -26,10 +26,10 @@ func roundFloat(val float64, precision uint) float64 {
}
// convertLevel performs the necessary math for a channel level
func convertLevel(i float32) float32 {
func convertLevel(i float64) float64 {
if i > 0 {
val := 20 * math.Log10(float64(i))
return float32(roundFloat(float64(val), 1))
val := 20 * math.Log10(i)
return roundFloat(val, 1)
}
return -200.0
}

View File

@@ -20,8 +20,8 @@ func TestAllTrue(t *testing.T) {
func TestUpdate(t *testing.T) {
//t.Skip("skipping test")
s1 := []float32{3.6, 8.7, 1.8, 18.2}
s2 := make([]float32, len(s1))
s1 := []float64{3.6, 8.7, 1.8, 18.2}
s2 := make([]float64, len(s1))
update(s2, s1, len(s1))
t.Run("Should return true", func(t *testing.T) {
assert.Equal(t, s1, s2)
@@ -32,10 +32,10 @@ func TestConvertLevel(t *testing.T) {
//t.Skip("skipping test")
res := convertLevel(0.02)
t.Run("Should be equal", func(t *testing.T) {
assert.Equal(t, float32(-34), res)
assert.Equal(t, float64(-34), res)
})
res = convertLevel(-0.02)
t.Run("Should be equal", func(t *testing.T) {
assert.Equal(t, float32(-200), res)
assert.Equal(t, float64(-200), res)
})
}

21
vban.go
View File

@@ -1,6 +1,10 @@
package voicemeeter
import "fmt"
import (
"fmt"
log "github.com/sirupsen/logrus"
)
// iVban defines the interface vban types must satisfy
type iVban interface {
@@ -105,7 +109,8 @@ func (v *vbanStream) SetBit(val int) {
case 24:
val = 2
default:
panic("expected value 16 or 24")
log.Warn("expected value 16 or 24")
return
}
v.setter_int("Bit", val)
}
@@ -139,19 +144,19 @@ func newVbanInStream(i int) iVban {
return iVban(&vbi)
}
// SetSr panics reason read only
// SetSr logs a warning reason read only
func (vbi *vbanInStream) SetSr(val int) {
panic("SR is readonly for vban instreams")
log.Warn("SR is readonly for vban instreams")
}
// SetChannel panics reason read only
// SetChannel logs a warning reason read only
func (vbi *vbanInStream) SetChannel(val int) {
panic("channel is readonly for vban instreams")
log.Warn("channel is readonly for vban instreams")
}
// SetBit panics reason read only
// SetBit logs a warning reason read only
func (vbi *vbanInStream) SetBit(val int) {
panic("bit is readonly for vban instreams")
log.Warn("bit is readonly for vban instreams")
}
type vbanOutStream struct {