mirror of
https://github.com/onyx-and-iris/voicemeeter.git
synced 2025-04-20 12:13:53 +01:00
Compare commits
No commits in common. "0bfc1e62ba60aa83d0bccc6f0e9c0ec89f48ade3" and "359c2d61b5724c2b6c39c6fbee40f1be71a5fa74" have entirely different histories.
0bfc1e62ba
...
359c2d61b5
@ -1,6 +1,6 @@
|
|||||||
## About
|
## About
|
||||||
|
|
||||||
A Voicemeeter CLI, offers ability to toggle, get and set parameters.
|
A simple voicemeeter-cli program. Offers ability to toggle, get and set parameters.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@ -8,32 +8,28 @@ First build and install it with `go install` (skip this step if using binary fro
|
|||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
Commands that begin with `!` will toggle a parameter, commands that contain `=` will set a parameter, all other commands will get a value.
|
Toggle with `!` prefix, get by excluding `=` and set by including `=`. Mix and match arguments.
|
||||||
|
|
||||||
You may pass the following optional flags:
|
You may pass the following optional flags:
|
||||||
|
|
||||||
- -h: Print the help message
|
- -v: (-verbose) to toggle console output.
|
||||||
- -i: Enable interactive mode
|
- -i: (-interactive) to toggle interactive mode.
|
||||||
- -k: The kind of Voicemeeter GUI to launch, defaults to Banana
|
- -k: (-kind) to set the kind of Voicemeeter. Defaults to banana.
|
||||||
- -l: Log level (0 up to 6), defaults to 3, Warn Level
|
- -d: (-delay) to set a delay on the getters. Defaults to 20ms.
|
||||||
- -d: Set the delay between commands, defaults to 20ms
|
|
||||||
- -v: Enable extra console output (toggle and set messages).
|
|
||||||
|
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
`vm-cli.exe -v -l=4 -k=potato strip[0].mute=0 strip[0].mute !strip[0].mute strip[0].mute bus[0].gain=-8.8 command.lock=1`
|
`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:
|
Expected output:
|
||||||
|
|
||||||
```
|
```
|
||||||
time="<timestamp>" level=info msg="Logged into Voicemeeter Potato v3.1.1.1"
|
Running command strip[0].mute=0
|
||||||
Setting strip[0].mute=0
|
Value of strip[0].mute is: 0
|
||||||
strip[0].mute: 0.00
|
|
||||||
Toggling strip[0].mute
|
Toggling strip[0].mute
|
||||||
strip[0].mute: 1.00
|
Value of strip[0].mute is: 1
|
||||||
Setting bus[0].gain=-8.8
|
Running command bus[0].gain=-8.8
|
||||||
Setting command.lock=1
|
Running command command.lock=1
|
||||||
time="<timestamp>" level=info msg="Logged out of Voicemeeter Potato"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If running in interactive mode enter `Q`, to exit.
|
If running in interactive mode enter `q`, `quit` or `<Enter>` to exit.
|
||||||
|
@ -4,36 +4,26 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/onyx-and-iris/voicemeeter/v2"
|
"github.com/onyx-and-iris/voicemeeter/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
type (
|
||||||
FLOAT = iota
|
verbosePrinter struct {
|
||||||
STRING
|
verbose bool
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type result struct {
|
|
||||||
kind int
|
|
||||||
stringParam string
|
|
||||||
floatParam float64
|
|
||||||
}
|
|
||||||
|
|
||||||
type verbosePrinter struct {
|
|
||||||
verbose bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newVerbosePrinter() *verbosePrinter {
|
func newVerbosePrinter() *verbosePrinter {
|
||||||
return &verbosePrinter{}
|
return &verbosePrinter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *verbosePrinter) printf(format string, a ...interface{}) {
|
func (v *verbosePrinter) printf(format string, a ...interface{}) {
|
||||||
if v.verbose {
|
if v.verbose {
|
||||||
fmt.Printf(format, a...)
|
fmt.Printf(format+"\n", a...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,68 +40,28 @@ func main() {
|
|||||||
kind string
|
kind string
|
||||||
delay int
|
delay int
|
||||||
interactive bool
|
interactive bool
|
||||||
loglevel int
|
|
||||||
help bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
|
|
||||||
flag.BoolVar(&help, "help", false, "print the help message")
|
|
||||||
flag.BoolVar(&help, "h", false, "print the help message (shorthand)")
|
|
||||||
flag.StringVar(&kind, "kind", "banana", "kind of voicemeeter")
|
flag.StringVar(&kind, "kind", "banana", "kind of voicemeeter")
|
||||||
flag.StringVar(&kind, "k", "banana", "kind of voicemeeter (shorthand)")
|
flag.StringVar(&kind, "k", "banana", "kind of voicemeeter (shorthand)")
|
||||||
flag.IntVar(&delay, "delay", 20, "delay between commands")
|
flag.IntVar(&delay, "delay", 20, "delay between commands")
|
||||||
flag.IntVar(&delay, "d", 20, "delay between commands (shorthand)")
|
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, "interactive", false, "toggle interactive mode")
|
||||||
flag.BoolVar(&interactive, "i", false, "toggle interactive mode (shorthand)")
|
flag.BoolVar(&interactive, "i", false, "toggle interactive mode (shorthand)")
|
||||||
flag.IntVar(&loglevel, "loglevel", int(log.WarnLevel), "set the log level")
|
|
||||||
flag.IntVar(&loglevel, "l", int(log.WarnLevel), "set the log level (shorthand)")
|
|
||||||
flag.BoolVar(&vPrinter.verbose, "verbose", false, "enable extra console output (toggle and set messages)")
|
|
||||||
flag.BoolVar(&vPrinter.verbose, "v", false, "enable extra console output (toggle and set messages) (shorthand)")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if help {
|
|
||||||
flag.Usage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if loglevel >= int(log.PanicLevel) && loglevel <= int(log.TraceLevel) {
|
|
||||||
log.SetLevel(log.Level(loglevel))
|
|
||||||
}
|
|
||||||
|
|
||||||
vm, err := vmConnect(kind, delay)
|
vm, err := vmConnect(kind, delay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer vm.Logout()
|
defer vm.Logout()
|
||||||
|
|
||||||
if interactive {
|
err = runCommands(vm, interactive)
|
||||||
interactiveMode(vm)
|
if err != nil {
|
||||||
return
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
args := flag.Args()
|
|
||||||
if len(args) == 0 {
|
|
||||||
flag.Usage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, arg := range args {
|
|
||||||
if err := parse(vm, arg); err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
fmt.Println("usage: ./vm-cli.exe [-h] [-i] [-k] [-l] [-d] [-v]\n" +
|
|
||||||
"Where:\n" +
|
|
||||||
"\th: Print the help message\n" +
|
|
||||||
"\ti: Enable interactive mode\n" +
|
|
||||||
"\tk: The kind of Voicemeeter GUI to launch, defaults to Banana\n" +
|
|
||||||
"\tl: Log level 0 up to 6, (defaults to 3, Warn Level)\n" +
|
|
||||||
"\td: Set the delay between commands (defaults to 20ms)\n" +
|
|
||||||
"\tv: Enable extra console output (toggle and set messages).")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func vmConnect(kind string, delay int) (*voicemeeter.Remote, error) {
|
func vmConnect(kind string, delay int) (*voicemeeter.Remote, error) {
|
||||||
@ -128,23 +78,38 @@ func vmConnect(kind string, delay int) (*voicemeeter.Remote, error) {
|
|||||||
return vm, nil
|
return vm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func interactiveMode(vm *voicemeeter.Remote) error {
|
func runCommands(vm *voicemeeter.Remote, interactive bool) error {
|
||||||
fmt.Println("Interactive mode enabled. Enter 'Q' to exit.")
|
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)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
fmt.Printf(">> ")
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
input := scanner.Text()
|
input := scanner.Text()
|
||||||
if strings.ToUpper(input) == "Q" {
|
if input == "q" || input == "quit" || input == "" {
|
||||||
break
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range strings.Split(input, " ") {
|
for _, cmd := range strings.Split(input, " ") {
|
||||||
if err := parse(vm, cmd); err != nil {
|
err := parse(vm, cmd)
|
||||||
log.Error(err.Error())
|
if err != nil {
|
||||||
|
vPrinter.printf(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf(">> ")
|
|
||||||
}
|
}
|
||||||
if scanner.Err() != nil {
|
if scanner.Err() != nil {
|
||||||
return scanner.Err()
|
return scanner.Err()
|
||||||
@ -154,60 +119,58 @@ func interactiveMode(vm *voicemeeter.Remote) error {
|
|||||||
|
|
||||||
func parse(vm *voicemeeter.Remote, cmd string) error {
|
func parse(vm *voicemeeter.Remote, cmd string) error {
|
||||||
if cmd[0] == '!' {
|
if cmd[0] == '!' {
|
||||||
if err := toggleCmd(vm, cmd[1:]); err != nil {
|
err := toggleCmd(vm, cmd[1:])
|
||||||
return err
|
if err != nil {
|
||||||
}
|
|
||||||
} else if strings.Contains(cmd, "=") {
|
|
||||||
if err := setCmd(vm, cmd); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r := result{kind: FLOAT}
|
if strings.Contains(cmd, "=") {
|
||||||
if err := getCmd(vm, cmd, &r); err != nil {
|
err := setCmd(vm, cmd)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
switch r.kind {
|
}
|
||||||
case FLOAT:
|
} else {
|
||||||
fmt.Printf("%s: %.2f\n", cmd, r.floatParam)
|
err := getCmd(vm, cmd)
|
||||||
case STRING:
|
if err != nil {
|
||||||
fmt.Printf("%s: %s\n", cmd, r.stringParam)
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleCmd(vm *voicemeeter.Remote, cmd string) error {
|
func toggleCmd(vm *voicemeeter.Remote, cmd string) error {
|
||||||
r := result{kind: FLOAT}
|
val, err := vm.GetFloat(cmd)
|
||||||
if err := getCmd(vm, cmd, &r); err != nil {
|
if err != nil {
|
||||||
|
err = fmt.Errorf("unable to toggle %s", cmd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if r.kind == FLOAT && (r.floatParam == 0 || r.floatParam == 1) {
|
vm.SetFloat(cmd, 1-val)
|
||||||
vPrinter.printf("Toggling %s\n", cmd)
|
vPrinter.printf("Toggling %s", cmd)
|
||||||
vm.SetFloat(cmd, 1-r.floatParam)
|
|
||||||
} else {
|
|
||||||
log.Warnf("%s does not appear to be a boolean parameter", cmd)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCmd(vm *voicemeeter.Remote, cmd string) error {
|
func setCmd(vm *voicemeeter.Remote, cmd string) error {
|
||||||
if err := vm.SendText(cmd); err != nil {
|
vPrinter.printf("Running command %s", cmd)
|
||||||
|
err := vm.SendText(cmd)
|
||||||
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to set %s", cmd)
|
err = fmt.Errorf("unable to set %s", cmd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
vPrinter.printf("Setting %s\n", cmd)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCmd(vm *voicemeeter.Remote, cmd string, r *result) error {
|
func getCmd(vm *voicemeeter.Remote, cmd string) error {
|
||||||
if val, err := vm.GetFloat(cmd); err == nil {
|
valF, err := vm.GetFloat(cmd)
|
||||||
r.floatParam = val
|
if err != nil {
|
||||||
} else if val, err := vm.GetString(cmd); err == nil {
|
valS, err := vm.GetString(cmd)
|
||||||
r.kind = STRING
|
if err != nil {
|
||||||
r.stringParam = val
|
err = fmt.Errorf("unable to get %s", cmd)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("Value of %s is: %s", cmd, valS)
|
||||||
} else {
|
} else {
|
||||||
err := fmt.Errorf("unknown parameter '%s'", cmd)
|
fmt.Printf("Value of %s is: %v", cmd, valF)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user