mirror of
https://github.com/onyx-and-iris/xair-cli.git
synced 2026-04-18 06:43:33 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 942d1b18bd | |||
| 2e1c28c909 | |||
| cf470181a1 | |||
| 873ff87429 | |||
| 376f3109ef | |||
| 9484f8e4f3 | |||
| a936a7e3db | |||
|
|
a0153f6b84 | ||
| 886c078f67 | |||
| 07ac73fbe4 | |||
| 23422f9641 | |||
| 3c47d12719 | |||
| 8a452c83b9 |
8
.pre-commit-config.yaml
Normal file
8
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: update-readme
|
||||||
|
name: update-readme
|
||||||
|
entry: python update_readme.py
|
||||||
|
language: python
|
||||||
|
pass_filenames: false
|
||||||
131
README.md
131
README.md
@@ -54,134 +54,14 @@ export X32_CLI_TIMEOUT=100ms
|
|||||||
export X32_CLI_LOGLEVEL=warn
|
export X32_CLI_LOGLEVEL=warn
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Use
|
### Use
|
||||||
|
|
||||||
```console
|
For each command/subcommand in the tree there exists a `--help` flag, use it to print usage information.
|
||||||
Usage: xair-cli <command> [flags]
|
|
||||||
|
|
||||||
A CLI to control Behringer X-Air mixers.
|
- [xair-cli](./xair-help.md)
|
||||||
|
- [x32-cli](./x32-help.md)
|
||||||
Flags:
|
|
||||||
-h, --help Show context-sensitive help.
|
|
||||||
-H, --host="mixer.local" The host of the X-Air device ($XAIR_CLI_HOST).
|
|
||||||
-P, --port=10024 The port of the X-Air device ($XAIR_CLI_PORT).
|
|
||||||
-T, --timeout=100ms Timeout for OSC operations ($XAIR_CLI_TIMEOUT).
|
|
||||||
-L, --loglevel="warn" Log level for the CLI ($XAIR_CLI_LOGLEVEL).
|
|
||||||
-v, --version Print xair-cli version information and quit
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
completion (c) Generate shell completion scripts.
|
|
||||||
|
|
||||||
Raw
|
|
||||||
raw Send raw OSC messages to the mixer.
|
|
||||||
|
|
||||||
Main
|
|
||||||
main mute Get or set the mute state of the Main L/R output.
|
|
||||||
main fader Get or set the fader level of the Main L/R output.
|
|
||||||
main fadein Fade in the Main L/R output over a specified duration.
|
|
||||||
main fadeout Fade out the Main L/R output over a specified duration.
|
|
||||||
main eq on Get or set the EQ on/off state of the Main L/R output.
|
|
||||||
main eq <band> gain Get or set the gain of the specified EQ band.
|
|
||||||
main eq <band> freq Get or set the frequency of the specified EQ band.
|
|
||||||
main eq <band> q Get or set the Q factor of the specified EQ band.
|
|
||||||
main eq <band> type Get or set the type of the specified EQ band.
|
|
||||||
main comp on Get or set the compressor on/off state of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp mode Get or set the compressor mode of the Main L/R output.
|
|
||||||
main comp threshold Get or set the compressor threshold of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp ratio Get or set the compressor ratio of the Main L/R output.
|
|
||||||
main comp mix Get or set the compressor mix level of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp makeup Get or set the compressor makeup gain of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp attack Get or set the compressor attack time of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp hold Get or set the compressor hold time of the Main L/R
|
|
||||||
output.
|
|
||||||
main comp release Get or set the compressor release time of the Main L/R
|
|
||||||
output.
|
|
||||||
|
|
||||||
Strip
|
|
||||||
strip <index> mute Get or set the mute state of the strip.
|
|
||||||
strip <index> fader Get or set the fader level of the strip.
|
|
||||||
strip <index> fadein Fade in the strip over a specified duration.
|
|
||||||
strip <index> fadeout Fade out the strip over a specified duration.
|
|
||||||
strip <index> send Get or set the send level for a specific bus.
|
|
||||||
strip <index> name Get or set the name of the strip.
|
|
||||||
strip <index> gate on Get or set the gate on/off state of the strip.
|
|
||||||
strip <index> gate mode Get or set the gate mode of the strip.
|
|
||||||
strip <index> gate threshold Get or set the gate threshold of the strip.
|
|
||||||
strip <index> gate range Get or set the gate range of the strip.
|
|
||||||
strip <index> gate attack Get or set the gate attack time of the strip.
|
|
||||||
strip <index> gate hold Get or set the gate hold time of the strip.
|
|
||||||
strip <index> gate release Get or set the gate release time of the strip.
|
|
||||||
strip <index> eq on Get or set the EQ on/off state of the strip.
|
|
||||||
strip <index> eq <band> gain Get or set the gain of the EQ band.
|
|
||||||
strip <index> eq <band> freq Get or set the frequency of the EQ band.
|
|
||||||
strip <index> eq <band> q Get or set the Q factor of the EQ band.
|
|
||||||
strip <index> eq <band> type Get or set the type of the EQ band.
|
|
||||||
strip <index> comp on Get or set the compressor on/off state of the
|
|
||||||
strip.
|
|
||||||
strip <index> comp mode Get or set the compressor mode of the strip.
|
|
||||||
strip <index> comp threshold Get or set the compressor threshold of the
|
|
||||||
strip.
|
|
||||||
strip <index> comp ratio Get or set the compressor ratio of the strip.
|
|
||||||
strip <index> comp mix Get or set the compressor mix of the strip.
|
|
||||||
strip <index> comp makeup Get or set the compressor makeup gain of the
|
|
||||||
strip.
|
|
||||||
strip <index> comp attack Get or set the compressor attack time of the
|
|
||||||
strip.
|
|
||||||
strip <index> comp hold Get or set the compressor hold time of the
|
|
||||||
strip.
|
|
||||||
strip <index> comp release Get or set the compressor release time of the
|
|
||||||
strip.
|
|
||||||
|
|
||||||
Bus
|
|
||||||
bus <index> mute Get or set the mute state of the bus.
|
|
||||||
bus <index> fader Get or set the fader level of the bus.
|
|
||||||
bus <index> fadein Fade in the bus over a specified duration.
|
|
||||||
bus <index> fadeout Fade out the bus over a specified duration.
|
|
||||||
bus <index> name Get or set the name of the bus.
|
|
||||||
bus <index> eq on Get or set the EQ on/off state of the bus.
|
|
||||||
bus <index> eq mode Get or set the EQ mode of the bus (peq, geq or
|
|
||||||
teq).
|
|
||||||
bus <index> eq <band> gain Get or set the gain of the EQ band.
|
|
||||||
bus <index> eq <band> freq Get or set the frequency of the EQ band.
|
|
||||||
bus <index> eq <band> q Get or set the Q factor of the EQ band.
|
|
||||||
bus <index> eq <band> type Get or set the type of the EQ band (lcut, lshv,
|
|
||||||
peq, veq, hshv, hcut).
|
|
||||||
bus <index> comp on Get or set the compressor on/off state of the
|
|
||||||
bus.
|
|
||||||
bus <index> comp mode Get or set the compressor mode of the bus (comp,
|
|
||||||
exp).
|
|
||||||
bus <index> comp threshold Get or set the compressor threshold of the bus
|
|
||||||
(in dB).
|
|
||||||
bus <index> comp ratio Get or set the compressor ratio of the bus.
|
|
||||||
bus <index> comp mix Get or set the compressor mix level of the bus
|
|
||||||
(in %).
|
|
||||||
bus <index> comp makeup Get or set the compressor makeup gain of the bus
|
|
||||||
(in dB).
|
|
||||||
bus <index> comp attack Get or set the compressor attack time of the bus
|
|
||||||
(in ms).
|
|
||||||
bus <index> comp hold Get or set the compressor hold time of the bus
|
|
||||||
(in ms).
|
|
||||||
bus <index> comp release Get or set the compressor release time of the
|
|
||||||
bus (in ms).
|
|
||||||
|
|
||||||
Headamp
|
|
||||||
headamp <index> gain Get or set the gain of the headamp.
|
|
||||||
headamp <index> phantom Get or set the phantom power state of the headamp.
|
|
||||||
|
|
||||||
Snapshot
|
|
||||||
snapshot list List all snapshots.
|
|
||||||
snapshot <index> name Get or set the name of a snapshot.
|
|
||||||
snapshot <index> save Save the current mixer state to a snapshot.
|
|
||||||
snapshot <index> load Load a mixer state from a snapshot.
|
|
||||||
snapshot <index> delete Delete a snapshot.
|
|
||||||
|
|
||||||
Run "xair-cli <command> --help" for more information on a command.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -231,6 +111,7 @@ xair-cli raw /ch/01/config/name
|
|||||||
xair-cli snapshot 20 save 'twitch live'
|
xair-cli snapshot 20 save 'twitch live'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
BIN_X32: x32-cli
|
WINDOWS: '{{.BIN_DIR}}/{{.PROGRAM}}_windows_amd64.exe'
|
||||||
|
LINUX: '{{.BIN_DIR}}/{{.PROGRAM}}_linux_amd64'
|
||||||
|
MACOS: '{{.BIN_DIR}}/{{.PROGRAM}}_darwin_amd64'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
windows-amd64:
|
windows-amd64:
|
||||||
desc: Build the x32-cli project for Windows
|
desc: Build the x32-cli project for Windows
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=windows GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_X32}}_windows_amd64.exe -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_X32}}
|
- GOOS=windows GOARCH=amd64 go build -o {{.WINDOWS}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|
||||||
linux-amd64:
|
linux-amd64:
|
||||||
desc: Build the x32-cli project for Linux
|
desc: Build the x32-cli project for Linux
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=linux GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_X32}}_linux_amd64 -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_X32}}
|
- GOOS=linux GOARCH=amd64 go build -o {{.LINUX}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|
||||||
darwin-amd64:
|
darwin-amd64:
|
||||||
desc: Build the x32-cli project for macOS
|
desc: Build the x32-cli project for macOS
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=darwin GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_X32}}_darwin_amd64 -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_X32}}
|
- GOOS=darwin GOARCH=amd64 go build -o {{.MACOS}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
BIN_XAIR: xair-cli
|
WINDOWS: '{{.BIN_DIR}}/{{.PROGRAM}}_windows_amd64.exe'
|
||||||
|
LINUX: '{{.BIN_DIR}}/{{.PROGRAM}}_linux_amd64'
|
||||||
|
MACOS: '{{.BIN_DIR}}/{{.PROGRAM}}_darwin_amd64'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
windows-amd64:
|
windows-amd64:
|
||||||
desc: Build the xair-cli project for Windows
|
desc: Build the xair-cli project for Windows
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=windows GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_XAIR}}_windows_amd64.exe -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_XAIR}}
|
- GOOS=windows GOARCH=amd64 go build -o {{.WINDOWS}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|
||||||
linux-amd64:
|
linux-amd64:
|
||||||
desc: Build the xair-cli project for Linux
|
desc: Build the xair-cli project for Linux
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=linux GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_XAIR}}_linux_amd64 -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_XAIR}}
|
- GOOS=linux GOARCH=amd64 go build -o {{.LINUX}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|
||||||
darwin-amd64:
|
darwin-amd64:
|
||||||
desc: Build the xair-cli project for macOS
|
desc: Build the xair-cli project for macOS
|
||||||
cmds:
|
cmds:
|
||||||
- GOOS=darwin GOARCH=amd64 go build -o {{.BIN_DIR}}/{{.BIN_XAIR}}_darwin_amd64 -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.BIN_XAIR}}
|
- GOOS=darwin GOARCH=amd64 go build -o {{.MACOS}} -ldflags="-X main.version={{.VERSION}}" ./cmd/{{.PROGRAM}}
|
||||||
internal: true
|
|
||||||
|
|||||||
24
Taskfile.yml
24
Taskfile.yml
@@ -1,8 +1,16 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
includes:
|
includes:
|
||||||
build-xair: ./Taskfile.build-xair.yml
|
build-xair:
|
||||||
build-x32: ./Taskfile.build-x32.yml
|
taskfile: ./Taskfile.build-xair.yml
|
||||||
|
internal: true
|
||||||
|
vars:
|
||||||
|
PROGRAM: xair-cli
|
||||||
|
build-x32:
|
||||||
|
taskfile: ./Taskfile.build-x32.yml
|
||||||
|
internal: true
|
||||||
|
vars:
|
||||||
|
PROGRAM: x32-cli
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
SHELL: '{{if eq .OS "Windows_NT"}}powershell{{end}}'
|
SHELL: '{{if eq .OS "Windows_NT"}}powershell{{end}}'
|
||||||
@@ -20,13 +28,11 @@ tasks:
|
|||||||
desc: Build the xair-cli and x32-cli projects for all platforms
|
desc: Build the xair-cli and x32-cli projects for all platforms
|
||||||
deps: [vet]
|
deps: [vet]
|
||||||
cmds:
|
cmds:
|
||||||
- task: build-xair:windows-amd64
|
- for:
|
||||||
- task: build-xair:linux-amd64
|
matrix:
|
||||||
- task: build-xair:darwin-amd64
|
PROGRAM: ['build-xair', 'build-x32']
|
||||||
|
TARGET: ['windows-amd64', 'linux-amd64', 'darwin-amd64']
|
||||||
- task: build-x32:windows-amd64
|
task: '{{.ITEM.PROGRAM}}:{{.ITEM.TARGET}}'
|
||||||
- task: build-x32:linux-amd64
|
|
||||||
- task: build-x32:darwin-amd64
|
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
desc: Vet the code
|
desc: Vet the code
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BusCmdGroup defines the commands related to controlling the buses of the X-Air device.
|
// BusCmdGroup defines the commands related to controlling the buses of the X-Air device.
|
||||||
@@ -183,9 +181,13 @@ type BusEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks that the provided EQ band number is within the valid range (1-6).
|
// Validate checks that the provided EQ band number is within the valid range (1-6).
|
||||||
func (cmd *BusEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *BusEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("EQ band number must be between 1 and 6")
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type CLI struct {
|
|||||||
Bus BusCmdGroup `help:"Control the buses." cmd:"" group:"Bus"`
|
Bus BusCmdGroup `help:"Control the buses." cmd:"" group:"Bus"`
|
||||||
Headamp HeadampCmdGroup `help:"Control input gain and phantom power." cmd:"" group:"Headamp"`
|
Headamp HeadampCmdGroup `help:"Control input gain and phantom power." cmd:"" group:"Headamp"`
|
||||||
Snapshot SnapshotCmdGroup `help:"Save and load mixer states." cmd:"" group:"Snapshot"`
|
Snapshot SnapshotCmdGroup `help:"Save and load mixer states." cmd:"" group:"Snapshot"`
|
||||||
|
Dca DCACmdGroup `help:"Control DCA groups." cmd:"" group:"DCA"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -121,7 +122,6 @@ func connect(config Config) (*xair.X32Client, error) {
|
|||||||
client, err := xair.NewX32Client(
|
client, err := xair.NewX32Client(
|
||||||
config.Host,
|
config.Host,
|
||||||
config.Port,
|
config.Port,
|
||||||
xair.WithKind("x32"),
|
|
||||||
xair.WithTimeout(config.Timeout),
|
xair.WithTimeout(config.Timeout),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
67
cmd/x32-cli/dca.go
Normal file
67
cmd/x32-cli/dca.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DCACmdGroup struct {
|
||||||
|
Index struct {
|
||||||
|
Index int `arg:"" help:"The index of the DCA group (1-8)."`
|
||||||
|
Mute DCAMuteCmd `help:"Get or set the mute status of the DCA group." cmd:""`
|
||||||
|
Name DCANameCmd `help:"Get or set the name of the DCA group." cmd:""`
|
||||||
|
} `arg:"" help:"Control a specific DCA group by its index."`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if the provided index is within the valid range.
|
||||||
|
func (cmd *DCACmdGroup) Validate() error {
|
||||||
|
if cmd.Index.Index < 1 || cmd.Index.Index > 8 {
|
||||||
|
return fmt.Errorf("DCA group index must be between 1 and 8, got %d", cmd.Index.Index)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCAMuteCmd is the command to get or set the mute status of a DCA group.
|
||||||
|
type DCAMuteCmd struct {
|
||||||
|
State *string `arg:"" help:"Set the mute status of the DCA group." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the DCAMuteCmd command.
|
||||||
|
func (cmd *DCAMuteCmd) Run(ctx *context, dca *DCACmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.DCA.Mute(dca.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get DCA mute status: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "DCA Group %d mute state: %t\n", dca.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.DCA.SetMute(dca.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set DCA mute status: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCANameCmd is the command to get or set the name of a DCA group.
|
||||||
|
type DCANameCmd struct {
|
||||||
|
Name *string `arg:"" help:"Set the name of the DCA group." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the DCANameCmd command.
|
||||||
|
func (cmd *DCANameCmd) Run(ctx *context, dca *DCACmdGroup) error {
|
||||||
|
if cmd.Name == nil {
|
||||||
|
resp, err := ctx.Client.DCA.Name(dca.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get DCA name: %w", err)
|
||||||
|
}
|
||||||
|
if resp == "" {
|
||||||
|
resp = fmt.Sprintf("DCA %d", dca.Index.Index)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "DCA Group %d is named '%s'\n", dca.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := ctx.Client.DCA.SetName(dca.Index.Index, *cmd.Name); err != nil {
|
||||||
|
return fmt.Errorf("failed to set DCA name: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MainCmdGroup defines the command group for controlling the Main L/R output, including commands for mute state, fader level, and fade-in/fade-out times.
|
// MainCmdGroup defines the command group for controlling the Main L/R output, including commands for mute state, fader level, and fade-in/fade-out times.
|
||||||
@@ -146,9 +144,13 @@ type MainEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main L/R output.
|
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main L/R output.
|
||||||
func (cmd *MainEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *MainEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("invalid EQ band number: %d. Valid range is 1-6", cmd.Band.Band)
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MainMonoCmdGroup defines the command group for controlling the Main Mono output, including commands for mute state, fader level, and fade-in/fade-out times.
|
// MainMonoCmdGroup defines the command group for controlling the Main Mono output, including commands for mute state, fader level, and fade-in/fade-out times.
|
||||||
@@ -146,9 +144,13 @@ type MainMonoEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main Mono output.
|
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main Mono output.
|
||||||
func (cmd *MainMonoEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *MainMonoEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("invalid EQ band number: %d. Valid range is 1-6", cmd.Band.Band)
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MatrixCmdGroup defines the command group for controlling the Matrix outputs, including commands for mute state, fader level, and fade-in/fade-out times.
|
// MatrixCmdGroup defines the command group for controlling the Matrix outputs, including commands for mute state, fader level, and fade-in/fade-out times.
|
||||||
@@ -22,9 +20,9 @@ type MatrixCmdGroup struct {
|
|||||||
} `help:"Commands for controlling individual Matrix outputs." arg:""`
|
} `help:"Commands for controlling individual Matrix outputs." arg:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *MatrixCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *MatrixCmdGroup) Validate() error {
|
||||||
if cmd.Index.Index < 1 || cmd.Index.Index > 6 {
|
if cmd.Index.Index < 1 || cmd.Index.Index > 6 {
|
||||||
return fmt.Errorf("invalid Matrix output index: %d. Valid range is 1-6", cmd.Index.Index)
|
return fmt.Errorf("Matrix output index must be between 1 and 6, got %d", cmd.Index.Index)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -156,9 +154,13 @@ type MatrixEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Matrix output.
|
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Matrix output.
|
||||||
func (cmd *MatrixEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *MatrixEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("invalid EQ band number: %d. Valid range is 1-6", cmd.Band.Band)
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StripCmdGroup defines the command group for controlling the strips of the mixer, including commands for getting and setting various parameters such as mute state, fader level, send levels, and EQ settings.
|
// StripCmdGroup defines the command group for controlling the strips of the mixer, including commands for getting and setting various parameters such as mute state, fader level, send levels, and EQ settings.
|
||||||
@@ -374,9 +372,13 @@ type StripEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is valid (between 1 and 4) and returns an error if it is not.
|
// Validate checks if the provided EQ band number is valid (between 1 and 4) and returns an error if it is not.
|
||||||
func (cmd *StripEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *StripEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 4 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 4 {
|
||||||
return fmt.Errorf("EQ band number must be between 1 and 4")
|
return fmt.Errorf("EQ band number must be between 1 and 4, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BusCmdGroup defines the commands related to controlling the buses of the X-Air device.
|
// BusCmdGroup defines the commands related to controlling the buses of the X-Air device.
|
||||||
@@ -183,9 +181,14 @@ type BusEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks that the provided EQ band number is within the valid range (1-6).
|
// Validate checks that the provided EQ band number is within the valid range (1-6).
|
||||||
func (cmd *BusEqCmdGroup) Validate(ctx kong.Context) error {
|
// Only validates when a band number is actually specified (non-zero).
|
||||||
|
func (cmd *BusEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("EQ band number must be between 1 and 6")
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ type CLI struct {
|
|||||||
Bus BusCmdGroup `help:"Control the buses." cmd:"" group:"Bus"`
|
Bus BusCmdGroup `help:"Control the buses." cmd:"" group:"Bus"`
|
||||||
Headamp HeadampCmdGroup `help:"Control input gain and phantom power." cmd:"" group:"Headamp"`
|
Headamp HeadampCmdGroup `help:"Control input gain and phantom power." cmd:"" group:"Headamp"`
|
||||||
Snapshot SnapshotCmdGroup `help:"Save and load mixer states." cmd:"" group:"Snapshot"`
|
Snapshot SnapshotCmdGroup `help:"Save and load mixer states." cmd:"" group:"Snapshot"`
|
||||||
|
Dca DCACmdGroup `help:"Control DCA groups." cmd:"" group:"DCA"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -119,7 +120,6 @@ func connect(config Config) (*xair.XAirClient, error) {
|
|||||||
client, err := xair.NewXAirClient(
|
client, err := xair.NewXAirClient(
|
||||||
config.Host,
|
config.Host,
|
||||||
config.Port,
|
config.Port,
|
||||||
xair.WithKind("xair"),
|
|
||||||
xair.WithTimeout(config.Timeout),
|
xair.WithTimeout(config.Timeout),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
68
cmd/xair-cli/dca.go
Normal file
68
cmd/xair-cli/dca.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DCACmdGroup is the command group for controlling DCA groups.
|
||||||
|
type DCACmdGroup struct {
|
||||||
|
Index struct {
|
||||||
|
Index int `arg:"" help:"The index of the DCA group (1-4)."`
|
||||||
|
Mute DCAMuteCmd `help:"Get or set the mute status of the DCA group." cmd:""`
|
||||||
|
Name DCANameCmd `help:"Get or set the name of the DCA group." cmd:""`
|
||||||
|
} `arg:"" help:"Control a specific DCA group by its index."`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if the provided index is within the valid range.
|
||||||
|
func (cmd *DCACmdGroup) Validate() error {
|
||||||
|
if cmd.Index.Index < 1 || cmd.Index.Index > 4 {
|
||||||
|
return fmt.Errorf("DCA group index must be between 1 and 4, got %d", cmd.Index.Index)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCAMuteCmd is the command to get or set the mute status of a DCA group.
|
||||||
|
type DCAMuteCmd struct {
|
||||||
|
State *string `arg:"" help:"Set the mute status of the DCA group." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the DCAMuteCmd command.
|
||||||
|
func (cmd *DCAMuteCmd) Run(ctx *context, dca *DCACmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.DCA.Mute(dca.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get DCA mute status: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "DCA Group %d mute state: %t\n", dca.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.DCA.SetMute(dca.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set DCA mute status: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCANameCmd is the command to get or set the name of a DCA group.
|
||||||
|
type DCANameCmd struct {
|
||||||
|
Name *string `arg:"" help:"Set the name of the DCA group." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the DCANameCmd command.
|
||||||
|
func (cmd *DCANameCmd) Run(ctx *context, dca *DCACmdGroup) error {
|
||||||
|
if cmd.Name == nil {
|
||||||
|
resp, err := ctx.Client.DCA.Name(dca.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get DCA name: %w", err)
|
||||||
|
}
|
||||||
|
if resp == "" {
|
||||||
|
resp = fmt.Sprintf("DCA %d", dca.Index.Index)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "DCA Group %d is named '%s'\n", dca.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := ctx.Client.DCA.SetName(dca.Index.Index, *cmd.Name); err != nil {
|
||||||
|
return fmt.Errorf("failed to set DCA name: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MainCmdGroup defines the command group for controlling the Main L/R output, including commands for mute state, fader level, and fade-in/fade-out times.
|
// MainCmdGroup defines the command group for controlling the Main L/R output, including commands for mute state, fader level, and fade-in/fade-out times.
|
||||||
@@ -146,9 +144,13 @@ type MainEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main L/R output.
|
// Validate checks if the provided EQ band number is within the valid range (1-6) for the Main L/R output.
|
||||||
func (cmd *MainEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *MainEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
return fmt.Errorf("invalid EQ band number: %d. Valid range is 1-6", cmd.Band.Band)
|
return fmt.Errorf("EQ band number must be between 1 and 6, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StripCmdGroup defines the command group for controlling the strips of the mixer, including commands for getting and setting various parameters such as mute state, fader level, send levels, and EQ settings.
|
// StripCmdGroup defines the command group for controlling the strips of the mixer, including commands for getting and setting various parameters such as mute state, fader level, send levels, and EQ settings.
|
||||||
@@ -374,9 +372,13 @@ type StripEqCmdGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the provided EQ band number is valid (between 1 and 4) and returns an error if it is not.
|
// Validate checks if the provided EQ band number is valid (between 1 and 4) and returns an error if it is not.
|
||||||
func (cmd *StripEqCmdGroup) Validate(ctx kong.Context) error {
|
func (cmd *StripEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.Band.Band < 1 || cmd.Band.Band > 4 {
|
if cmd.Band.Band < 1 || cmd.Band.Band > 4 {
|
||||||
return fmt.Errorf("EQ band number must be between 1 and 4")
|
return fmt.Errorf("EQ band number must be between 1 and 4, got %d", cmd.Band.Band)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
10
go.mod
10
go.mod
@@ -3,7 +3,7 @@ module github.com/onyx-and-iris/xair-cli
|
|||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/kong v1.13.0
|
github.com/alecthomas/kong v1.14.0
|
||||||
github.com/charmbracelet/log v0.4.2
|
github.com/charmbracelet/log v0.4.2
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5
|
||||||
github.com/jotaen/kong-completion v0.0.11
|
github.com/jotaen/kong-completion v0.0.11
|
||||||
@@ -13,12 +13,12 @@ require (
|
|||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.4.1 // indirect
|
github.com/charmbracelet/colorprofile v0.4.1 // indirect
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.11.4 // indirect
|
github.com/charmbracelet/x/ansi v0.11.6 // indirect
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
|
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
||||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
@@ -31,5 +31,5 @@ require (
|
|||||||
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
|
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
20
go.sum
20
go.sum
@@ -1,7 +1,7 @@
|
|||||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
github.com/alecthomas/kong v1.13.0 h1:5e/7XC3ugvhP1DQBmTS+WuHtCbcv44hsohMgcvVxSrA=
|
github.com/alecthomas/kong v1.14.0 h1:gFgEUZWu2ZmZ+UhyZ1bDhuutbKN1nTtJTwh19Wsn21s=
|
||||||
github.com/alecthomas/kong v1.13.0/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I=
|
github.com/alecthomas/kong v1.14.0/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I=
|
||||||
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||||
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
@@ -12,18 +12,18 @@ github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoF
|
|||||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||||
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
||||||
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
||||||
github.com/charmbracelet/x/ansi v0.11.4 h1:6G65PLu6HjmE858CnTUQY1LXT3ZUWwfvqEROLF8vqHI=
|
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
|
||||||
github.com/charmbracelet/x/ansi v0.11.4/go.mod h1:/5AZ+UfWExW3int5H5ugnsG/PWjNcSQcwYsHBlPFQN4=
|
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
|
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
|
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
|
||||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||||
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
|
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
|
||||||
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
|
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
|
||||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos=
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -68,8 +68,8 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu
|
|||||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
||||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ package xair
|
|||||||
var xairAddressMap = map[string]string{
|
var xairAddressMap = map[string]string{
|
||||||
"main": "/lr",
|
"main": "/lr",
|
||||||
"strip": "/ch/%02d",
|
"strip": "/ch/%02d",
|
||||||
"bus": "/bus/%01d",
|
"bus": "/bus/%d",
|
||||||
"headamp": "/headamp/%02d",
|
"headamp": "/headamp/%02d",
|
||||||
"snapshot": "/-snap",
|
"snapshot": "/-snap",
|
||||||
|
"dca": "/dca/%d",
|
||||||
}
|
}
|
||||||
|
|
||||||
var x32AddressMap = map[string]string{
|
var x32AddressMap = map[string]string{
|
||||||
@@ -16,11 +17,12 @@ var x32AddressMap = map[string]string{
|
|||||||
"bus": "/bus/%02d",
|
"bus": "/bus/%02d",
|
||||||
"headamp": "/headamp/%03d",
|
"headamp": "/headamp/%03d",
|
||||||
"snapshot": "/-snap",
|
"snapshot": "/-snap",
|
||||||
|
"dca": "/dca/%d",
|
||||||
}
|
}
|
||||||
|
|
||||||
func addressMapForMixerKind(kind MixerKind) map[string]string {
|
func addressMapFromMixerKind(kind mixerKind) map[string]string {
|
||||||
switch kind {
|
switch kind {
|
||||||
case KindX32:
|
case kindX32:
|
||||||
return x32AddressMap
|
return x32AddressMap
|
||||||
default:
|
default:
|
||||||
return xairAddressMap
|
return xairAddressMap
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ type Bus struct {
|
|||||||
Comp *Comp
|
Comp *Comp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newBus creates a new Bus instance
|
||||||
func newBus(c *Client) *Bus {
|
func newBus(c *Client) *Bus {
|
||||||
return &Bus{
|
return &Bus{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["bus"],
|
baseAddress: c.addressMap["bus"],
|
||||||
Eq: newEqForBus(c),
|
Eq: newEq(c, c.addressMap["bus"]),
|
||||||
Comp: newCompForBus(c),
|
Comp: newComp(c, c.addressMap["bus"]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package xair
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
@@ -11,9 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
engine
|
*engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XAirClient is a client for controlling XAir mixers
|
||||||
type XAirClient struct {
|
type XAirClient struct {
|
||||||
Client
|
Client
|
||||||
Main *Main
|
Main *Main
|
||||||
@@ -21,8 +21,10 @@ type XAirClient struct {
|
|||||||
Bus *Bus
|
Bus *Bus
|
||||||
HeadAmp *HeadAmp
|
HeadAmp *HeadAmp
|
||||||
Snapshot *Snapshot
|
Snapshot *Snapshot
|
||||||
|
DCA *DCA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// X32Client is a client for controlling X32 mixers
|
||||||
type X32Client struct {
|
type X32Client struct {
|
||||||
Client
|
Client
|
||||||
Main *Main
|
Main *Main
|
||||||
@@ -32,52 +34,18 @@ type X32Client struct {
|
|||||||
Bus *Bus
|
Bus *Bus
|
||||||
HeadAmp *HeadAmp
|
HeadAmp *HeadAmp
|
||||||
Snapshot *Snapshot
|
Snapshot *Snapshot
|
||||||
|
DCA *DCA
|
||||||
}
|
}
|
||||||
|
|
||||||
func createEngine(mixerIP string, mixerPort int, opts ...Option) (*engine, error) {
|
// NewX32Client creates a new X32Client instance with optional engine configuration
|
||||||
localAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", 0))
|
func NewX32Client(mixerIP string, mixerPort int, opts ...EngineOption) (*X32Client, error) {
|
||||||
if err != nil {
|
e, err := newEngine(mixerIP, mixerPort, kindX32, opts...)
|
||||||
return nil, fmt.Errorf("failed to resolve local address: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := net.ListenUDP("udp", localAddr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create UDP connection: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mixerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", mixerIP, mixerPort))
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, fmt.Errorf("failed to resolve mixer address: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Local UDP connection: %s ", conn.LocalAddr().String())
|
|
||||||
|
|
||||||
e := &engine{
|
|
||||||
timeout: 100 * time.Millisecond,
|
|
||||||
conn: conn,
|
|
||||||
mixerAddr: mixerAddr,
|
|
||||||
parser: newParser(),
|
|
||||||
done: make(chan bool),
|
|
||||||
respChan: make(chan *osc.Message, 100),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
return e, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewX32Client creates a new X32Client instance
|
|
||||||
func NewX32Client(mixerIP string, mixerPort int, opts ...Option) (*X32Client, error) {
|
|
||||||
e, err := createEngine(mixerIP, mixerPort, opts...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &X32Client{
|
c := &X32Client{
|
||||||
Client: Client{*e},
|
Client: Client{e},
|
||||||
}
|
}
|
||||||
c.Main = newMainStereo(&c.Client)
|
c.Main = newMainStereo(&c.Client)
|
||||||
c.MainMono = newMainMono(&c.Client)
|
c.MainMono = newMainMono(&c.Client)
|
||||||
@@ -86,25 +54,27 @@ func NewX32Client(mixerIP string, mixerPort int, opts ...Option) (*X32Client, er
|
|||||||
c.Bus = newBus(&c.Client)
|
c.Bus = newBus(&c.Client)
|
||||||
c.HeadAmp = newHeadAmp(&c.Client)
|
c.HeadAmp = newHeadAmp(&c.Client)
|
||||||
c.Snapshot = newSnapshot(&c.Client)
|
c.Snapshot = newSnapshot(&c.Client)
|
||||||
|
c.DCA = newDCA(&c.Client)
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewXAirClient creates a new XAirClient instance
|
// NewXAirClient creates a new XAirClient instance with optional engine configuration
|
||||||
func NewXAirClient(mixerIP string, mixerPort int, opts ...Option) (*XAirClient, error) {
|
func NewXAirClient(mixerIP string, mixerPort int, opts ...EngineOption) (*XAirClient, error) {
|
||||||
e, err := createEngine(mixerIP, mixerPort, opts...)
|
e, err := newEngine(mixerIP, mixerPort, kindXAir, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &XAirClient{
|
c := &XAirClient{
|
||||||
Client: Client{*e},
|
Client: Client{e},
|
||||||
}
|
}
|
||||||
c.Main = newMainStereo(&c.Client)
|
c.Main = newMainStereo(&c.Client)
|
||||||
c.Strip = newStrip(&c.Client)
|
c.Strip = newStrip(&c.Client)
|
||||||
c.Bus = newBus(&c.Client)
|
c.Bus = newBus(&c.Client)
|
||||||
c.HeadAmp = newHeadAmp(&c.Client)
|
c.HeadAmp = newHeadAmp(&c.Client)
|
||||||
c.Snapshot = newSnapshot(&c.Client)
|
c.Snapshot = newSnapshot(&c.Client)
|
||||||
|
c.DCA = newDCA(&c.Client)
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,53 +2,31 @@ package xair
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// Comp represents the compressor parameters.
|
||||||
type Comp struct {
|
type Comp struct {
|
||||||
client *Client
|
client *Client
|
||||||
baseAddress string
|
baseAddress string
|
||||||
AddressFunc func(fmtString string, args ...any) string
|
AddressFunc func(fmtString string, args ...any) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Factory function to create Comp instance for Main
|
// Factory function to create Comp instance with optional configuration
|
||||||
func newCompForMain(c *Client) *Comp {
|
func newComp(c *Client, baseAddress string, opts ...CompOption) *Comp {
|
||||||
return &Comp{
|
comp := &Comp{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["main"],
|
baseAddress: fmt.Sprintf("%s/dyn", baseAddress),
|
||||||
AddressFunc: func(fmtString string, args ...any) string {
|
|
||||||
return fmtString
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Comp instance for Strip
|
|
||||||
func newCompForStrip(c *Client) *Comp {
|
|
||||||
return &Comp{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["strip"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
AddressFunc: fmt.Sprintf,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Comp instance for Bus
|
for _, opt := range opts {
|
||||||
func newCompForBus(c *Client) *Comp {
|
opt(comp)
|
||||||
return &Comp{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["bus"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Comp instance for Matrix
|
return comp
|
||||||
func newCompForMatrix(c *Client) *Comp {
|
|
||||||
return &Comp{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["matrix"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// On retrieves the on/off status of the Compressor for a specific strip or bus (1-based indexing).
|
// On retrieves the on/off status of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) On(index int) (bool, error) {
|
func (c *Comp) On(index int) (bool, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/on"
|
address := c.AddressFunc(c.baseAddress, index) + "/on"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -67,7 +45,7 @@ func (c *Comp) On(index int) (bool, error) {
|
|||||||
|
|
||||||
// SetOn sets the on/off status of the Compressor for a specific strip or bus (1-based indexing).
|
// SetOn sets the on/off status of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetOn(index int, on bool) error {
|
func (c *Comp) SetOn(index int, on bool) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/on"
|
address := c.AddressFunc(c.baseAddress, index) + "/on"
|
||||||
var value int32
|
var value int32
|
||||||
if on {
|
if on {
|
||||||
value = 1
|
value = 1
|
||||||
@@ -77,7 +55,7 @@ func (c *Comp) SetOn(index int, on bool) error {
|
|||||||
|
|
||||||
// Mode retrieves the current mode of the Compressor for a specific strip or bus (1-based indexing).
|
// Mode retrieves the current mode of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Mode(index int) (string, error) {
|
func (c *Comp) Mode(index int) (string, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mode"
|
address := c.AddressFunc(c.baseAddress, index) + "/mode"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -98,14 +76,14 @@ func (c *Comp) Mode(index int) (string, error) {
|
|||||||
|
|
||||||
// SetMode sets the mode of the Compressor for a specific strip or bus (1-based indexing).
|
// SetMode sets the mode of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetMode(index int, mode string) error {
|
func (c *Comp) SetMode(index int, mode string) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mode"
|
address := c.AddressFunc(c.baseAddress, index) + "/mode"
|
||||||
possibleModes := []string{"comp", "exp"}
|
possibleModes := []string{"comp", "exp"}
|
||||||
return c.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
return c.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Threshold retrieves the threshold value of the Compressor for a specific strip or bus (1-based indexing).
|
// Threshold retrieves the threshold value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Threshold(index int) (float64, error) {
|
func (c *Comp) Threshold(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/thr"
|
address := c.AddressFunc(c.baseAddress, index) + "/thr"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -124,13 +102,13 @@ func (c *Comp) Threshold(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetThreshold sets the threshold value of the Compressor for a specific strip or bus (1-based indexing).
|
// SetThreshold sets the threshold value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetThreshold(index int, threshold float64) error {
|
func (c *Comp) SetThreshold(index int, threshold float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/thr"
|
address := c.AddressFunc(c.baseAddress, index) + "/thr"
|
||||||
return c.client.SendMessage(address, float32(linSet(-60, 0, threshold)))
|
return c.client.SendMessage(address, float32(linSet(-60, 0, threshold)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ratio retrieves the ratio value of the Compressor for a specific strip or bus (1-based indexing).
|
// Ratio retrieves the ratio value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Ratio(index int) (float32, error) {
|
func (c *Comp) Ratio(index int) (float32, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/ratio"
|
address := c.AddressFunc(c.baseAddress, index) + "/ratio"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -152,7 +130,7 @@ func (c *Comp) Ratio(index int) (float32, error) {
|
|||||||
|
|
||||||
// SetRatio sets the ratio value of the Compressor for a specific strip or bus (1-based indexing).
|
// SetRatio sets the ratio value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetRatio(index int, ratio float64) error {
|
func (c *Comp) SetRatio(index int, ratio float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/ratio"
|
address := c.AddressFunc(c.baseAddress, index) + "/ratio"
|
||||||
possibleValues := []float32{1.1, 1.3, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 7.0, 10, 20, 100}
|
possibleValues := []float32{1.1, 1.3, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 7.0, 10, 20, 100}
|
||||||
|
|
||||||
return c.client.SendMessage(address, int32(indexOf(possibleValues, float32(ratio))))
|
return c.client.SendMessage(address, int32(indexOf(possibleValues, float32(ratio))))
|
||||||
@@ -160,7 +138,7 @@ func (c *Comp) SetRatio(index int, ratio float64) error {
|
|||||||
|
|
||||||
// Attack retrieves the attack time of the Compressor for a specific strip or bus (1-based indexing).
|
// Attack retrieves the attack time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Attack(index int) (float64, error) {
|
func (c *Comp) Attack(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/attack"
|
address := c.AddressFunc(c.baseAddress, index) + "/attack"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -179,13 +157,13 @@ func (c *Comp) Attack(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetAttack sets the attack time of the Compressor for a specific strip or bus (1-based indexing).
|
// SetAttack sets the attack time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetAttack(index int, attack float64) error {
|
func (c *Comp) SetAttack(index int, attack float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/attack"
|
address := c.AddressFunc(c.baseAddress, index) + "/attack"
|
||||||
return c.client.SendMessage(address, float32(linSet(0, 120, attack)))
|
return c.client.SendMessage(address, float32(linSet(0, 120, attack)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hold retrieves the hold time of the Compressor for a specific strip or bus (1-based indexing).
|
// Hold retrieves the hold time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Hold(index int) (float64, error) {
|
func (c *Comp) Hold(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/hold"
|
address := c.AddressFunc(c.baseAddress, index) + "/hold"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -204,13 +182,13 @@ func (c *Comp) Hold(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetHold sets the hold time of the Compressor for a specific strip or bus (1-based indexing).
|
// SetHold sets the hold time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetHold(index int, hold float64) error {
|
func (c *Comp) SetHold(index int, hold float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/hold"
|
address := c.AddressFunc(c.baseAddress, index) + "/hold"
|
||||||
return c.client.SendMessage(address, float32(logSet(0.02, 2000, hold)))
|
return c.client.SendMessage(address, float32(logSet(0.02, 2000, hold)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release retrieves the release time of the Compressor for a specific strip or bus (1-based indexing).
|
// Release retrieves the release time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Release(index int) (float64, error) {
|
func (c *Comp) Release(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/release"
|
address := c.AddressFunc(c.baseAddress, index) + "/release"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -229,13 +207,13 @@ func (c *Comp) Release(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetRelease sets the release time of the Compressor for a specific strip or bus (1-based indexing).
|
// SetRelease sets the release time of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetRelease(index int, release float64) error {
|
func (c *Comp) SetRelease(index int, release float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/release"
|
address := c.AddressFunc(c.baseAddress, index) + "/release"
|
||||||
return c.client.SendMessage(address, float32(logSet(4, 4000, release)))
|
return c.client.SendMessage(address, float32(logSet(4, 4000, release)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makeup retrieves the makeup gain of the Compressor for a specific strip or bus (1-based indexing).
|
// Makeup retrieves the makeup gain of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Makeup(index int) (float64, error) {
|
func (c *Comp) Makeup(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mgain"
|
address := c.AddressFunc(c.baseAddress, index) + "/mgain"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -254,13 +232,13 @@ func (c *Comp) Makeup(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetMakeup sets the makeup gain of the Compressor for a specific strip or bus (1-based indexing).
|
// SetMakeup sets the makeup gain of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetMakeup(index int, makeup float64) error {
|
func (c *Comp) SetMakeup(index int, makeup float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mgain"
|
address := c.AddressFunc(c.baseAddress, index) + "/mgain"
|
||||||
return c.client.SendMessage(address, float32(linSet(0, 24, makeup)))
|
return c.client.SendMessage(address, float32(linSet(0, 24, makeup)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mix retrieves the mix value of the Compressor for a specific strip or bus (1-based indexing).
|
// Mix retrieves the mix value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) Mix(index int) (float64, error) {
|
func (c *Comp) Mix(index int) (float64, error) {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mix"
|
address := c.AddressFunc(c.baseAddress, index) + "/mix"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -279,6 +257,6 @@ func (c *Comp) Mix(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetMix sets the mix value of the Compressor for a specific strip or bus (1-based indexing).
|
// SetMix sets the mix value of the Compressor for a specific strip or bus (1-based indexing).
|
||||||
func (c *Comp) SetMix(index int, mix float64) error {
|
func (c *Comp) SetMix(index int, mix float64) error {
|
||||||
address := c.AddressFunc(c.baseAddress, index) + "/dyn/mix"
|
address := c.AddressFunc(c.baseAddress, index) + "/mix"
|
||||||
return c.client.SendMessage(address, float32(linSet(0, 100, mix)))
|
return c.client.SendMessage(address, float32(linSet(0, 100, mix)))
|
||||||
}
|
}
|
||||||
|
|||||||
95
internal/xair/dca.go
Normal file
95
internal/xair/dca.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package xair
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type DCA struct {
|
||||||
|
client *Client
|
||||||
|
baseAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newDCA creates a new DCA instance
|
||||||
|
func newDCA(c *Client) *DCA {
|
||||||
|
return &DCA{
|
||||||
|
client: c,
|
||||||
|
baseAddress: c.addressMap["dca"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mute requests the current mute status for a DCA group
|
||||||
|
func (d *DCA) Mute(group int) (bool, error) {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/on"
|
||||||
|
err := d.client.SendMessage(address)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := d.client.ReceiveMessage()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
val, ok := msg.Arguments[0].(int32)
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("unexpected argument type for DCA mute value")
|
||||||
|
}
|
||||||
|
return val == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMute sets the mute status for a specific DCA group (1-based indexing)
|
||||||
|
func (d *DCA) SetMute(group int, muted bool) error {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/on"
|
||||||
|
var value int32
|
||||||
|
if !muted {
|
||||||
|
value = 1
|
||||||
|
}
|
||||||
|
return d.client.SendMessage(address, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name requests the current name for a DCA group
|
||||||
|
func (d *DCA) Name(group int) (string, error) {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/config/name"
|
||||||
|
err := d.client.SendMessage(address)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := d.client.ReceiveMessage()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
name, ok := msg.Arguments[0].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("unexpected argument type for DCA name value")
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name for a specific DCA group (1-based indexing)
|
||||||
|
func (d *DCA) SetName(group int, name string) error {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/config/name"
|
||||||
|
return d.client.SendMessage(address, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color requests the current color for a DCA group
|
||||||
|
func (d *DCA) Color(group int) (int32, error) {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/config/color"
|
||||||
|
err := d.client.SendMessage(address)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := d.client.ReceiveMessage()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
color, ok := msg.Arguments[0].(int32)
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unexpected argument type for DCA color value")
|
||||||
|
}
|
||||||
|
return color, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColor sets the color for a specific DCA group (1-based indexing)
|
||||||
|
func (d *DCA) SetColor(group int, color int32) error {
|
||||||
|
address := fmt.Sprintf(d.baseAddress, group) + "/config/color"
|
||||||
|
return d.client.SendMessage(address, color)
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ type parser interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type engine struct {
|
type engine struct {
|
||||||
Kind MixerKind
|
Kind mixerKind
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
conn *net.UDPConn
|
conn *net.UDPConn
|
||||||
mixerAddr *net.UDPAddr
|
mixerAddr *net.UDPAddr
|
||||||
@@ -26,6 +26,42 @@ type engine struct {
|
|||||||
respChan chan *osc.Message
|
respChan chan *osc.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newEngine(mixerIP string, mixerPort int, kind mixerKind, opts ...EngineOption) (*engine, error) {
|
||||||
|
localAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", 0))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to resolve local address: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.ListenUDP("udp", localAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create UDP connection: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mixerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", mixerIP, mixerPort))
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, fmt.Errorf("failed to resolve mixer address: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Local UDP connection: %s ", conn.LocalAddr().String())
|
||||||
|
|
||||||
|
e := &engine{
|
||||||
|
timeout: 100 * time.Millisecond,
|
||||||
|
conn: conn,
|
||||||
|
mixerAddr: mixerAddr,
|
||||||
|
parser: newParser(),
|
||||||
|
addressMap: addressMapFromMixerKind(kind),
|
||||||
|
done: make(chan bool),
|
||||||
|
respChan: make(chan *osc.Message, 100),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
// receiveLoop handles incoming OSC messages
|
// receiveLoop handles incoming OSC messages
|
||||||
func (e *engine) receiveLoop() {
|
func (e *engine) receiveLoop() {
|
||||||
buffer := make([]byte, 4096)
|
buffer := make([]byte, 4096)
|
||||||
|
|||||||
@@ -4,53 +4,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Eq represents the EQ parameters.
|
||||||
type Eq struct {
|
type Eq struct {
|
||||||
client *Client
|
client *Client
|
||||||
baseAddress string
|
baseAddress string
|
||||||
AddressFunc func(fmtString string, args ...any) string
|
AddressFunc func(fmtString string, args ...any) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Factory function to create Eq instance for Main
|
// Factory function to create Eq instance with optional configuration
|
||||||
func newEqForMain(c *Client) *Eq {
|
func newEq(c *Client, baseAddress string, opts ...EqOption) *Eq {
|
||||||
return &Eq{
|
eq := &Eq{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["main"],
|
baseAddress: fmt.Sprintf("%s/eq", baseAddress),
|
||||||
AddressFunc: func(fmtString string, args ...any) string {
|
|
||||||
return fmtString
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Eq instance for Strip
|
|
||||||
func newEqForStrip(c *Client) *Eq {
|
|
||||||
return &Eq{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["strip"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
AddressFunc: fmt.Sprintf,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Eq instance for Bus
|
for _, opt := range opts {
|
||||||
func newEqForBus(c *Client) *Eq {
|
opt(eq)
|
||||||
return &Eq{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["bus"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Factory function to create Eq instance for Matrix
|
return eq
|
||||||
func newEqForMatrix(c *Client) *Eq {
|
|
||||||
return &Eq{
|
|
||||||
client: c,
|
|
||||||
baseAddress: c.addressMap["matrix"],
|
|
||||||
AddressFunc: fmt.Sprintf,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// On retrieves the on/off status of the EQ for a specific strip or bus (1-based indexing).
|
// On retrieves the on/off status of the EQ for a specific strip or bus (1-based indexing).
|
||||||
func (e *Eq) On(index int) (bool, error) {
|
func (e *Eq) On(index int) (bool, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + "/eq/on"
|
address := e.AddressFunc(e.baseAddress, index) + "/on"
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -69,7 +47,7 @@ func (e *Eq) On(index int) (bool, error) {
|
|||||||
|
|
||||||
// SetOn sets the on/off status of the EQ for a specific strip or bus (1-based indexing).
|
// SetOn sets the on/off status of the EQ for a specific strip or bus (1-based indexing).
|
||||||
func (e *Eq) SetOn(index int, on bool) error {
|
func (e *Eq) SetOn(index int, on bool) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + "/eq/on"
|
address := e.AddressFunc(e.baseAddress, index) + "/on"
|
||||||
var value int32
|
var value int32
|
||||||
if on {
|
if on {
|
||||||
value = 1
|
value = 1
|
||||||
@@ -78,7 +56,7 @@ func (e *Eq) SetOn(index int, on bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Eq) Mode(index int) (string, error) {
|
func (e *Eq) Mode(index int) (string, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + "/eq/mode"
|
address := e.AddressFunc(e.baseAddress, index) + "/mode"
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -98,14 +76,14 @@ func (e *Eq) Mode(index int) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Eq) SetMode(index int, mode string) error {
|
func (e *Eq) SetMode(index int, mode string) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + "/eq/mode"
|
address := e.AddressFunc(e.baseAddress, index) + "/mode"
|
||||||
possibleModes := []string{"peq", "geq", "teq"}
|
possibleModes := []string{"peq", "geq", "teq"}
|
||||||
return e.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
return e.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gain retrieves the gain for a specific EQ band on a strip or bus (1-based indexing).
|
// Gain retrieves the gain for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) Gain(index int, band int) (float64, error) {
|
func (e *Eq) Gain(index int, band int) (float64, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/g", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/g", band)
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -124,13 +102,13 @@ func (e *Eq) Gain(index int, band int) (float64, error) {
|
|||||||
|
|
||||||
// SetGain sets the gain for a specific EQ band on a strip or bus (1-based indexing).
|
// SetGain sets the gain for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) SetGain(index int, band int, gain float64) error {
|
func (e *Eq) SetGain(index int, band int, gain float64) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/g", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/g", band)
|
||||||
return e.client.SendMessage(address, float32(linSet(-15, 15, gain)))
|
return e.client.SendMessage(address, float32(linSet(-15, 15, gain)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frequency retrieves the frequency for a specific EQ band on a strip or bus (1-based indexing).
|
// Frequency retrieves the frequency for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) Frequency(index int, band int) (float64, error) {
|
func (e *Eq) Frequency(index int, band int) (float64, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/f", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/f", band)
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -149,13 +127,13 @@ func (e *Eq) Frequency(index int, band int) (float64, error) {
|
|||||||
|
|
||||||
// SetFrequency sets the frequency for a specific EQ band on a strip or bus (1-based indexing).
|
// SetFrequency sets the frequency for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) SetFrequency(index int, band int, frequency float64) error {
|
func (e *Eq) SetFrequency(index int, band int, frequency float64) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/f", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/f", band)
|
||||||
return e.client.SendMessage(address, float32(logSet(20, 20000, frequency)))
|
return e.client.SendMessage(address, float32(logSet(20, 20000, frequency)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Q retrieves the Q factor for a specific EQ band on a strip or bus (1-based indexing).
|
// Q retrieves the Q factor for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) Q(index int, band int) (float64, error) {
|
func (e *Eq) Q(index int, band int) (float64, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/q", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/q", band)
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -174,13 +152,13 @@ func (e *Eq) Q(index int, band int) (float64, error) {
|
|||||||
|
|
||||||
// SetQ sets the Q factor for a specific EQ band on a strip or bus (1-based indexing).
|
// SetQ sets the Q factor for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) SetQ(index int, band int, q float64) error {
|
func (e *Eq) SetQ(index int, band int, q float64) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/q", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/q", band)
|
||||||
return e.client.SendMessage(address, float32(1.0-logSet(0.3, 10, q)))
|
return e.client.SendMessage(address, float32(1.0-logSet(0.3, 10, q)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type retrieves the type for a specific EQ band on a strip or bus (1-based indexing).
|
// Type retrieves the type for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) Type(index int, band int) (string, error) {
|
func (e *Eq) Type(index int, band int) (string, error) {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/type", band)
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -201,7 +179,7 @@ func (e *Eq) Type(index int, band int) (string, error) {
|
|||||||
|
|
||||||
// SetType sets the type for a specific EQ band on a strip or bus (1-based indexing).
|
// SetType sets the type for a specific EQ band on a strip or bus (1-based indexing).
|
||||||
func (e *Eq) SetType(index int, band int, eqType string) error {
|
func (e *Eq) SetType(index int, band int, eqType string) error {
|
||||||
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
address := e.AddressFunc(e.baseAddress, index) + fmt.Sprintf("/%d/type", band)
|
||||||
possibleTypes := []string{"lcut", "lshv", "peq", "veq", "hshv", "hcut"}
|
possibleTypes := []string{"lcut", "lshv", "peq", "veq", "hshv", "hcut"}
|
||||||
return e.client.SendMessage(address, int32(indexOf(possibleTypes, eqType)))
|
return e.client.SendMessage(address, int32(indexOf(possibleTypes, eqType)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,22 +2,31 @@ package xair
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// Gate represents the gate parameters.
|
||||||
type Gate struct {
|
type Gate struct {
|
||||||
client *Client
|
client *Client
|
||||||
baseAddress string
|
baseAddress string
|
||||||
|
AddressFunc func(fmtString string, args ...any) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Factory function to create Gate instance for Strip
|
// Factory function to create Gate instance with optional configuration
|
||||||
func newGateForStrip(c *Client) *Gate {
|
func newGate(c *Client, baseAddress string, opts ...GateOption) *Gate {
|
||||||
return &Gate{
|
gate := &Gate{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["strip"],
|
baseAddress: fmt.Sprintf("%s/gate", baseAddress),
|
||||||
|
AddressFunc: fmt.Sprintf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(gate)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gate
|
||||||
}
|
}
|
||||||
|
|
||||||
// On retrieves the on/off status of the Gate for a specific strip (1-based indexing).
|
// On retrieves the on/off status of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) On(index int) (bool, error) {
|
func (g *Gate) On(index int) (bool, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/on"
|
address := g.AddressFunc(g.baseAddress, index) + "/on"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -36,7 +45,7 @@ func (g *Gate) On(index int) (bool, error) {
|
|||||||
|
|
||||||
// SetOn sets the on/off status of the Gate for a specific strip (1-based indexing).
|
// SetOn sets the on/off status of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetOn(index int, on bool) error {
|
func (g *Gate) SetOn(index int, on bool) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/on"
|
address := g.AddressFunc(g.baseAddress, index) + "/on"
|
||||||
var value int32
|
var value int32
|
||||||
if on {
|
if on {
|
||||||
value = 1
|
value = 1
|
||||||
@@ -46,7 +55,7 @@ func (g *Gate) SetOn(index int, on bool) error {
|
|||||||
|
|
||||||
// Mode retrieves the current mode of the Gate for a specific strip (1-based indexing).
|
// Mode retrieves the current mode of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Mode(index int) (string, error) {
|
func (g *Gate) Mode(index int) (string, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/mode"
|
address := g.AddressFunc(g.baseAddress, index) + "/mode"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -67,7 +76,7 @@ func (g *Gate) Mode(index int) (string, error) {
|
|||||||
|
|
||||||
// SetMode sets the mode of the Gate for a specific strip (1-based indexing).
|
// SetMode sets the mode of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetMode(index int, mode string) error {
|
func (g *Gate) SetMode(index int, mode string) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/mode"
|
address := g.AddressFunc(g.baseAddress, index) + "/mode"
|
||||||
possibleModes := []string{"exp2", "exp3", "exp4", "gate", "duck"}
|
possibleModes := []string{"exp2", "exp3", "exp4", "gate", "duck"}
|
||||||
|
|
||||||
return g.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
return g.client.SendMessage(address, int32(indexOf(possibleModes, mode)))
|
||||||
@@ -75,7 +84,7 @@ func (g *Gate) SetMode(index int, mode string) error {
|
|||||||
|
|
||||||
// Threshold retrieves the threshold value of the Gate for a specific strip (1-based indexing).
|
// Threshold retrieves the threshold value of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Threshold(index int) (float64, error) {
|
func (g *Gate) Threshold(index int) (float64, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/thr"
|
address := g.AddressFunc(g.baseAddress, index) + "/thr"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -94,13 +103,13 @@ func (g *Gate) Threshold(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetThreshold sets the threshold value of the Gate for a specific strip (1-based indexing).
|
// SetThreshold sets the threshold value of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetThreshold(index int, threshold float64) error {
|
func (g *Gate) SetThreshold(index int, threshold float64) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/thr"
|
address := g.AddressFunc(g.baseAddress, index) + "/thr"
|
||||||
return g.client.SendMessage(address, float32(linSet(-80, 0, threshold)))
|
return g.client.SendMessage(address, float32(linSet(-80, 0, threshold)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Range retrieves the range value of the Gate for a specific strip (1-based indexing).
|
// Range retrieves the range value of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Range(index int) (float64, error) {
|
func (g *Gate) Range(index int) (float64, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/range"
|
address := g.AddressFunc(g.baseAddress, index) + "/range"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -119,13 +128,13 @@ func (g *Gate) Range(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetRange sets the range value of the Gate for a specific strip (1-based indexing).
|
// SetRange sets the range value of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetRange(index int, rangeVal float64) error {
|
func (g *Gate) SetRange(index int, rangeVal float64) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/range"
|
address := g.AddressFunc(g.baseAddress, index) + "/range"
|
||||||
return g.client.SendMessage(address, float32(linSet(3, 60, rangeVal)))
|
return g.client.SendMessage(address, float32(linSet(3, 60, rangeVal)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attack retrieves the attack time of the Gate for a specific strip (1-based indexing).
|
// Attack retrieves the attack time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Attack(index int) (float64, error) {
|
func (g *Gate) Attack(index int) (float64, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/attack"
|
address := g.AddressFunc(g.baseAddress, index) + "/attack"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -144,13 +153,13 @@ func (g *Gate) Attack(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetAttack sets the attack time of the Gate for a specific strip (1-based indexing).
|
// SetAttack sets the attack time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetAttack(index int, attack float64) error {
|
func (g *Gate) SetAttack(index int, attack float64) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/attack"
|
address := g.AddressFunc(g.baseAddress, index) + "/attack"
|
||||||
return g.client.SendMessage(address, float32(linSet(0, 120, attack)))
|
return g.client.SendMessage(address, float32(linSet(0, 120, attack)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hold retrieves the hold time of the Gate for a specific strip (1-based indexing).
|
// Hold retrieves the hold time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Hold(index int) (float64, error) {
|
func (g *Gate) Hold(index int) (float64, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/hold"
|
address := g.AddressFunc(g.baseAddress, index) + "/hold"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -169,13 +178,13 @@ func (g *Gate) Hold(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetHold sets the hold time of the Gate for a specific strip (1-based indexing).
|
// SetHold sets the hold time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetHold(index int, hold float64) error {
|
func (g *Gate) SetHold(index int, hold float64) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/hold"
|
address := g.AddressFunc(g.baseAddress, index) + "/hold"
|
||||||
return g.client.SendMessage(address, float32(logSet(0.02, 2000, hold)))
|
return g.client.SendMessage(address, float32(logSet(0.02, 2000, hold)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release retrieves the release time of the Gate for a specific strip (1-based indexing).
|
// Release retrieves the release time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) Release(index int) (float64, error) {
|
func (g *Gate) Release(index int) (float64, error) {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/release"
|
address := g.AddressFunc(g.baseAddress, index) + "/release"
|
||||||
err := g.client.SendMessage(address)
|
err := g.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -194,6 +203,6 @@ func (g *Gate) Release(index int) (float64, error) {
|
|||||||
|
|
||||||
// SetRelease sets the release time of the Gate for a specific strip (1-based indexing).
|
// SetRelease sets the release time of the Gate for a specific strip (1-based indexing).
|
||||||
func (g *Gate) SetRelease(index int, release float64) error {
|
func (g *Gate) SetRelease(index int, release float64) error {
|
||||||
address := fmt.Sprintf(g.baseAddress, index) + "/gate/release"
|
address := g.AddressFunc(g.baseAddress, index) + "/release"
|
||||||
return g.client.SendMessage(address, float32(logSet(5, 4000, release)))
|
return g.client.SendMessage(address, float32(logSet(5, 4000, release)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package xair
|
package xair
|
||||||
|
|
||||||
type MixerKind string
|
type mixerKind string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KindXAir MixerKind = "xair"
|
kindXAir mixerKind = "xair"
|
||||||
KindX32 MixerKind = "x32"
|
kindX32 mixerKind = "x32"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,19 +11,29 @@ type Main struct {
|
|||||||
|
|
||||||
// newMainStereo creates a new Main instance for stereo main output
|
// newMainStereo creates a new Main instance for stereo main output
|
||||||
func newMainStereo(c *Client) *Main {
|
func newMainStereo(c *Client) *Main {
|
||||||
|
addressFunc := func(fmtString string, args ...any) string {
|
||||||
|
return fmtString
|
||||||
|
}
|
||||||
|
|
||||||
return &Main{
|
return &Main{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["main"],
|
baseAddress: c.addressMap["main"],
|
||||||
Eq: newEqForMain(c),
|
Eq: newEq(c, c.addressMap["main"], WithEqAddressFunc(addressFunc)),
|
||||||
Comp: newCompForMain(c),
|
Comp: newComp(c, c.addressMap["main"], WithCompAddressFunc(addressFunc)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMainMono creates a new MainMono instance for mono main output (X32 only)
|
// newMainMono creates a new MainMono instance for mono main output (X32 only)
|
||||||
func newMainMono(c *Client) *Main {
|
func newMainMono(c *Client) *Main {
|
||||||
|
addressFunc := func(fmtString string, args ...any) string {
|
||||||
|
return fmtString
|
||||||
|
}
|
||||||
|
|
||||||
return &Main{
|
return &Main{
|
||||||
baseAddress: c.addressMap["mainmono"],
|
baseAddress: c.addressMap["mainmono"],
|
||||||
client: c,
|
client: c,
|
||||||
|
Eq: newEq(c, c.addressMap["mainmono"], WithEqAddressFunc(addressFunc)),
|
||||||
|
Comp: newComp(c, c.addressMap["mainmono"], WithCompAddressFunc(addressFunc)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ func newMatrix(c *Client) *Matrix {
|
|||||||
return &Matrix{
|
return &Matrix{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["matrix"],
|
baseAddress: c.addressMap["matrix"],
|
||||||
Eq: newEqForMatrix(c),
|
Eq: newEq(c, c.addressMap["matrix"]),
|
||||||
Comp: newCompForMatrix(c),
|
Comp: newComp(c, c.addressMap["matrix"]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,38 @@ package xair
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Option func(*engine)
|
type EngineOption func(*engine)
|
||||||
|
|
||||||
func WithKind(kind string) Option {
|
// WithTimeout sets the timeout duration for OSC message responses
|
||||||
return func(e *engine) {
|
func WithTimeout(timeout time.Duration) EngineOption {
|
||||||
e.Kind = MixerKind(kind)
|
|
||||||
e.addressMap = addressMapForMixerKind(e.Kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithTimeout(timeout time.Duration) Option {
|
|
||||||
return func(e *engine) {
|
return func(e *engine) {
|
||||||
e.timeout = timeout
|
e.timeout = timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CompOption func(*Comp)
|
||||||
|
|
||||||
|
// WithCompAddressFunc allows customization of the OSC address formatting for Comp parameters
|
||||||
|
func WithCompAddressFunc(f func(fmtString string, args ...any) string) CompOption {
|
||||||
|
return func(c *Comp) {
|
||||||
|
c.AddressFunc = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type EqOption func(*Eq)
|
||||||
|
|
||||||
|
// WithEqAddressFunc allows customization of the OSC address formatting for Eq parameters
|
||||||
|
func WithEqAddressFunc(f func(fmtString string, args ...any) string) EqOption {
|
||||||
|
return func(e *Eq) {
|
||||||
|
e.AddressFunc = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GateOption func(*Gate)
|
||||||
|
|
||||||
|
// WithGateAddressFunc allows customization of the OSC address formatting for Gate parameters
|
||||||
|
func WithGateAddressFunc(f func(fmtString string, args ...any) string) GateOption {
|
||||||
|
return func(g *Gate) {
|
||||||
|
g.AddressFunc = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ type Snapshot struct {
|
|||||||
baseAddress string
|
baseAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newSnapshot creates a new Snapshot instance
|
||||||
func newSnapshot(c *Client) *Snapshot {
|
func newSnapshot(c *Client) *Snapshot {
|
||||||
return &Snapshot{
|
return &Snapshot{
|
||||||
client: c,
|
client: c,
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ type Strip struct {
|
|||||||
Comp *Comp
|
Comp *Comp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newStrip creates a new Strip instance
|
||||||
func newStrip(c *Client) *Strip {
|
func newStrip(c *Client) *Strip {
|
||||||
return &Strip{
|
return &Strip{
|
||||||
client: c,
|
client: c,
|
||||||
baseAddress: c.addressMap["strip"],
|
baseAddress: c.addressMap["strip"],
|
||||||
Gate: newGateForStrip(c),
|
Gate: newGate(c, c.addressMap["strip"]),
|
||||||
Eq: newEqForStrip(c),
|
Eq: newEq(c, c.addressMap["strip"]),
|
||||||
Comp: newCompForStrip(c),
|
Comp: newComp(c, c.addressMap["strip"]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ func (s *Strip) SetColor(strip int, color int32) error {
|
|||||||
return s.client.SendMessage(address, color)
|
return s.client.SendMessage(address, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends requests the sends level for a mixbus.
|
// SendLevel requests the sends level for a mixbus.
|
||||||
func (s *Strip) SendLevel(strip int, bus int) (float64, error) {
|
func (s *Strip) SendLevel(strip int, bus int) (float64, error) {
|
||||||
address := fmt.Sprintf(s.baseAddress, strip) + fmt.Sprintf("/mix/%02d/level", bus)
|
address := fmt.Sprintf(s.baseAddress, strip) + fmt.Sprintf("/mix/%02d/level", bus)
|
||||||
err := s.client.SendMessage(address)
|
err := s.client.SendMessage(address)
|
||||||
|
|||||||
198
x32-help.md
Normal file
198
x32-help.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
```console
|
||||||
|
Usage: x32-cli <command> [flags]
|
||||||
|
|
||||||
|
A CLI to control Behringer X32 mixers.
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-h, --help Show context-sensitive help.
|
||||||
|
-H, --host="mixer.local" The host of the X32 device ($X32_CLI_HOST).
|
||||||
|
-P, --port=10023 The port of the X32 device ($X32_CLI_PORT).
|
||||||
|
-T, --timeout=100ms Timeout for OSC operations ($X32_CLI_TIMEOUT).
|
||||||
|
-L, --loglevel="warn" Log level for the CLI ($X32_CLI_LOGLEVEL).
|
||||||
|
-v, --version Print x32-cli version information and quit
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
completion (c) Generate shell completion scripts.
|
||||||
|
|
||||||
|
Raw
|
||||||
|
raw Send raw OSC messages to the mixer.
|
||||||
|
|
||||||
|
Main
|
||||||
|
main mute Get or set the mute state of the Main L/R output.
|
||||||
|
main fader Get or set the fader level of the Main L/R output.
|
||||||
|
main fadein Fade in the Main L/R output over a specified duration.
|
||||||
|
main fadeout Fade out the Main L/R output over a specified duration.
|
||||||
|
main eq on Get or set the EQ on/off state of the Main L/R output.
|
||||||
|
main eq <band> gain Get or set the gain of the specified EQ band.
|
||||||
|
main eq <band> freq Get or set the frequency of the specified EQ band.
|
||||||
|
main eq <band> q Get or set the Q factor of the specified EQ band.
|
||||||
|
main eq <band> type Get or set the type of the specified EQ band.
|
||||||
|
main comp on Get or set the compressor on/off state of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp mode Get or set the compressor mode of the Main L/R output.
|
||||||
|
main comp threshold Get or set the compressor threshold of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp ratio Get or set the compressor ratio of the Main L/R output.
|
||||||
|
main comp mix Get or set the compressor mix level of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp makeup Get or set the compressor makeup gain of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp attack Get or set the compressor attack time of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp hold Get or set the compressor hold time of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp release Get or set the compressor release time of the Main L/R
|
||||||
|
output.
|
||||||
|
|
||||||
|
MainMono
|
||||||
|
mainmono mute Get or set the mute state of the Main Mono output.
|
||||||
|
mainmono fader Get or set the fader level of the Main Mono output.
|
||||||
|
mainmono fadein Fade in the Main Mono output over a specified
|
||||||
|
duration.
|
||||||
|
mainmono fadeout Fade out the Main Mono output over a specified
|
||||||
|
duration.
|
||||||
|
mainmono eq on Get or set the EQ on/off state of the Main Mono
|
||||||
|
output.
|
||||||
|
mainmono eq <band> gain Get or set the gain of the specified EQ band.
|
||||||
|
mainmono eq <band> freq Get or set the frequency of the specified EQ band.
|
||||||
|
mainmono eq <band> q Get or set the Q factor of the specified EQ band.
|
||||||
|
mainmono eq <band> type Get or set the type of the specified EQ band.
|
||||||
|
mainmono comp on Get or set the compressor on/off state of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp mode Get or set the compressor mode of the Main Mono
|
||||||
|
output.
|
||||||
|
mainmono comp threshold Get or set the compressor threshold of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp ratio Get or set the compressor ratio of the Main Mono
|
||||||
|
output.
|
||||||
|
mainmono comp mix Get or set the compressor mix level of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp makeup Get or set the compressor makeup gain of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp attack Get or set the compressor attack time of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp hold Get or set the compressor hold time of the Main
|
||||||
|
Mono output.
|
||||||
|
mainmono comp release Get or set the compressor release time of the Main
|
||||||
|
Mono output.
|
||||||
|
|
||||||
|
Matrix
|
||||||
|
matrix <index> mute Get or set the mute state of the Matrix
|
||||||
|
output.
|
||||||
|
matrix <index> fader Get or set the fader level of the Matrix
|
||||||
|
output.
|
||||||
|
matrix <index> fadein Fade in the Matrix output over a specified
|
||||||
|
duration.
|
||||||
|
matrix <index> fadeout Fade out the Matrix output over a specified
|
||||||
|
duration.
|
||||||
|
matrix <index> eq on Get or set the EQ on/off state of the Matrix
|
||||||
|
output.
|
||||||
|
matrix <index> eq <band> gain Get or set the gain of the specified EQ band.
|
||||||
|
matrix <index> eq <band> freq Get or set the frequency of the specified EQ
|
||||||
|
band.
|
||||||
|
matrix <index> eq <band> q Get or set the Q factor of the specified EQ
|
||||||
|
band.
|
||||||
|
matrix <index> eq <band> type Get or set the type of the specified EQ band.
|
||||||
|
matrix <index> comp on Get or set the compressor on/off state of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp mode Get or set the compressor mode of the Matrix
|
||||||
|
output.
|
||||||
|
matrix <index> comp threshold Get or set the compressor threshold of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp ratio Get or set the compressor ratio of the Matrix
|
||||||
|
output.
|
||||||
|
matrix <index> comp mix Get or set the compressor mix level of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp makeup Get or set the compressor makeup gain of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp attack Get or set the compressor attack time of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp hold Get or set the compressor hold time of the
|
||||||
|
Matrix output.
|
||||||
|
matrix <index> comp release Get or set the compressor release time of the
|
||||||
|
Matrix output.
|
||||||
|
|
||||||
|
Strip
|
||||||
|
strip <index> mute Get or set the mute state of the strip.
|
||||||
|
strip <index> fader Get or set the fader level of the strip.
|
||||||
|
strip <index> fadein Fade in the strip over a specified duration.
|
||||||
|
strip <index> fadeout Fade out the strip over a specified duration.
|
||||||
|
strip <index> send Get or set the send level for a specific bus.
|
||||||
|
strip <index> name Get or set the name of the strip.
|
||||||
|
strip <index> gate on Get or set the gate on/off state of the strip.
|
||||||
|
strip <index> gate mode Get or set the gate mode of the strip.
|
||||||
|
strip <index> gate threshold Get or set the gate threshold of the strip.
|
||||||
|
strip <index> gate range Get or set the gate range of the strip.
|
||||||
|
strip <index> gate attack Get or set the gate attack time of the strip.
|
||||||
|
strip <index> gate hold Get or set the gate hold time of the strip.
|
||||||
|
strip <index> gate release Get or set the gate release time of the strip.
|
||||||
|
strip <index> eq on Get or set the EQ on/off state of the strip.
|
||||||
|
strip <index> eq <band> gain Get or set the gain of the EQ band.
|
||||||
|
strip <index> eq <band> freq Get or set the frequency of the EQ band.
|
||||||
|
strip <index> eq <band> q Get or set the Q factor of the EQ band.
|
||||||
|
strip <index> eq <band> type Get or set the type of the EQ band.
|
||||||
|
strip <index> comp on Get or set the compressor on/off state of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp mode Get or set the compressor mode of the strip.
|
||||||
|
strip <index> comp threshold Get or set the compressor threshold of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp ratio Get or set the compressor ratio of the strip.
|
||||||
|
strip <index> comp mix Get or set the compressor mix of the strip.
|
||||||
|
strip <index> comp makeup Get or set the compressor makeup gain of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp attack Get or set the compressor attack time of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp hold Get or set the compressor hold time of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp release Get or set the compressor release time of the
|
||||||
|
strip.
|
||||||
|
|
||||||
|
Bus
|
||||||
|
bus <index> mute Get or set the mute state of the bus.
|
||||||
|
bus <index> fader Get or set the fader level of the bus.
|
||||||
|
bus <index> fadein Fade in the bus over a specified duration.
|
||||||
|
bus <index> fadeout Fade out the bus over a specified duration.
|
||||||
|
bus <index> name Get or set the name of the bus.
|
||||||
|
bus <index> eq on Get or set the EQ on/off state of the bus.
|
||||||
|
bus <index> eq mode Get or set the EQ mode of the bus (peq, geq or
|
||||||
|
teq).
|
||||||
|
bus <index> eq <band> gain Get or set the gain of the EQ band.
|
||||||
|
bus <index> eq <band> freq Get or set the frequency of the EQ band.
|
||||||
|
bus <index> eq <band> q Get or set the Q factor of the EQ band.
|
||||||
|
bus <index> eq <band> type Get or set the type of the EQ band (lcut, lshv,
|
||||||
|
peq, veq, hshv, hcut).
|
||||||
|
bus <index> comp on Get or set the compressor on/off state of the
|
||||||
|
bus.
|
||||||
|
bus <index> comp mode Get or set the compressor mode of the bus (comp,
|
||||||
|
exp).
|
||||||
|
bus <index> comp threshold Get or set the compressor threshold of the bus
|
||||||
|
(in dB).
|
||||||
|
bus <index> comp ratio Get or set the compressor ratio of the bus.
|
||||||
|
bus <index> comp mix Get or set the compressor mix level of the bus
|
||||||
|
(in %).
|
||||||
|
bus <index> comp makeup Get or set the compressor makeup gain of the bus
|
||||||
|
(in dB).
|
||||||
|
bus <index> comp attack Get or set the compressor attack time of the bus
|
||||||
|
(in ms).
|
||||||
|
bus <index> comp hold Get or set the compressor hold time of the bus
|
||||||
|
(in ms).
|
||||||
|
bus <index> comp release Get or set the compressor release time of the
|
||||||
|
bus (in ms).
|
||||||
|
|
||||||
|
Headamp
|
||||||
|
headamp <index> gain Get or set the gain of the headamp.
|
||||||
|
headamp <index> phantom Get or set the phantom power state of the headamp.
|
||||||
|
|
||||||
|
Snapshot
|
||||||
|
snapshot list List all snapshots.
|
||||||
|
snapshot <index> name Get or set the name of a snapshot.
|
||||||
|
snapshot <index> save Save the current mixer state to a snapshot.
|
||||||
|
snapshot <index> load Load a mixer state from a snapshot.
|
||||||
|
snapshot <index> delete Delete a snapshot.
|
||||||
|
|
||||||
|
DCA
|
||||||
|
dca <index> mute Get or set the mute status of the DCA group.
|
||||||
|
dca <index> name Get or set the name of the DCA group.
|
||||||
|
|
||||||
|
Run "x32-cli <command> --help" for more information on a command.
|
||||||
|
```
|
||||||
130
xair-help.md
Normal file
130
xair-help.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
```console
|
||||||
|
Usage: xair-cli <command> [flags]
|
||||||
|
|
||||||
|
A CLI to control Behringer X-Air mixers.
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-h, --help Show context-sensitive help.
|
||||||
|
-H, --host="mixer.local" The host of the X-Air device ($XAIR_CLI_HOST).
|
||||||
|
-P, --port=10024 The port of the X-Air device ($XAIR_CLI_PORT).
|
||||||
|
-T, --timeout=100ms Timeout for OSC operations ($XAIR_CLI_TIMEOUT).
|
||||||
|
-L, --loglevel="warn" Log level for the CLI ($XAIR_CLI_LOGLEVEL).
|
||||||
|
-v, --version Print xair-cli version information and quit
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
completion (c) Generate shell completion scripts.
|
||||||
|
|
||||||
|
Raw
|
||||||
|
raw Send raw OSC messages to the mixer.
|
||||||
|
|
||||||
|
Main
|
||||||
|
main mute Get or set the mute state of the Main L/R output.
|
||||||
|
main fader Get or set the fader level of the Main L/R output.
|
||||||
|
main fadein Fade in the Main L/R output over a specified duration.
|
||||||
|
main fadeout Fade out the Main L/R output over a specified duration.
|
||||||
|
main eq on Get or set the EQ on/off state of the Main L/R output.
|
||||||
|
main eq <band> gain Get or set the gain of the specified EQ band.
|
||||||
|
main eq <band> freq Get or set the frequency of the specified EQ band.
|
||||||
|
main eq <band> q Get or set the Q factor of the specified EQ band.
|
||||||
|
main eq <band> type Get or set the type of the specified EQ band.
|
||||||
|
main comp on Get or set the compressor on/off state of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp mode Get or set the compressor mode of the Main L/R output.
|
||||||
|
main comp threshold Get or set the compressor threshold of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp ratio Get or set the compressor ratio of the Main L/R output.
|
||||||
|
main comp mix Get or set the compressor mix level of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp makeup Get or set the compressor makeup gain of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp attack Get or set the compressor attack time of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp hold Get or set the compressor hold time of the Main L/R
|
||||||
|
output.
|
||||||
|
main comp release Get or set the compressor release time of the Main L/R
|
||||||
|
output.
|
||||||
|
|
||||||
|
Strip
|
||||||
|
strip <index> mute Get or set the mute state of the strip.
|
||||||
|
strip <index> fader Get or set the fader level of the strip.
|
||||||
|
strip <index> fadein Fade in the strip over a specified duration.
|
||||||
|
strip <index> fadeout Fade out the strip over a specified duration.
|
||||||
|
strip <index> send Get or set the send level for a specific bus.
|
||||||
|
strip <index> name Get or set the name of the strip.
|
||||||
|
strip <index> gate on Get or set the gate on/off state of the strip.
|
||||||
|
strip <index> gate mode Get or set the gate mode of the strip.
|
||||||
|
strip <index> gate threshold Get or set the gate threshold of the strip.
|
||||||
|
strip <index> gate range Get or set the gate range of the strip.
|
||||||
|
strip <index> gate attack Get or set the gate attack time of the strip.
|
||||||
|
strip <index> gate hold Get or set the gate hold time of the strip.
|
||||||
|
strip <index> gate release Get or set the gate release time of the strip.
|
||||||
|
strip <index> eq on Get or set the EQ on/off state of the strip.
|
||||||
|
strip <index> eq <band> gain Get or set the gain of the EQ band.
|
||||||
|
strip <index> eq <band> freq Get or set the frequency of the EQ band.
|
||||||
|
strip <index> eq <band> q Get or set the Q factor of the EQ band.
|
||||||
|
strip <index> eq <band> type Get or set the type of the EQ band.
|
||||||
|
strip <index> comp on Get or set the compressor on/off state of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp mode Get or set the compressor mode of the strip.
|
||||||
|
strip <index> comp threshold Get or set the compressor threshold of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp ratio Get or set the compressor ratio of the strip.
|
||||||
|
strip <index> comp mix Get or set the compressor mix of the strip.
|
||||||
|
strip <index> comp makeup Get or set the compressor makeup gain of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp attack Get or set the compressor attack time of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp hold Get or set the compressor hold time of the
|
||||||
|
strip.
|
||||||
|
strip <index> comp release Get or set the compressor release time of the
|
||||||
|
strip.
|
||||||
|
|
||||||
|
Bus
|
||||||
|
bus <index> mute Get or set the mute state of the bus.
|
||||||
|
bus <index> fader Get or set the fader level of the bus.
|
||||||
|
bus <index> fadein Fade in the bus over a specified duration.
|
||||||
|
bus <index> fadeout Fade out the bus over a specified duration.
|
||||||
|
bus <index> name Get or set the name of the bus.
|
||||||
|
bus <index> eq on Get or set the EQ on/off state of the bus.
|
||||||
|
bus <index> eq mode Get or set the EQ mode of the bus (peq, geq or
|
||||||
|
teq).
|
||||||
|
bus <index> eq <band> gain Get or set the gain of the EQ band.
|
||||||
|
bus <index> eq <band> freq Get or set the frequency of the EQ band.
|
||||||
|
bus <index> eq <band> q Get or set the Q factor of the EQ band.
|
||||||
|
bus <index> eq <band> type Get or set the type of the EQ band (lcut, lshv,
|
||||||
|
peq, veq, hshv, hcut).
|
||||||
|
bus <index> comp on Get or set the compressor on/off state of the
|
||||||
|
bus.
|
||||||
|
bus <index> comp mode Get or set the compressor mode of the bus (comp,
|
||||||
|
exp).
|
||||||
|
bus <index> comp threshold Get or set the compressor threshold of the bus
|
||||||
|
(in dB).
|
||||||
|
bus <index> comp ratio Get or set the compressor ratio of the bus.
|
||||||
|
bus <index> comp mix Get or set the compressor mix level of the bus
|
||||||
|
(in %).
|
||||||
|
bus <index> comp makeup Get or set the compressor makeup gain of the bus
|
||||||
|
(in dB).
|
||||||
|
bus <index> comp attack Get or set the compressor attack time of the bus
|
||||||
|
(in ms).
|
||||||
|
bus <index> comp hold Get or set the compressor hold time of the bus
|
||||||
|
(in ms).
|
||||||
|
bus <index> comp release Get or set the compressor release time of the
|
||||||
|
bus (in ms).
|
||||||
|
|
||||||
|
Headamp
|
||||||
|
headamp <index> gain Get or set the gain of the headamp.
|
||||||
|
headamp <index> phantom Get or set the phantom power state of the headamp.
|
||||||
|
|
||||||
|
Snapshot
|
||||||
|
snapshot list List all snapshots.
|
||||||
|
snapshot <index> name Get or set the name of a snapshot.
|
||||||
|
snapshot <index> save Save the current mixer state to a snapshot.
|
||||||
|
snapshot <index> load Load a mixer state from a snapshot.
|
||||||
|
snapshot <index> delete Delete a snapshot.
|
||||||
|
|
||||||
|
DCA
|
||||||
|
dca <index> mute Get or set the mute status of the DCA group.
|
||||||
|
dca <index> name Get or set the name of the DCA group.
|
||||||
|
|
||||||
|
Run "xair-cli <command> --help" for more information on a command.
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user