mirror of
https://github.com/onyx-and-iris/xair-cli.git
synced 2026-02-26 00:09:11 +00:00
migrate CLI component to Kong
This commit is contained in:
parent
49cf3ff49e
commit
128f0c1df6
503
bus.go
Normal file
503
bus.go
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BusCmdGroup struct {
|
||||||
|
Index struct {
|
||||||
|
Index int `arg:"" help:"The index of the bus. (1-based indexing)"`
|
||||||
|
Mute BusMuteCmd ` help:"Get or set the mute state of the bus." cmd:""`
|
||||||
|
Fader BusFaderCmd ` help:"Get or set the fader level of the bus." cmd:""`
|
||||||
|
Fadein BusFadeinCmd ` help:"Fade in the bus over a specified duration." cmd:""`
|
||||||
|
Fadeout BusFadeoutCmd ` help:"Fade out the bus over a specified duration." cmd:""`
|
||||||
|
Name BusNameCmd ` help:"Get or set the name of the bus." cmd:""`
|
||||||
|
|
||||||
|
Eq BusEqCmdGroup ` help:"Commands related to the bus EQ." cmd:"eq"`
|
||||||
|
Comp BusCompCmdGroup ` help:"Commands related to the bus compressor." cmd:"comp"`
|
||||||
|
} `arg:"" help:"The index of the bus."`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusMuteCmd struct {
|
||||||
|
State *string `arg:"" help:"The mute state to set (true or false). If not provided, the current mute state will be returned." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusMuteCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Mute(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d mute state: %t\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.SetMute(bus.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d mute state set to: %s\n", bus.Index.Index, *cmd.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusFaderCmd struct {
|
||||||
|
Level *float64 `arg:"" help:"The fader level to set (in dB). If not provided, the current fader level will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusFaderCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Level == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Fader(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d fader level: %.2f dB\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.SetFader(bus.Index.Index, *cmd.Level); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d fader level set to: %.2f dB\n", bus.Index.Index, *cmd.Level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusFadeinCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-in effect." default:"5s"`
|
||||||
|
Target float64 ` help:"The target fader level (in dB)." default:"0.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusFadeinCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
currentLevel, err := ctx.Client.Bus.Fader(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get current fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel >= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f dB) is already at or above the target level (%.2f dB)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(cmd.Target - currentLevel)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel < cmd.Target {
|
||||||
|
currentLevel += totalSteps / float64(cmd.Duration.Seconds()*1000/stepDuration.Seconds())
|
||||||
|
if currentLevel > cmd.Target {
|
||||||
|
currentLevel = cmd.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.SetFader(bus.Index.Index, currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set fader level: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d fade-in complete. Final level: %.2f dB\n", bus.Index.Index, cmd.Target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusFadeoutCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-out effect." default:"5s"`
|
||||||
|
Target float64 ` help:"The target fader level (in dB)." default:"-90.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusFadeoutCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
currentLevel, err := ctx.Client.Bus.Fader(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get current fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel <= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f dB) is already at or below the target level (%.2f dB)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(currentLevel - cmd.Target)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel > cmd.Target {
|
||||||
|
currentLevel -= totalSteps / float64(cmd.Duration.Seconds()*1000/stepDuration.Seconds())
|
||||||
|
if currentLevel < cmd.Target {
|
||||||
|
currentLevel = cmd.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.SetFader(bus.Index.Index, currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set fader level: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d fade-out complete. Final level: %.2f dB\n", bus.Index.Index, cmd.Target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusNameCmd struct {
|
||||||
|
Name *string `arg:"" help:"The name to set for the bus. If not provided, the current name will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusNameCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Name == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Name(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d name: %s\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.SetName(bus.Index.Index, *cmd.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d name set to: %s\n", bus.Index.Index, *cmd.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqCmdGroup struct {
|
||||||
|
On BusEqOnCmd `help:"Get or set the EQ on/off state of the bus." cmd:"on"`
|
||||||
|
Mode BusEqModeCmd `help:"Get or set the EQ mode of the bus (graphic or parametric)." cmd:"mode"`
|
||||||
|
Band struct {
|
||||||
|
Band int `arg:"" help:"The EQ band number."`
|
||||||
|
Gain BusEqBandGainCmd `help:"Get or set the gain of the EQ band." cmd:"gain"`
|
||||||
|
Freq BusEqBandFreqCmd `help:"Get or set the frequency of the EQ band." cmd:"freq"`
|
||||||
|
Q BusEqBandQCmd `help:"Get or set the Q factor of the EQ band." cmd:"q"`
|
||||||
|
Type BusEqBandTypeCmd `help:"Get or set the type of the EQ band (bell, high shelf, low shelf, high pass, low pass)." cmd:"type"`
|
||||||
|
} `help:"Commands for controlling a specific EQ band of the bus." arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band < 1 || cmd.Band.Band > 6 {
|
||||||
|
return fmt.Errorf("EQ band number must be between 1 and 6")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqOnCmd struct {
|
||||||
|
State *string `arg:"" help:"The EQ on/off state to set (true or false). If not provided, the current EQ state will be returned." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqOnCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.On(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ on state: %t\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetOn(bus.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ on state set to: %s\n", bus.Index.Index, *cmd.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqModeCmd struct {
|
||||||
|
Mode *string `arg:"" help:"The EQ mode to set (graphic or parametric). If not provided, the current EQ mode will be returned." optional:"" enum:"peq,geq,teq"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqModeCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Mode == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.Mode(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ mode: %s\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetMode(bus.Index.Index, *cmd.Mode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ mode set to: %s\n", bus.Index.Index, *cmd.Mode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqBandGainCmd struct {
|
||||||
|
Gain *float64 `arg:"" help:"The gain to set for the EQ band (in dB). If not provided, the current gain will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqBandGainCmd) Run(ctx *context, bus *BusCmdGroup, busEq *BusEqCmdGroup) error {
|
||||||
|
if cmd.Gain == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.Gain(bus.Index.Index, busEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d gain: %.2f dB\n", bus.Index.Index, busEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetGain(bus.Index.Index, busEq.Band.Band, *cmd.Gain); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d gain set to: %.2f dB\n", bus.Index.Index, busEq.Band.Band, *cmd.Gain)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqBandFreqCmd struct {
|
||||||
|
Freq *float64 `arg:"" help:"The frequency to set for the EQ band (in Hz). If not provided, the current frequency will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqBandFreqCmd) Run(ctx *context, bus *BusCmdGroup, busEq *BusEqCmdGroup) error {
|
||||||
|
if cmd.Freq == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.Frequency(bus.Index.Index, busEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d frequency: %.2f Hz\n", bus.Index.Index, busEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetFrequency(bus.Index.Index, busEq.Band.Band, *cmd.Freq); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d frequency set to: %.2f Hz\n", bus.Index.Index, busEq.Band.Band, *cmd.Freq)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqBandQCmd struct {
|
||||||
|
Q *float64 `arg:"" help:"The Q factor to set for the EQ band. If not provided, the current Q factor will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqBandQCmd) Run(ctx *context, bus *BusCmdGroup, busEq *BusEqCmdGroup) error {
|
||||||
|
if cmd.Q == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.Q(bus.Index.Index, busEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d Q factor: %.2f\n", bus.Index.Index, busEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetQ(bus.Index.Index, busEq.Band.Band, *cmd.Q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d Q factor set to: %.2f\n", bus.Index.Index, busEq.Band.Band, *cmd.Q)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusEqBandTypeCmd struct {
|
||||||
|
Type *string `arg:"" help:"The type to set for the EQ band (bell, high shelf, low shelf, high pass, low pass). If not provided, the current type will be returned." optional:"" enum:"lcut,lshv,peq,veq,hshv,hcut"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusEqBandTypeCmd) Run(ctx *context, bus *BusCmdGroup, busEq *BusEqCmdGroup) error {
|
||||||
|
if cmd.Type == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Eq.Type(bus.Index.Index, busEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d type: %s\n", bus.Index.Index, busEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Eq.SetType(bus.Index.Index, busEq.Band.Band, *cmd.Type); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d EQ band %d type set to: %s\n", bus.Index.Index, busEq.Band.Band, *cmd.Type)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompCmdGroup struct {
|
||||||
|
On BusCompOnCmd `help:"Get or set the compressor on/off state of the bus." cmd:"on"`
|
||||||
|
Mode BusCompModeCmd `help:"Get or set the compressor mode of the bus (standard, vintage, or modern)." cmd:"mode"`
|
||||||
|
Threshold BusCompThresholdCmd `help:"Get or set the compressor threshold of the bus (in dB)." cmd:"threshold"`
|
||||||
|
Ratio BusCompRatioCmd `help:"Get or set the compressor ratio of the bus." cmd:"ratio"`
|
||||||
|
Mix BusCompMixCmd `help:"Get or set the compressor mix level of the bus (in %)." cmd:"mix"`
|
||||||
|
Makeup BusCompMakeupCmd `help:"Get or set the compressor makeup gain of the bus (in dB)." cmd:"makeup"`
|
||||||
|
Attack BusCompAttackCmd `help:"Get or set the compressor attack time of the bus (in ms)." cmd:"attack"`
|
||||||
|
Hold BusCompHoldCmd `help:"Get or set the compressor hold time of the bus (in ms)." cmd:"hold"`
|
||||||
|
Release BusCompReleaseCmd `help:"Get or set the compressor release time of the bus (in ms)." cmd:"release"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompOnCmd struct {
|
||||||
|
State *string `arg:"" help:"The compressor on/off state to set (true or false). If not provided, the current compressor state will be returned." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompOnCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.On(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor on state: %t\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetOn(bus.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor on state set to: %s\n", bus.Index.Index, *cmd.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompModeCmd struct {
|
||||||
|
Mode *string `arg:"" help:"The compressor mode to set (standard, vintage, or modern). If not provided, the current compressor mode will be returned." optional:"" enum:"comp,exp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompModeCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Mode == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Mode(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor mode: %s\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetMode(bus.Index.Index, *cmd.Mode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor mode set to: %s\n", bus.Index.Index, *cmd.Mode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompThresholdCmd struct {
|
||||||
|
Threshold *float64 `arg:"" help:"The compressor threshold to set (in dB). If not provided, the current compressor threshold will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompThresholdCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Threshold == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Threshold(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor threshold: %.2f dB\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetThreshold(bus.Index.Index, *cmd.Threshold); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor threshold set to: %.2f dB\n", bus.Index.Index, *cmd.Threshold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompRatioCmd struct {
|
||||||
|
Ratio *float64 `arg:"" help:"The compressor ratio to set. If not provided, the current compressor ratio will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompRatioCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Ratio == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Ratio(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor ratio: %.2f\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetRatio(bus.Index.Index, *cmd.Ratio); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor ratio set to: %.2f\n", bus.Index.Index, *cmd.Ratio)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompMixCmd struct {
|
||||||
|
Mix *float64 `arg:"" help:"The compressor mix level to set (in %). If not provided, the current compressor mix level will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompMixCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Mix == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Mix(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor mix level: %.2f%%\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetMix(bus.Index.Index, *cmd.Mix); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor mix level set to: %.2f%%\n", bus.Index.Index, *cmd.Mix)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompMakeupCmd struct {
|
||||||
|
Makeup *float64 `arg:"" help:"The compressor makeup gain to set (in dB). If not provided, the current compressor makeup gain will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompMakeupCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Makeup == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Makeup(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor makeup gain: %.2f dB\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetMakeup(bus.Index.Index, *cmd.Makeup); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor makeup gain set to: %.2f dB\n", bus.Index.Index, *cmd.Makeup)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompAttackCmd struct {
|
||||||
|
Attack *float64 `arg:"" help:"The compressor attack time to set (in ms). If not provided, the current compressor attack time will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompAttackCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Attack == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Attack(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor attack time: %.2f ms\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetAttack(bus.Index.Index, *cmd.Attack); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor attack time set to: %.2f ms\n", bus.Index.Index, *cmd.Attack)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompHoldCmd struct {
|
||||||
|
Hold *float64 `arg:"" help:"The compressor hold time to set (in ms). If not provided, the current compressor hold time will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompHoldCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Hold == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Hold(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor hold time: %.2f ms\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetHold(bus.Index.Index, *cmd.Hold); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor hold time set to: %.2f ms\n", bus.Index.Index, *cmd.Hold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusCompReleaseCmd struct {
|
||||||
|
Release *float64 `arg:"" help:"The compressor release time to set (in ms). If not provided, the current compressor release time will be returned."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *BusCompReleaseCmd) Run(ctx *context, bus *BusCmdGroup) error {
|
||||||
|
if cmd.Release == nil {
|
||||||
|
resp, err := ctx.Client.Bus.Comp.Release(bus.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor release time: %.2f ms\n", bus.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Bus.Comp.SetRelease(bus.Index.Index, *cmd.Release); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Bus %d compressor release time set to: %.2f ms\n", bus.Index.Index, *cmd.Release)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
935
cmd/bus.go
935
cmd/bus.go
@ -1,935 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// busCmd represents the bus command.
|
|
||||||
var busCmd = &cobra.Command{
|
|
||||||
Short: "Commands to control individual buses",
|
|
||||||
Long: `Commands to control individual buses of the XAir mixer, including mute status.`,
|
|
||||||
Use: "bus",
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busMuteCmd represents the bus mute command.
|
|
||||||
var busMuteCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus mute status",
|
|
||||||
Long: `Get or set the mute status of a specific bus.`,
|
|
||||||
Use: "mute [bus number] [true|false]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and mute status (true/false)")
|
|
||||||
}
|
|
||||||
|
|
||||||
busNum := mustConvToInt(args[0])
|
|
||||||
var muted bool
|
|
||||||
switch args[1] {
|
|
||||||
case "true", "1":
|
|
||||||
muted = true
|
|
||||||
case "false", "0":
|
|
||||||
muted = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid mute status. Use true/false or 1/0")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.SetMute(busNum, muted)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus mute status: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d mute set to %v\n", busNum, muted)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busFaderCmd represents the bus fader command.
|
|
||||||
var busFaderCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus fader level",
|
|
||||||
Long: `Get or set the fader level of a specific bus.
|
|
||||||
If no level argument is provided, the current fader level is retrieved.
|
|
||||||
If a level argument (in dB) is provided, the bus fader is set to that level.`,
|
|
||||||
Use: "fader [bus number] [level in dB]",
|
|
||||||
Example: ` # Get the current fader level of bus 1
|
|
||||||
xair-cli bus fader 1
|
|
||||||
|
|
||||||
# Set the fader level of bus 1 to -10.0 dB
|
|
||||||
xair-cli bus fader 1 -10.0`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
level, err := client.Bus.Fader(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d fader level: %.1f dB\n", busIndex, level)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and fader level (in dB)")
|
|
||||||
}
|
|
||||||
|
|
||||||
level := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.SetFader(busIndex, level)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d fader set to %.2f dB\n", busIndex, level)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busFadeOutCmd represents the bus fade out command.
|
|
||||||
var busFadeOutCmd = &cobra.Command{
|
|
||||||
Short: "Fade out the bus fader over a specified duration",
|
|
||||||
Long: "Fade out the bus fader to minimum level over a specified duration in seconds.",
|
|
||||||
Use: "fadeout [bus number] --duration [seconds] [target level in dB]",
|
|
||||||
Example: ` # Fade out bus 1 over 5 seconds
|
|
||||||
xair-cli bus fadeout 1 --duration 5s -- -90.0`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
duration, err := cmd.Flags().GetDuration("duration")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting duration flag: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
target := -90.0
|
|
||||||
if len(args) > 1 {
|
|
||||||
target = mustConvToFloat64(args[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFader, err := client.Bus.Fader(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting current bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate total steps needed to reach target dB
|
|
||||||
totalSteps := float64(currentFader - target)
|
|
||||||
if totalSteps <= 0 {
|
|
||||||
cmd.Println("Bus is already at or below target level")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
stepDelay := time.Duration(duration.Seconds()*1000/totalSteps) * time.Millisecond
|
|
||||||
|
|
||||||
for currentFader > target {
|
|
||||||
currentFader -= 1.0
|
|
||||||
err := client.Bus.SetFader(busIndex, currentFader)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
time.Sleep(stepDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Bus fade out completed")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// BusFadeInCmd represents the bus fade in command.
|
|
||||||
var busFadeInCmd = &cobra.Command{
|
|
||||||
Short: "Fade in the bus fader over a specified duration",
|
|
||||||
Long: "Fade in the bus fader to maximum level over a specified duration in seconds.",
|
|
||||||
Use: "fadein [bus number] --duration [seconds] [target level in dB]",
|
|
||||||
Example: ` # Fade in bus 1 over 5 seconds
|
|
||||||
xair-cli bus fadein 1 --duration 5s -- 0.0`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
duration, err := cmd.Flags().GetDuration("duration")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting duration flag: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
target := 0.0
|
|
||||||
if len(args) > 1 {
|
|
||||||
target = mustConvToFloat64(args[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFader, err := client.Bus.Fader(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting current bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate total steps needed to reach target dB
|
|
||||||
totalSteps := float64(target - currentFader)
|
|
||||||
if totalSteps <= 0 {
|
|
||||||
cmd.Println("Bus is already at or above target level")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
stepDelay := time.Duration(duration.Seconds()*1000/totalSteps) * time.Millisecond
|
|
||||||
|
|
||||||
for currentFader < target {
|
|
||||||
currentFader += 1.0
|
|
||||||
err := client.Bus.SetFader(busIndex, currentFader)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus fader level: %w", err)
|
|
||||||
}
|
|
||||||
time.Sleep(stepDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Bus fade in completed")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busNameCmd represents the bus name command.
|
|
||||||
var busNameCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus name",
|
|
||||||
Long: `Get or set the name of a specific bus.`,
|
|
||||||
Use: "name [bus number] [new name]",
|
|
||||||
Example: ` # Get the name of bus 1
|
|
||||||
xair-cli bus name 1
|
|
||||||
|
|
||||||
# Set the name of bus 1 to "Vocals"
|
|
||||||
xair-cli bus name 1 Vocals`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
name, err := client.Bus.Name(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus name: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d name: %s\n", busIndex, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
newName := args[1]
|
|
||||||
err := client.Bus.SetName(busIndex, newName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus name: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d name set to: %s\n", busIndex, newName)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqCmd represents the bus EQ command.
|
|
||||||
var busEqCmd = &cobra.Command{
|
|
||||||
Short: "Commands to control bus EQ settings",
|
|
||||||
Long: `Commands to control the EQ of individual buses, including turning the EQ on or off.`,
|
|
||||||
Use: "eq",
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqOnCmd represents the bus EQ on/off command.
|
|
||||||
var busEqOnCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ on/off status",
|
|
||||||
Long: `Get or set the EQ on/off status of a specific bus.`,
|
|
||||||
Use: "on [bus number] [true|false]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and EQ on status (true/false)")
|
|
||||||
}
|
|
||||||
|
|
||||||
busNum := mustConvToInt(args[0])
|
|
||||||
var eqOn bool
|
|
||||||
switch args[1] {
|
|
||||||
case "true", "1":
|
|
||||||
eqOn = true
|
|
||||||
case "false", "0":
|
|
||||||
eqOn = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid EQ on status. Use true/false or 1/0")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetOn(busNum, eqOn)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ on status: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ on set to %v\n", busNum, eqOn)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqModeCmd represents the bus EQ mode command.
|
|
||||||
var busEqModeCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ mode",
|
|
||||||
Long: `Get or set the EQ mode of a specific bus.`,
|
|
||||||
Use: "mode [bus number] [mode]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
modeNames := []string{"peq", "geq", "teq"}
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
mode, err := client.Bus.Eq.Mode(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus EQ mode: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d EQ mode: %s\n", busIndex, modeNames[mode])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := indexOf(modeNames, args[1])
|
|
||||||
if mode == -1 {
|
|
||||||
return fmt.Errorf("Invalid EQ mode. Valid modes are: %v", modeNames)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetMode(busIndex, mode)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ mode: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ mode set to %s\n", busIndex, modeNames[mode])
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqGainCmd represents the bus EQ gain command.
|
|
||||||
var busEqGainCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ gain for a specific band",
|
|
||||||
Long: `Get or set the EQ gain (in dB) for a specific band of a bus.
|
|
||||||
|
|
||||||
Gain values range from -15.0 dB to +15.0 dB.`,
|
|
||||||
Use: "gain [bus number] [band number] [gain in dB]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and band number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex, bandIndex := func() (int, int) {
|
|
||||||
return mustConvToInt(args[0]), mustConvToInt(args[1])
|
|
||||||
}()
|
|
||||||
|
|
||||||
if len(args) == 2 {
|
|
||||||
gain, err := client.Bus.Eq.Gain(busIndex, bandIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus EQ gain: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d EQ band %d gain: %.1f dB\n", busIndex, bandIndex, gain)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 3 {
|
|
||||||
return fmt.Errorf("Please provide bus number, band number, and gain (in dB)")
|
|
||||||
}
|
|
||||||
|
|
||||||
gain := mustConvToFloat64(args[2])
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetGain(busIndex, bandIndex, gain)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ gain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ band %d gain set to %.1f dB\n", busIndex, bandIndex, gain)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqFreqCmd represents the bus EQ frequency command.
|
|
||||||
var busEqFreqCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ frequency for a specific band",
|
|
||||||
Long: `Get or set the EQ frequency (in Hz) for a specific band of a bus.`,
|
|
||||||
Use: "freq [bus number] [band number] [frequency in Hz]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and band number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex, bandIndex := func() (int, int) {
|
|
||||||
return mustConvToInt(args[0]), mustConvToInt(args[1])
|
|
||||||
}()
|
|
||||||
|
|
||||||
if len(args) == 2 {
|
|
||||||
freq, err := client.Bus.Eq.Frequency(busIndex, bandIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus EQ frequency: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d EQ band %d frequency: %.1f Hz\n", busIndex, bandIndex, freq)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 3 {
|
|
||||||
return fmt.Errorf("Please provide bus number, band number, and frequency (in Hz)")
|
|
||||||
}
|
|
||||||
|
|
||||||
freq := mustConvToFloat64(args[2])
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetFrequency(busIndex, bandIndex, freq)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ frequency: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ band %d frequency set to %.1f Hz\n", busIndex, bandIndex, freq)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqQCmd represents the bus EQ Q command.
|
|
||||||
var busEqQCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ Q factor for a specific band",
|
|
||||||
Long: `Get or set the EQ Q factor for a specific band of a bus.`,
|
|
||||||
Use: "q [bus number] [band number] [Q factor]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and band number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex, bandIndex := func() (int, int) {
|
|
||||||
return mustConvToInt(args[0]), mustConvToInt(args[1])
|
|
||||||
}()
|
|
||||||
|
|
||||||
if len(args) == 2 {
|
|
||||||
qFactor, err := client.Bus.Eq.Q(busIndex, bandIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus EQ Q factor: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d EQ band %d Q factor: %.2f\n", busIndex, bandIndex, qFactor)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 3 {
|
|
||||||
return fmt.Errorf("Please provide bus number, band number, and Q factor")
|
|
||||||
}
|
|
||||||
|
|
||||||
qFactor := mustConvToFloat64(args[2])
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetQ(busIndex, bandIndex, qFactor)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ Q factor: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ band %d Q factor set to %.2f\n", busIndex, bandIndex, qFactor)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busEqTypeCmd represents the bus EQ type command.
|
|
||||||
var busEqTypeCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus EQ band type",
|
|
||||||
Long: `Get or set the EQ band type for a specific band of a bus.`,
|
|
||||||
Use: "type [bus number] [band number] [type]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and band number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex, bandIndex := func() (int, int) {
|
|
||||||
return mustConvToInt(args[0]), mustConvToInt(args[1])
|
|
||||||
}()
|
|
||||||
|
|
||||||
eqTypeNames := []string{"lcut", "lshv", "peq", "veq", "hshv", "hcut"}
|
|
||||||
|
|
||||||
if len(args) == 2 {
|
|
||||||
currentType, err := client.Bus.Eq.Type(busIndex, bandIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus EQ band type: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d EQ band %d type: %s\n", busIndex, bandIndex, eqTypeNames[currentType])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
eqType := indexOf(eqTypeNames, args[2])
|
|
||||||
if eqType == -1 {
|
|
||||||
return fmt.Errorf("Invalid EQ band type. Valid types are: %v", eqTypeNames)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.Eq.SetType(busIndex, bandIndex, eqType)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus EQ band type: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d EQ band %d type set to %s\n", busIndex, bandIndex, eqTypeNames[eqType])
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busCompCmd represents the bus Compressor command.
|
|
||||||
var busCompCmd = &cobra.Command{
|
|
||||||
Short: "Commands to control bus Compressor settings",
|
|
||||||
Long: `Commands to control the Compressor of individual buses, including turning the Compressor on or off.`,
|
|
||||||
Use: "comp",
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busCompOnCmd represents the bus Compressor on/off command.
|
|
||||||
var busCompOnCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor on/off status",
|
|
||||||
Long: `Get or set the Compressor on/off status of a specific bus.`,
|
|
||||||
Use: "on [bus number] [true|false]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and Compressor on status (true/false)")
|
|
||||||
}
|
|
||||||
|
|
||||||
busNum := mustConvToInt(args[0])
|
|
||||||
var compOn bool
|
|
||||||
switch args[1] {
|
|
||||||
case "true", "1":
|
|
||||||
compOn = true
|
|
||||||
case "false", "0":
|
|
||||||
compOn = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid Compressor on status. Use true/false or 1/0")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetOn(busNum, compOn)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor on status: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor on set to %v\n", busNum, compOn)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busCompModeCmd represents the bus Compressor mode command.
|
|
||||||
var busCompModeCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor mode",
|
|
||||||
Long: `Get or set the Compressor mode of a specific bus.`,
|
|
||||||
Use: "mode [bus number] [mode]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
mode, err := client.Bus.Comp.Mode(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor mode: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor mode: %s\n", busIndex, mode)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := args[1]
|
|
||||||
if !contains([]string{"comp", "exp"}, mode) {
|
|
||||||
return fmt.Errorf("Invalid mode value. Valid values are: comp, exp")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetMode(busIndex, mode)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor mode: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor mode set to %s\n", busIndex, mode)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busCompThresholdCmd represents the bus Compressor threshold command.
|
|
||||||
var busCompThresholdCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor threshold",
|
|
||||||
Long: `Get or set the Compressor threshold (in dB) for a specific bus.`,
|
|
||||||
Use: "threshold [bus number] [threshold in dB]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
threshold, err := client.Bus.Comp.Threshold(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor threshold: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor threshold: %.1f dB\n", busIndex, threshold)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and threshold (in dB)")
|
|
||||||
}
|
|
||||||
|
|
||||||
threshold := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetThreshold(busIndex, threshold)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor threshold: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor threshold set to %.1f dB\n", busIndex, threshold)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busCompRatioCmd represents the bus Compressor ratio command.
|
|
||||||
var busCompRatioCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor ratio",
|
|
||||||
Long: `Get or set the Compressor ratio for a specific bus.`,
|
|
||||||
Use: "ratio [bus number] [ratio]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
ratio, err := client.Bus.Comp.Ratio(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor ratio: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor ratio: %.2f\n", busIndex, ratio)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and ratio")
|
|
||||||
}
|
|
||||||
|
|
||||||
ratio := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetRatio(busIndex, ratio)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor ratio: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor ratio set to %.2f\n", busIndex, ratio)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busMixCmd represents the bus Compressor mix command.
|
|
||||||
var busCompMixCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor mix",
|
|
||||||
Long: `Get or set the Compressor mix (0-100%) for a specific bus.`,
|
|
||||||
Use: "mix [bus number] [mix percentage]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
mix, err := client.Bus.Comp.Mix(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor mix: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor mix: %.1f%%\n", busIndex, mix)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and mix percentage")
|
|
||||||
}
|
|
||||||
|
|
||||||
mix := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetMix(busIndex, mix)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor mix: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor mix set to %.1f%%\n", busIndex, mix)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busMakeUpCmd represents the bus Compressor make-up gain command.
|
|
||||||
var busCompMakeUpCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor make-up gain",
|
|
||||||
Long: `Get or set the Compressor make-up gain (in dB) for a specific bus.`,
|
|
||||||
Use: "makeup [bus number] [make-up gain in dB]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
makeUp, err := client.Bus.Comp.MakeUp(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor make-up gain: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor make-up gain: %.1f dB\n", busIndex, makeUp)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and make-up gain (in dB)")
|
|
||||||
}
|
|
||||||
|
|
||||||
makeUp := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetMakeUp(busIndex, makeUp)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor make-up gain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor make-up gain set to %.1f dB\n", busIndex, makeUp)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busAttackCmd represents the bus Compressor attack time command.
|
|
||||||
var busCompAttackCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor attack time",
|
|
||||||
Long: `Get or set the Compressor attack time (in milliseconds) for a specific bus.`,
|
|
||||||
Use: "attack [bus number] [attack time in ms]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
attack, err := client.Bus.Comp.Attack(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor attack time: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor attack time: %.1f ms\n", busIndex, attack)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and attack time (in ms)")
|
|
||||||
}
|
|
||||||
|
|
||||||
attack := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetAttack(busIndex, attack)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor attack time: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor attack time set to %.1f ms\n", busIndex, attack)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busHoldCmd represents the bus Compressor hold time command.
|
|
||||||
var busCompHoldCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor hold time",
|
|
||||||
Long: `Get or set the Compressor hold time (in milliseconds) for a specific bus.`,
|
|
||||||
Use: "hold [bus number] [hold time in ms]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
hold, err := client.Bus.Comp.Hold(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor hold time: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor hold time: %.2f ms\n", busIndex, hold)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and hold time (in ms)")
|
|
||||||
}
|
|
||||||
|
|
||||||
hold := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetHold(busIndex, hold)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor hold time: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor hold time set to %.2f ms\n", busIndex, hold)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// busReleaseCmd represents the bus Compressor release time command.
|
|
||||||
var busCompReleaseCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the bus Compressor release time",
|
|
||||||
Long: `Get or set the Compressor release time (in milliseconds) for a specific bus.`,
|
|
||||||
Use: "release [bus number] [release time in ms]",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide bus number")
|
|
||||||
}
|
|
||||||
|
|
||||||
busIndex := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
release, err := client.Bus.Comp.Release(busIndex)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting bus Compressor release time: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Bus %d Compressor release time: %.1f ms\n", busIndex, release)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide bus number and release time (in ms)")
|
|
||||||
}
|
|
||||||
|
|
||||||
release := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
err := client.Bus.Comp.SetRelease(busIndex, release)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting bus Compressor release time: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Bus %d Compressor release time set to %.1f ms\n", busIndex, release)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(busCmd)
|
|
||||||
|
|
||||||
busCmd.AddCommand(busMuteCmd)
|
|
||||||
busCmd.AddCommand(busFaderCmd)
|
|
||||||
busCmd.AddCommand(busFadeOutCmd)
|
|
||||||
busFadeOutCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration for fade out in seconds")
|
|
||||||
busCmd.AddCommand(busFadeInCmd)
|
|
||||||
busFadeInCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration for fade in in seconds")
|
|
||||||
busCmd.AddCommand(busNameCmd)
|
|
||||||
|
|
||||||
busCmd.AddCommand(busEqCmd)
|
|
||||||
busEqCmd.AddCommand(busEqOnCmd)
|
|
||||||
busEqCmd.AddCommand(busEqModeCmd)
|
|
||||||
busEqCmd.AddCommand(busEqGainCmd)
|
|
||||||
busEqCmd.AddCommand(busEqFreqCmd)
|
|
||||||
busEqCmd.AddCommand(busEqQCmd)
|
|
||||||
busEqCmd.AddCommand(busEqTypeCmd)
|
|
||||||
|
|
||||||
busCmd.AddCommand(busCompCmd)
|
|
||||||
busCompCmd.AddCommand(busCompOnCmd)
|
|
||||||
busCompCmd.AddCommand(busCompModeCmd)
|
|
||||||
busCompCmd.AddCommand(busCompThresholdCmd)
|
|
||||||
busCompCmd.AddCommand(busCompRatioCmd)
|
|
||||||
busCompCmd.AddCommand(busCompMixCmd)
|
|
||||||
busCompCmd.AddCommand(busCompMakeUpCmd)
|
|
||||||
busCompCmd.AddCommand(busCompAttackCmd)
|
|
||||||
busCompCmd.AddCommand(busCompHoldCmd)
|
|
||||||
busCompCmd.AddCommand(busCompReleaseCmd)
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/onyx-and-iris/xair-cli/internal/xair"
|
|
||||||
)
|
|
||||||
|
|
||||||
type clientKey string
|
|
||||||
|
|
||||||
// WithContext returns a new context with the provided xair.Client.
|
|
||||||
func WithContext(ctx context.Context, client *xair.Client) context.Context {
|
|
||||||
return context.WithValue(ctx, clientKey("oscClient"), client)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientFromContext retrieves the xair.Client from the context.
|
|
||||||
func ClientFromContext(ctx context.Context) *xair.Client {
|
|
||||||
if client, ok := ctx.Value(clientKey("oscClient")).(*xair.Client); ok {
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
211
cmd/headamp.go
211
cmd/headamp.go
@ -1,211 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/log"
|
|
||||||
"github.com/onyx-and-iris/xair-cli/internal/xair"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// headampCmd represents the headamp command
|
|
||||||
var headampCmd = &cobra.Command{
|
|
||||||
Short: "Commands to control headamp gain and phantom power",
|
|
||||||
Long: `Commands to control the headamp gain and phantom power settings of the XAir mixer.
|
|
||||||
|
|
||||||
You can get or set the gain level for individual headamps, as well as enable or disable phantom power.`,
|
|
||||||
Use: "headamp",
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// headampGainCmd represents the headamp gain command
|
|
||||||
var headampGainCmd = &cobra.Command{
|
|
||||||
Use: "gain",
|
|
||||||
Short: "Get or set headamp gain level",
|
|
||||||
Long: `Get or set the gain level for a specified headamp index.
|
|
||||||
When setting gain, it will gradually increase from the current level to prevent
|
|
||||||
sudden jumps that could cause feedback or equipment damage.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
# Get gain level for headamp index 1
|
|
||||||
xair-cli headamp gain 1
|
|
||||||
# Set gain level for headamp index 1 to 3.5 dB (gradually over 5 seconds)
|
|
||||||
xair-cli headamp gain 1 3.5
|
|
||||||
# Set gain level for headamp index 1 to 3.5 dB over 10 seconds
|
|
||||||
xair-cli headamp gain 1 3.5 --duration 10s`,
|
|
||||||
Args: cobra.RangeArgs(1, 2),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide a headamp index")
|
|
||||||
}
|
|
||||||
|
|
||||||
index := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
gain, err := client.HeadAmp.Gain(index)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting headamp gain level: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Headamp %d Gain: %.2f dB\n", index, gain)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide a gain level in dB")
|
|
||||||
}
|
|
||||||
|
|
||||||
targetLevel := mustConvToFloat64(args[1])
|
|
||||||
|
|
||||||
currentGain, err := client.HeadAmp.Gain(index)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting current headamp gain level: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
duration, err := cmd.Flags().GetDuration("duration")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting duration flag: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if currentGain == targetLevel {
|
|
||||||
cmd.Printf("Headamp %d Gain already at %.2f dB\n", index, targetLevel)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := gradualGainAdjust(client, cmd, index, currentGain, targetLevel, duration); err != nil {
|
|
||||||
return fmt.Errorf("Error adjusting headamp gain level: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Headamp %d Gain set to %.2f dB\n", index, targetLevel)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// gradualGainAdjust gradually adjusts gain from current to target over specified duration
|
|
||||||
func gradualGainAdjust(
|
|
||||||
client *xair.Client,
|
|
||||||
cmd *cobra.Command,
|
|
||||||
index int,
|
|
||||||
currentGain, targetGain float64,
|
|
||||||
duration time.Duration,
|
|
||||||
) error {
|
|
||||||
gainDiff := targetGain - currentGain
|
|
||||||
|
|
||||||
stepInterval := 100 * time.Millisecond
|
|
||||||
totalSteps := int(duration / stepInterval)
|
|
||||||
|
|
||||||
if totalSteps < 1 {
|
|
||||||
totalSteps = 1
|
|
||||||
stepInterval = duration
|
|
||||||
}
|
|
||||||
|
|
||||||
stepIncrement := gainDiff / float64(totalSteps)
|
|
||||||
|
|
||||||
log.Debugf("Adjusting Headamp %d gain from %.2f dB to %.2f dB over %v...\n",
|
|
||||||
index, currentGain, targetGain, duration)
|
|
||||||
|
|
||||||
for step := 1; step <= totalSteps; step++ {
|
|
||||||
newGain := currentGain + (stepIncrement * float64(step))
|
|
||||||
|
|
||||||
if step == totalSteps {
|
|
||||||
newGain = targetGain
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.HeadAmp.SetGain(index, newGain)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if step%10 == 0 || step == totalSteps {
|
|
||||||
log.Debugf(" Step %d/%d: %.2f dB\n", step, totalSteps, newGain)
|
|
||||||
}
|
|
||||||
|
|
||||||
if step < totalSteps {
|
|
||||||
time.Sleep(stepInterval)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// headampPhantomPowerCmd represents the headamp phantom power command
|
|
||||||
var headampPhantomPowerCmd = &cobra.Command{
|
|
||||||
Use: "phantom",
|
|
||||||
Short: "Get or set headamp phantom power status",
|
|
||||||
Long: `Get or set the phantom power status for a specified headamp index.
|
|
||||||
Examples:
|
|
||||||
# Get phantom power status for headamp index 1
|
|
||||||
xairctl headamp phantom 1
|
|
||||||
# Enable phantom power for headamp index 1
|
|
||||||
xairctl headamp phantom 1 on
|
|
||||||
# Disable phantom power for headamp index 1
|
|
||||||
xairctl headamp phantom 1 off`,
|
|
||||||
Args: cobra.RangeArgs(1, 2),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return fmt.Errorf("Please provide a headamp index")
|
|
||||||
}
|
|
||||||
|
|
||||||
index := mustConvToInt(args[0])
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
enabled, err := client.HeadAmp.PhantomPower(index)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting headamp phantom power status: %w", err)
|
|
||||||
}
|
|
||||||
status := "disabled"
|
|
||||||
if enabled {
|
|
||||||
status = "enabled"
|
|
||||||
}
|
|
||||||
cmd.Printf("Headamp %d Phantom Power is %s\n", index, status)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 2 {
|
|
||||||
return fmt.Errorf("Please provide phantom power status: on or off")
|
|
||||||
}
|
|
||||||
|
|
||||||
var enable bool
|
|
||||||
switch args[1] {
|
|
||||||
case "on", "enable":
|
|
||||||
enable = true
|
|
||||||
case "off", "disable":
|
|
||||||
enable = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid phantom power status. Use 'on' or 'off'")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.HeadAmp.SetPhantomPower(index, enable)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting headamp phantom power status: %w", err)
|
|
||||||
}
|
|
||||||
status := "disabled"
|
|
||||||
if enable {
|
|
||||||
status = "enabled"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Printf("Headamp %d Phantom Power %s successfully\n", index, status)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(headampCmd)
|
|
||||||
|
|
||||||
headampCmd.AddCommand(headampGainCmd)
|
|
||||||
headampGainCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration over which to gradually adjust gain")
|
|
||||||
|
|
||||||
headampCmd.AddCommand(headampPhantomPowerCmd)
|
|
||||||
}
|
|
||||||
237
cmd/main.go
237
cmd/main.go
@ -1,237 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// mainCmd represents the main command.
|
|
||||||
var mainCmd = &cobra.Command{
|
|
||||||
Short: "Commands to control the main output",
|
|
||||||
Long: `Commands to control the main output of the XAir mixer, including fader level and mute status.`,
|
|
||||||
Use: "main",
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// mainMuteCmd represents the main mute command.
|
|
||||||
var mainMuteCmd = &cobra.Command{
|
|
||||||
Short: "Get or set the main LR mute status",
|
|
||||||
Long: `Get or set the main L/R mute status.
|
|
||||||
|
|
||||||
If no argument is provided, the current mute status is retrieved.
|
|
||||||
If "true" or "1" is provided as an argument, the main output is muted.
|
|
||||||
If "false" or "0" is provided, the main output is unmuted.`,
|
|
||||||
Use: "mute [true|false]",
|
|
||||||
Example: ` # Get the current main LR mute status
|
|
||||||
xair-cli main mute
|
|
||||||
|
|
||||||
# Mute the main output
|
|
||||||
xair-cli main mute true
|
|
||||||
|
|
||||||
# Unmute the main output
|
|
||||||
xair-cli main mute false`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) == 0 {
|
|
||||||
resp, err := client.Main.Mute()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting main LR mute status: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Main LR mute: %v\n", resp)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var muted bool
|
|
||||||
switch args[0] {
|
|
||||||
case "true", "1":
|
|
||||||
muted = true
|
|
||||||
case "false", "0":
|
|
||||||
muted = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid mute status. Use true/false or 1/0")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Main.SetMute(muted)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting main LR mute status: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Main LR mute status set successfully")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// mainFaderCmd represents the main fader command.
|
|
||||||
var mainFaderCmd = &cobra.Command{
|
|
||||||
Short: "Set or get the main LR fader level",
|
|
||||||
Long: `Set or get the main L/R fader level in dB.
|
|
||||||
|
|
||||||
If no argument is provided, the current fader level is retrieved.
|
|
||||||
If a dB value is provided as an argument, the fader level is set to that value.`,
|
|
||||||
Use: "fader [level in dB]",
|
|
||||||
Example: ` # Get the current main LR fader level
|
|
||||||
xair-cli main fader
|
|
||||||
|
|
||||||
# Set the main LR fader level to -10.0 dB
|
|
||||||
xair-cli main fader -- -10.0`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("OSC client not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) == 0 {
|
|
||||||
resp, err := client.Main.Fader()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting main LR fader: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Printf("Main LR fader: %.1f dB\n", resp)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.Main.SetFader(mustConvToFloat64(args[0]))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error setting main LR fader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Main LR fader set successfully")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// mainFadeOutCmd represents the main fadeout command.
|
|
||||||
var mainFadeOutCmd = &cobra.Command{
|
|
||||||
Short: "Fade out the main output",
|
|
||||||
Long: `Fade out the main output over a specified duration.
|
|
||||||
|
|
||||||
This command will fade out the main output to the specified dB level.
|
|
||||||
`,
|
|
||||||
Use: "fadeout --duration [seconds] [target_db]",
|
|
||||||
Example: ` # Fade out main output over 5 seconds
|
|
||||||
xair-cli main fadeout --duration 5s -- -90.0`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
cmd.PrintErrln("OSC client not found in context")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
duration, err := cmd.Flags().GetDuration("duration")
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error getting duration flag:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default target for fadeout
|
|
||||||
target := -90.0
|
|
||||||
if len(args) > 0 {
|
|
||||||
target = mustConvToFloat64(args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFader, err := client.Main.Fader()
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error getting current main LR fader:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate total steps needed to reach target dB
|
|
||||||
totalSteps := float64(currentFader - target)
|
|
||||||
if totalSteps <= 0 {
|
|
||||||
cmd.Println("Main output is already faded out")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate delay per step to achieve exact duration
|
|
||||||
stepDelay := time.Duration(duration.Seconds()*1000/totalSteps) * time.Millisecond
|
|
||||||
|
|
||||||
for currentFader > target {
|
|
||||||
currentFader -= 1.0
|
|
||||||
err = client.Main.SetFader(currentFader)
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error setting main LR fader:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(stepDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Main output faded out successfully")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// mainFadeInCmd represents the main fadein command.
|
|
||||||
var mainFadeInCmd = &cobra.Command{
|
|
||||||
Short: "Fade in the main output",
|
|
||||||
Long: `Fade in the main output over a specified duration.
|
|
||||||
|
|
||||||
This command will fade in the main output to the specified dB level.
|
|
||||||
`,
|
|
||||||
Use: "fadein --duration [seconds] [target_db]",
|
|
||||||
Example: ` # Fade in main output over 5 seconds
|
|
||||||
xair-cli main fadein --duration 5s -- 0.0`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
cmd.PrintErrln("OSC client not found in context")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
duration, err := cmd.Flags().GetDuration("duration")
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error getting duration flag:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
target := 0.0
|
|
||||||
if len(args) > 0 {
|
|
||||||
target = mustConvToFloat64(args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFader, err := client.Main.Fader()
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error getting current main LR fader:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate total steps needed to reach target dB
|
|
||||||
totalSteps := float64(target - currentFader)
|
|
||||||
if totalSteps <= 0 {
|
|
||||||
cmd.Println("Main output is already at or above target level")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate delay per step to achieve exact duration
|
|
||||||
stepDelay := time.Duration(duration.Seconds()*1000/totalSteps) * time.Millisecond
|
|
||||||
|
|
||||||
for currentFader < target {
|
|
||||||
currentFader += 1.0
|
|
||||||
err = client.Main.SetFader(currentFader)
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln("Error setting main LR fader:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(stepDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Main output faded in successfully")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(mainCmd)
|
|
||||||
|
|
||||||
mainCmd.AddCommand(mainMuteCmd)
|
|
||||||
|
|
||||||
mainCmd.AddCommand(mainFaderCmd)
|
|
||||||
mainCmd.AddCommand(mainFadeOutCmd)
|
|
||||||
mainFadeOutCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration for fade out in seconds")
|
|
||||||
mainCmd.AddCommand(mainFadeInCmd)
|
|
||||||
mainFadeInCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration for fade in in seconds")
|
|
||||||
}
|
|
||||||
58
cmd/raw.go
58
cmd/raw.go
@ -1,58 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// rawCmd represents the raw command
|
|
||||||
var rawCmd = &cobra.Command{
|
|
||||||
Short: "Send a raw OSC message to the mixer",
|
|
||||||
Long: `Send a raw OSC message to the mixer.
|
|
||||||
You need to provide the OSC address and any parameters as arguments.
|
|
||||||
|
|
||||||
Optionally provide a timeout duration to wait for a response from the mixer. Default is 200ms.`,
|
|
||||||
Use: "raw",
|
|
||||||
Example: ` xair-cli raw /xinfo
|
|
||||||
xair-cli raw /ch/01/mix/fader 0.75
|
|
||||||
xair-cli raw --timeout 500ms /bus/2/mix/on 1`,
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("no client found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
command := args[0]
|
|
||||||
params := make([]any, len(args[1:]))
|
|
||||||
for i, arg := range args[1:] {
|
|
||||||
params[i] = arg
|
|
||||||
}
|
|
||||||
if err := client.SendMessage(command, params...); err != nil {
|
|
||||||
return fmt.Errorf("error sending message: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout, err := cmd.Flags().GetDuration("timeout")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting timeout flag: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := client.ReceiveMessage(timeout)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error receiving message: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg != nil {
|
|
||||||
fmt.Printf("Received response: %v\n", msg)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(rawCmd)
|
|
||||||
|
|
||||||
rawCmd.Flags().DurationP("timeout", "t", 200*time.Millisecond, "Timeout duration for receiving a response")
|
|
||||||
}
|
|
||||||
106
cmd/root.go
106
cmd/root.go
@ -1,106 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"runtime/debug"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/log"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
|
|
||||||
"github.com/onyx-and-iris/xair-cli/internal/xair"
|
|
||||||
)
|
|
||||||
|
|
||||||
var version string // Version of the CLI, set during build time
|
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands.
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "xair-cli",
|
|
||||||
Short: "A command-line utility to interact with Behringer X Air mixers via OSC",
|
|
||||||
Long: `xair-cli is a command-line tool that allows users to send OSC messages
|
|
||||||
to Behringer X Air mixers for remote control and configuration. It supports
|
|
||||||
various commands to manage mixer settings directly from the terminal.`,
|
|
||||||
Version: versionFromBuild(),
|
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
|
||||||
level, err := log.ParseLevel(viper.GetString("loglevel"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.SetLevel(level)
|
|
||||||
|
|
||||||
kind := viper.GetString("kind")
|
|
||||||
log.Debugf("Initialising client for mixer kind: %s", kind)
|
|
||||||
|
|
||||||
if kind == "x32" && !viper.IsSet("port") {
|
|
||||||
viper.Set("port", 10023)
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := xair.NewClient(
|
|
||||||
viper.GetString("host"),
|
|
||||||
viper.GetInt("port"),
|
|
||||||
xair.WithKind(kind),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd.SetContext(WithContext(cmd.Context(), client))
|
|
||||||
|
|
||||||
client.StartListening()
|
|
||||||
err, resp := client.RequestInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Received mixer info: %+v", resp)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
PersistentPostRunE: func(cmd *cobra.Command, _ []string) error {
|
|
||||||
client := ClientFromContext(cmd.Context())
|
|
||||||
if client != nil {
|
|
||||||
client.Stop()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
cmd.Help()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
|
||||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
|
||||||
func Execute() {
|
|
||||||
err := rootCmd.Execute()
|
|
||||||
if err != nil {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.PersistentFlags().StringP("host", "H", "mixer.local", "host address of the X Air mixer")
|
|
||||||
rootCmd.PersistentFlags().IntP("port", "p", 10024, "Port number of the X Air mixer")
|
|
||||||
rootCmd.PersistentFlags().
|
|
||||||
StringP("loglevel", "l", "warn", "Log level (debug, info, warn, error, fatal, panic)")
|
|
||||||
rootCmd.PersistentFlags().StringP("kind", "k", "xair", "Kind of mixer (xair, x32)")
|
|
||||||
|
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
|
||||||
viper.SetEnvPrefix("XAIR_CLI")
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
viper.BindPFlag("host", rootCmd.PersistentFlags().Lookup("host"))
|
|
||||||
viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))
|
|
||||||
viper.BindPFlag("loglevel", rootCmd.PersistentFlags().Lookup("loglevel"))
|
|
||||||
viper.BindPFlag("kind", rootCmd.PersistentFlags().Lookup("kind"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func versionFromBuild() string {
|
|
||||||
if version == "" {
|
|
||||||
info, ok := debug.ReadBuildInfo()
|
|
||||||
if !ok {
|
|
||||||
return "(unable to read version)"
|
|
||||||
}
|
|
||||||
version = strings.Split(info.Main.Version, "-")[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return version
|
|
||||||
}
|
|
||||||
1354
cmd/strip.go
1354
cmd/strip.go
File diff suppressed because it is too large
Load Diff
38
cmd/util.go
38
cmd/util.go
@ -1,38 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// mustConvToFloat64 converts a string to float64, panicking on error.
|
|
||||||
func mustConvToFloat64(floatStr string) float64 {
|
|
||||||
level, err := strconv.ParseFloat(floatStr, 64)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return level
|
|
||||||
}
|
|
||||||
|
|
||||||
// mustConvToInt converts a string to int, panicking on error.
|
|
||||||
func mustConvToInt(intStr string) int {
|
|
||||||
val, err := strconv.Atoi(intStr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
// generic indexOf returns the index of elem in slice, or -1 if not found.
|
|
||||||
func indexOf[T comparable](slice []T, elem T) int {
|
|
||||||
for i, v := range slice {
|
|
||||||
if v == elem {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// generic contains checks if elem is in slice.
|
|
||||||
func contains[T comparable](slice []T, elem T) bool {
|
|
||||||
return indexOf(slice, elem) != -1
|
|
||||||
}
|
|
||||||
22
go.mod
22
go.mod
@ -1,12 +1,12 @@
|
|||||||
module github.com/onyx-and-iris/xair-cli
|
module github.com/onyx-and-iris/xair-cli
|
||||||
|
|
||||||
go 1.24.2
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/alecthomas/kong v1.13.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/spf13/cobra v1.10.2
|
github.com/jotaen/kong-completion v0.0.11
|
||||||
github.com/spf13/viper v1.21.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -19,25 +19,17 @@ require (
|
|||||||
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.5.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
|
||||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||||
github.com/muesli/termenv v0.16.0 // indirect
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/posener/complete v1.2.3 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
|
||||||
github.com/spf13/afero v1.15.0 // indirect
|
|
||||||
github.com/spf13/cast v1.10.0 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.10 // indirect
|
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // 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.40.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
63
go.sum
63
go.sum
@ -1,3 +1,9 @@
|
|||||||
|
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/kong v1.13.0 h1:5e/7XC3ugvhP1DQBmTS+WuHtCbcv44hsohMgcvVxSrA=
|
||||||
|
github.com/alecthomas/kong v1.13.0/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I=
|
||||||
|
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/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
|
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
|
||||||
@ -18,27 +24,25 @@ github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfa
|
|||||||
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.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
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=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
|
||||||
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
||||||
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
||||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
|
||||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5 h1:fqwINudmUrvGCuw+e3tedZ2UJ0hklSw6t8UPomctKyQ=
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5 h1:fqwINudmUrvGCuw+e3tedZ2UJ0hklSw6t8UPomctKyQ=
|
||||||
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5/go.mod h1:lqMjoCs0y0GoRRujSPZRBaGb4c5ER6TfkFKSClxkMbY=
|
github.com/hypebeast/go-osc v0.0.0-20220308234300-cec5a8a1e5f5/go.mod h1:lqMjoCs0y0GoRRujSPZRBaGb4c5ER6TfkFKSClxkMbY=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/jotaen/kong-completion v0.0.11 h1:ZRyQt+IwjcAObbiyxJZ3YR7r/o/f6HYidTK1+7YNtnE=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/jotaen/kong-completion v0.0.11/go.mod h1:dyIG20e3qq128SUBtF8jzI7YtkfzjWMlgbqkAJd6xHQ=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
@ -47,45 +51,26 @@ github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byF
|
|||||||
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
|
||||||
|
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
|
||||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
|
||||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
|
||||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
|
||||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
|
||||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
|
||||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
|
||||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
|
||||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
|
||||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
|
||||||
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.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
|
||||||
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/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
124
headamp.go
Normal file
124
headamp.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HeadampCmdGroup struct {
|
||||||
|
Index struct {
|
||||||
|
Index int `arg:"" help:"The index of the headamp."`
|
||||||
|
Gain HeadampGainCmd `help:"Get or set the gain of the headamp." cmd:""`
|
||||||
|
Phantom HeadampPhantomCmd `help:"Get or set the phantom power state of the headamp." cmd:""`
|
||||||
|
} `arg:"" help:"Control a specific headamp by index."`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeadampGainCmd struct {
|
||||||
|
Duration time.Duration `help:"The duration of the fade in/out when setting the gain." default:"5s"`
|
||||||
|
Gain *float64 `help:"The gain of the headamp in dB." arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *HeadampGainCmd) Run(ctx *context, headamp *HeadampCmdGroup) error {
|
||||||
|
if cmd.Gain == nil {
|
||||||
|
resp, err := ctx.Client.HeadAmp.Gain(headamp.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get headamp gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Headamp %d gain: %.2f dB\n", headamp.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGain, err := ctx.Client.HeadAmp.Gain(headamp.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get current headamp gain: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gradualGainAdjust(ctx, headamp.Index.Index, currentGain, *cmd.Gain, cmd.Duration); err != nil {
|
||||||
|
return fmt.Errorf("failed to set headamp gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Headamp %d gain set to: %.2f dB\n", headamp.Index.Index, *cmd.Gain)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// gradualGainAdjust gradually adjusts gain from current to target over specified duration
|
||||||
|
func gradualGainAdjust(
|
||||||
|
ctx *context,
|
||||||
|
index int,
|
||||||
|
currentGain, targetGain float64,
|
||||||
|
duration time.Duration,
|
||||||
|
) error {
|
||||||
|
gainDiff := targetGain - currentGain
|
||||||
|
|
||||||
|
stepInterval := 100 * time.Millisecond
|
||||||
|
totalSteps := int(duration / stepInterval)
|
||||||
|
|
||||||
|
if totalSteps < 1 {
|
||||||
|
totalSteps = 1
|
||||||
|
stepInterval = duration
|
||||||
|
}
|
||||||
|
|
||||||
|
stepIncrement := gainDiff / float64(totalSteps)
|
||||||
|
|
||||||
|
log.Debugf("Adjusting Headamp %d gain from %.2f dB to %.2f dB over %v...\n",
|
||||||
|
index, currentGain, targetGain, duration)
|
||||||
|
|
||||||
|
for step := 1; step <= totalSteps; step++ {
|
||||||
|
newGain := currentGain + (stepIncrement * float64(step))
|
||||||
|
|
||||||
|
if step == totalSteps {
|
||||||
|
newGain = targetGain
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ctx.Client.HeadAmp.SetGain(index, newGain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if step%10 == 0 || step == totalSteps {
|
||||||
|
log.Debugf(" Step %d/%d: %.2f dB\n", step, totalSteps, newGain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if step < totalSteps {
|
||||||
|
time.Sleep(stepInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeadampPhantomCmd struct {
|
||||||
|
State *string `help:"The phantom power state of the headamp." arg:"" enum:"true,on,false,off" optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *HeadampPhantomCmd) Validate() error {
|
||||||
|
if cmd.State != nil {
|
||||||
|
switch *cmd.State {
|
||||||
|
case "true", "on":
|
||||||
|
*cmd.State = "true"
|
||||||
|
case "false", "off":
|
||||||
|
*cmd.State = "false"
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid phantom power state: %s", *cmd.State)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *HeadampPhantomCmd) Run(ctx *context, headamp *HeadampCmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.HeadAmp.PhantomPower(headamp.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get headamp phantom power state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Headamp %d phantom power: %t\n", headamp.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.HeadAmp.SetPhantomPower(headamp.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set headamp phantom power state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Headamp %d phantom power set to: %s\n", headamp.Index.Index, *cmd.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -74,8 +74,8 @@ func (c *Client) StartListening() {
|
|||||||
log.Debugf("Started listening on %s...", c.engine.conn.LocalAddr().String())
|
log.Debugf("Started listening on %s...", c.engine.conn.LocalAddr().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the client and closes the connection
|
// Close stops the client and closes the connection
|
||||||
func (c *Client) Stop() {
|
func (c *Client) Close() {
|
||||||
close(c.engine.done)
|
close(c.engine.done)
|
||||||
if c.engine.conn != nil {
|
if c.engine.conn != nil {
|
||||||
c.engine.conn.Close()
|
c.engine.conn.Close()
|
||||||
@ -102,10 +102,10 @@ func (c *Client) ReceiveMessage(timeout time.Duration) (*osc.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RequestInfo requests mixer information
|
// RequestInfo requests mixer information
|
||||||
func (c *Client) RequestInfo() (error, InfoResponse) {
|
func (c *Client) RequestInfo() (InfoResponse, error) {
|
||||||
err := c.SendMessage("/xinfo")
|
err := c.SendMessage("/xinfo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, InfoResponse{}
|
return InfoResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
val := <-c.respChan
|
val := <-c.respChan
|
||||||
@ -115,7 +115,7 @@ func (c *Client) RequestInfo() (error, InfoResponse) {
|
|||||||
info.Name = val.Arguments[1].(string)
|
info.Name = val.Arguments[1].(string)
|
||||||
info.Model = val.Arguments[2].(string)
|
info.Model = val.Arguments[2].(string)
|
||||||
}
|
}
|
||||||
return nil, info
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeepAlive sends keep-alive message (required for multi-client usage)
|
// KeepAlive sends keep-alive message (required for multi-client usage)
|
||||||
|
|||||||
@ -189,8 +189,8 @@ func (c *Comp) SetRelease(index int, release float64) error {
|
|||||||
return c.client.SendMessage(address, float32(logSet(4, 4000, release)))
|
return c.client.SendMessage(address, float32(logSet(4, 4000, release)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeUp retrieves the make-up 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 := fmt.Sprintf(c.baseAddress, index) + "/dyn/mgain"
|
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/mgain"
|
||||||
err := c.client.SendMessage(address)
|
err := c.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -200,15 +200,15 @@ func (c *Comp) MakeUp(index int) (float64, error) {
|
|||||||
resp := <-c.client.respChan
|
resp := <-c.client.respChan
|
||||||
val, ok := resp.Arguments[0].(float32)
|
val, ok := resp.Arguments[0].(float32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, fmt.Errorf("unexpected argument type for Compressor make-up gain value")
|
return 0, fmt.Errorf("unexpected argument type for Compressor makeup gain value")
|
||||||
}
|
}
|
||||||
return linGet(0, 24, float64(val)), nil
|
return linGet(0, 24, float64(val)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMakeUp sets the make-up 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 := fmt.Sprintf(c.baseAddress, index) + "/dyn/mgain"
|
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/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).
|
||||||
|
|||||||
@ -49,24 +49,27 @@ func (e *Eq) SetOn(index int, on bool) error {
|
|||||||
return e.client.SendMessage(address, value)
|
return e.client.SendMessage(address, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Eq) Mode(index int) (int, error) {
|
func (e *Eq) Mode(index int) (string, error) {
|
||||||
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
|
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
possibleModes := []string{"peq", "geq", "teq"}
|
||||||
|
|
||||||
resp := <-e.client.respChan
|
resp := <-e.client.respChan
|
||||||
val, ok := resp.Arguments[0].(int32)
|
val, ok := resp.Arguments[0].(int32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, fmt.Errorf("unexpected argument type for EQ mode value")
|
return "", fmt.Errorf("unexpected argument type for EQ mode value")
|
||||||
}
|
}
|
||||||
return int(val), nil
|
return possibleModes[val], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Eq) SetMode(index int, mode int) error {
|
func (e *Eq) SetMode(index int, mode string) error {
|
||||||
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
|
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
|
||||||
return e.client.SendMessage(address, int32(mode))
|
possibleModes := []string{"peq", "geq", "teq"}
|
||||||
|
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).
|
||||||
@ -136,23 +139,26 @@ func (e *Eq) SetQ(index int, band int, q float64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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) (int, error) {
|
func (e *Eq) Type(index int, band int) (string, error) {
|
||||||
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
||||||
err := e.client.SendMessage(address)
|
err := e.client.SendMessage(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
possibleTypes := []string{"lcut", "lshv", "peq", "veq", "hshv", "hcut"}
|
||||||
|
|
||||||
resp := <-e.client.respChan
|
resp := <-e.client.respChan
|
||||||
val, ok := resp.Arguments[0].(int32)
|
val, ok := resp.Arguments[0].(int32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, fmt.Errorf("unexpected argument type for EQ type value")
|
return "", fmt.Errorf("unexpected argument type for EQ type value")
|
||||||
}
|
}
|
||||||
return int(val), nil
|
return possibleTypes[val], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 int) error {
|
func (e *Eq) SetType(index int, band int, eqType string) error {
|
||||||
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
|
||||||
return e.client.SendMessage(address, int32(eqType))
|
possibleTypes := []string{"lcut", "lshv", "peq", "veq", "hshv", "hcut"}
|
||||||
|
return e.client.SendMessage(address, int32(indexOf(possibleTypes, eqType)))
|
||||||
}
|
}
|
||||||
|
|||||||
120
lr.go
Normal file
120
lr.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MainCmdGroup struct {
|
||||||
|
Mute MainMuteCmd `help:"Get or set the mute state of the Main L/R output." cmd:""`
|
||||||
|
|
||||||
|
Fader MainFaderCmd `help:"Get or set the fader level of the Main L/R output." cmd:""`
|
||||||
|
Fadein MainFadeinCmd `help:"Get or set the fade-in time of the Main L/R output." cmd:""`
|
||||||
|
Fadeout MainFadeoutCmd `help:"Get or set the fade-out time of the Main L/R output." cmd:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainMuteCmd struct {
|
||||||
|
Mute *bool `arg:"" help:"The mute state to set. If not provided, the current state will be printed."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *MainMuteCmd) Run(ctx *context) error {
|
||||||
|
if cmd.Mute == nil {
|
||||||
|
resp, err := ctx.Client.Main.Mute()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get Main L/R mute state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R mute state: %t\n", resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Main.SetMute(*cmd.Mute); err != nil {
|
||||||
|
return fmt.Errorf("failed to set Main L/R mute state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R mute state set to: %t\n", *cmd.Mute)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainFaderCmd struct {
|
||||||
|
Level *float64 `arg:"" help:"The fader level to set. If not provided, the current level will be printed."`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *MainFaderCmd) Run(ctx *context) error {
|
||||||
|
if cmd.Level == nil {
|
||||||
|
resp, err := ctx.Client.Main.Fader()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R fader level: %.2f\n", resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Main.SetFader(*cmd.Level); err != nil {
|
||||||
|
return fmt.Errorf("failed to set Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R fader level set to: %.2f\n", *cmd.Level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainFadeinCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-in. (in seconds.)" default:"5s"`
|
||||||
|
Target float64 ` help:"The target level for the fade-in. If not provided, the current target level will be printed." default:"0.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *MainFadeinCmd) Run(ctx *context) error {
|
||||||
|
currentLevel, err := ctx.Client.Main.Fader()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel >= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f) is already at or above the target level (%.2f)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(cmd.Target - currentLevel)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel < cmd.Target {
|
||||||
|
currentLevel++
|
||||||
|
if err := ctx.Client.Main.SetFader(currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R fade-in completed. Final level: %.2f\n", currentLevel)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainFadeoutCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-out. (in seconds.)" default:"5s"`
|
||||||
|
Target float64 ` help:"The target level for the fade-out. If not provided, the current target level will be printed." default:"-90.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *MainFadeoutCmd) Run(ctx *context) error {
|
||||||
|
currentLevel, err := ctx.Client.Main.Fader()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel <= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f) is already at or below the target level (%.2f)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(currentLevel - cmd.Target)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel > cmd.Target {
|
||||||
|
currentLevel--
|
||||||
|
if err := ctx.Client.Main.SetFader(currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set Main L/R fader level: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Main L/R fade-out completed. Final level: %.2f\n", currentLevel)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
110
main.go
110
main.go
@ -1,7 +1,113 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/onyx-and-iris/xair-cli/cmd"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alecthomas/kong"
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
kongcompletion "github.com/jotaen/kong-completion"
|
||||||
|
"github.com/onyx-and-iris/xair-cli/internal/xair"
|
||||||
|
)
|
||||||
|
|
||||||
|
var version string // Version of the CLI, set at build time.
|
||||||
|
|
||||||
|
// VersionFlag is a custom flag type that prints the version and exits.
|
||||||
|
type VersionFlag string
|
||||||
|
|
||||||
|
func (v VersionFlag) Decode(_ *kong.DecodeContext) error { return nil } // nolint: revive
|
||||||
|
func (v VersionFlag) IsBool() bool { return true } // nolint: revive
|
||||||
|
func (v VersionFlag) BeforeApply(app *kong.Kong, vars kong.Vars) error { // nolint: revive, unparam
|
||||||
|
fmt.Printf("xair-cli version: %s\n", vars["version"])
|
||||||
|
app.Exit(0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type context struct {
|
||||||
|
Client *xair.Client
|
||||||
|
Out io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Host string `default:"mixer.local" help:"The host of the X-Air device." env:"XAIR_CLI_HOST"`
|
||||||
|
Port int `default:"10024" help:"The port of the X-Air device." env:"XAIR_CLI_PORT"`
|
||||||
|
Kind string `default:"xr18" help:"The kind of the X-Air device." env:"XAIR_CLI_KIND"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CLI struct {
|
||||||
|
Config `embed:"" prefix:"" help:"The configuration for the CLI."`
|
||||||
|
|
||||||
|
Version VersionFlag `help:"Print gobs-cli version information and quit" name:"version" short:"v"`
|
||||||
|
|
||||||
|
Completion kongcompletion.Completion `help:"Generate shell completion scripts." cmd:"" aliases:"c"`
|
||||||
|
|
||||||
|
Raw RawCmdGroup `help:"Send raw OSC messages to the mixer." cmd:"" group:"Raw"`
|
||||||
|
Main MainCmdGroup `help:"Control the Main L/R output" cmd:"" group:"Main"`
|
||||||
|
Strip StripCmdGroup `help:"Control the strips." cmd:"" group:"Strip"`
|
||||||
|
Bus BusCmdGroup `help:"Control the buses." cmd:"" group:"Bus"`
|
||||||
|
Headamp HeadampCmdGroup `help:"Control input gain and phantom power." cmd:"" group:"Headamp"`
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
var cli CLI
|
||||||
|
kongcompletion.Register(kong.Must(&cli))
|
||||||
|
ctx := kong.Parse(
|
||||||
|
&cli,
|
||||||
|
kong.Name("xair-cli"),
|
||||||
|
kong.Description("A CLI to control Behringer X-Air mixers."),
|
||||||
|
kong.UsageOnError(),
|
||||||
|
kong.ConfigureHelp(kong.HelpOptions{
|
||||||
|
Compact: true,
|
||||||
|
}),
|
||||||
|
kong.Vars{
|
||||||
|
"version": func() string {
|
||||||
|
if version == "" {
|
||||||
|
info, ok := debug.ReadBuildInfo()
|
||||||
|
if !ok {
|
||||||
|
return "(unable to read build info)"
|
||||||
|
}
|
||||||
|
version = strings.Split(info.Main.Version, "-")[0]
|
||||||
|
}
|
||||||
|
return version
|
||||||
|
}(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx.FatalIfErrorf(run(ctx, cli.Config))
|
||||||
|
}
|
||||||
|
|
||||||
|
// run is the main entry point for the CLI.
|
||||||
|
// It connects to the X-Air device, retrieves mixer info, and then runs the command.
|
||||||
|
func run(ctx *kong.Context, config Config) error {
|
||||||
|
client, err := connect(config)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to connect to X-Air device: %w", err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
client.StartListening()
|
||||||
|
resp, err := client.RequestInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Received mixer info: %+v", resp)
|
||||||
|
|
||||||
|
ctx.Bind(&context{
|
||||||
|
Client: client,
|
||||||
|
Out: os.Stdout,
|
||||||
|
})
|
||||||
|
|
||||||
|
return ctx.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect(config Config) (*xair.Client, error) {
|
||||||
|
client, err := xair.NewClient(config.Host, config.Port, xair.WithKind(config.Kind))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|||||||
34
raw.go
Normal file
34
raw.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RawCmdGroup struct {
|
||||||
|
Send RawSendCmd `help:"Send a raw OSC message to the mixer." cmd:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSendCmd struct {
|
||||||
|
Timeout time.Duration `help:"Timeout for the OSC message send operation." default:"200ms" short:"t"`
|
||||||
|
Address string `help:"The OSC address to send the message to." arg:""`
|
||||||
|
Args []string `help:"The arguments to include in the OSC message." arg:"" optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *RawSendCmd) Run(ctx *context) error {
|
||||||
|
params := make([]any, len(cmd.Args))
|
||||||
|
for i, arg := range cmd.Args {
|
||||||
|
params[i] = arg
|
||||||
|
}
|
||||||
|
if err := ctx.Client.SendMessage(cmd.Address, params...); err != nil {
|
||||||
|
return fmt.Errorf("failed to send raw OSC message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := ctx.Client.ReceiveMessage(cmd.Timeout)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to receive response for raw OSC message: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Received response: %s with args: %v\n", msg.Address, msg.Arguments)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
663
strip.go
Normal file
663
strip.go
Normal file
@ -0,0 +1,663 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StripCmdGroup struct {
|
||||||
|
Index struct {
|
||||||
|
Index int `arg:"" help:"The index of the strip. (1-based indexing)"`
|
||||||
|
Mute StripMuteCmd ` help:"Get or set the mute state of the strip." cmd:""`
|
||||||
|
Fader StripFaderCmd ` help:"Get or set the fader level of the strip." cmd:""`
|
||||||
|
Fadein StripFadeinCmd ` help:"Fade in the strip over a specified duration." cmd:""`
|
||||||
|
Fadeout StripFadeoutCmd ` help:"Fade out the strip over a specified duration." cmd:""`
|
||||||
|
Send StripSendCmd ` help:"Get or set the send level for a specific bus." cmd:""`
|
||||||
|
Name StripNameCmd ` help:"Get or set the name of the strip." cmd:""`
|
||||||
|
|
||||||
|
Gate StripGateCmdGroup ` help:"Commands related to the strip gate." cmd:"gate"`
|
||||||
|
Eq StripEqCmdGroup ` help:"Commands related to the strip EQ." cmd:"eq"`
|
||||||
|
Comp StripCompCmdGroup ` help:"Commands related to the strip compressor." cmd:"comp"`
|
||||||
|
} `arg:"" help:"The index of the strip."`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripMuteCmd struct {
|
||||||
|
State *string `arg:"" help:"The mute state to set (true or false). If not provided, the current mute state will be returned." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripMuteCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.State == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Mute(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get mute state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d mute state: %t\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.SetMute(strip.Index.Index, *cmd.State == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set mute state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d mute state set to: %s\n", strip.Index.Index, *cmd.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripFaderCmd struct {
|
||||||
|
Level *float64 `arg:"" help:"The fader level to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripFaderCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Level == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Fader(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get fader level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d fader level: %.2f dB\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.SetFader(strip.Index.Index, *cmd.Level); err != nil {
|
||||||
|
return fmt.Errorf("failed to set fader level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d fader level set to: %.2f dB\n", strip.Index.Index, *cmd.Level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripFadeinCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-in (in seconds)." default:"5s"`
|
||||||
|
Target float64 ` help:"The target fader level (in dB)." default:"0.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripFadeinCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
currentLevel, err := ctx.Client.Strip.Fader(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get current fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel >= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f dB) is already at or above the target level (%.2f dB)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(cmd.Target - currentLevel)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel < cmd.Target {
|
||||||
|
currentLevel++
|
||||||
|
if err := ctx.Client.Strip.SetFader(strip.Index.Index, currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set fader level during fade-in: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d fade-in complete. Final level: %.2f dB\n", strip.Index.Index, cmd.Target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripFadeoutCmd struct {
|
||||||
|
Duration time.Duration `flag:"" help:"The duration of the fade-out (in seconds)." default:"5s"`
|
||||||
|
Target float64 ` help:"The target fader level (in dB)." default:"-90.0" arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripFadeoutCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
{
|
||||||
|
currentLevel, err := ctx.Client.Strip.Fader(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get current fader level: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLevel <= cmd.Target {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"current fader level (%.2f dB) is already at or below the target level (%.2f dB)",
|
||||||
|
currentLevel,
|
||||||
|
cmd.Target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalSteps := float64(currentLevel - cmd.Target)
|
||||||
|
stepDuration := time.Duration(cmd.Duration.Seconds()*1000/totalSteps) * time.Millisecond
|
||||||
|
for currentLevel > cmd.Target {
|
||||||
|
currentLevel--
|
||||||
|
if err := ctx.Client.Strip.SetFader(strip.Index.Index, currentLevel); err != nil {
|
||||||
|
return fmt.Errorf("failed to set fader level during fade-out: %w", err)
|
||||||
|
}
|
||||||
|
time.Sleep(stepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d fade-out complete. Final level: %.2f dB\n", strip.Index.Index, cmd.Target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripSendCmd struct {
|
||||||
|
BusNum int `arg:"" help:"The bus number to get or set the send level for."`
|
||||||
|
Level *string `arg:"" help:"The send level to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripSendCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Level == nil {
|
||||||
|
resp, err := ctx.Client.Strip.SendLevel(strip.Index.Index, cmd.BusNum)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get send level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d send level for bus %d: %.2f dB\n", strip.Index.Index, cmd.BusNum, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
level := mustConvToFloat64(*cmd.Level)
|
||||||
|
if err := ctx.Client.Strip.SetSendLevel(strip.Index.Index, cmd.BusNum, level); err != nil {
|
||||||
|
return fmt.Errorf("failed to set send level: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d send level for bus %d set to: %.2f dB\n", strip.Index.Index, cmd.BusNum, level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripNameCmd struct {
|
||||||
|
Name *string `arg:"" help:"The name to set for the strip." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripNameCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Name == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Name(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get strip name: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d name: %s\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.SetName(strip.Index.Index, *cmd.Name); err != nil {
|
||||||
|
return fmt.Errorf("failed to set strip name: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d name set to: %s\n", strip.Index.Index, *cmd.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateCmdGroup struct {
|
||||||
|
On StripGateOnCmd `help:"Get or set the gate on/off state of the strip." cmd:""`
|
||||||
|
Mode StripGateModeCmd `help:"Get or set the gate mode of the strip." cmd:""`
|
||||||
|
Threshold StripGateThresholdCmd `help:"Get or set the gate threshold of the strip." cmd:""`
|
||||||
|
Range StripGateRangeCmd `help:"Get the gate range of the strip." cmd:""`
|
||||||
|
Attack StripGateAttackCmd `help:"Get or set the gate attack time of the strip." cmd:""`
|
||||||
|
Hold StripGateHoldCmd `help:"Get or set the gate hold time of the strip." cmd:""`
|
||||||
|
Release StripGateReleaseCmd `help:"Get or set the gate release time of the strip." cmd:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateOnCmd struct {
|
||||||
|
Enable *string `arg:"" help:"Whether to enable or disable the gate." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateOnCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Enable == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.On(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate state: %t\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetOn(strip.Index.Index, *cmd.Enable == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate state set to: %s\n", strip.Index.Index, *cmd.Enable)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateModeCmd struct {
|
||||||
|
Mode *string `arg:"" help:"The gate mode to set." optional:"" enum:"exp2,exp3,exp4,gate,duck"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateModeCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Mode == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Mode(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate mode: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate mode: %s\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetMode(strip.Index.Index, *cmd.Mode); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate mode: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate mode set to: %s\n", strip.Index.Index, *cmd.Mode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateThresholdCmd struct {
|
||||||
|
Threshold *float64 `arg:"" help:"The gate threshold to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateThresholdCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Threshold == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Threshold(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate threshold: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate threshold: %.2f\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetThreshold(strip.Index.Index, *cmd.Threshold); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate threshold: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate threshold set to: %.2f\n", strip.Index.Index, *cmd.Threshold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateRangeCmd struct {
|
||||||
|
Range *float64 `arg:"" help:"The gate range to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateRangeCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Range == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Range(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate range: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate range: %.2f\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetRange(strip.Index.Index, *cmd.Range); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate range: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate range set to: %.2f\n", strip.Index.Index, *cmd.Range)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateAttackCmd struct {
|
||||||
|
Attack *float64 `arg:"" help:"The gate attack time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateAttackCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Attack == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Attack(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate attack time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate attack time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetAttack(strip.Index.Index, *cmd.Attack); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate attack time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate attack time set to: %.2f ms\n", strip.Index.Index, *cmd.Attack)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateHoldCmd struct {
|
||||||
|
Hold *float64 `arg:"" help:"The gate hold time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateHoldCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Hold == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Hold(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate hold time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate hold time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetHold(strip.Index.Index, *cmd.Hold); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate hold time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate hold time set to: %.2f ms\n", strip.Index.Index, *cmd.Hold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripGateReleaseCmd struct {
|
||||||
|
Release *float64 `arg:"" help:"The gate release time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripGateReleaseCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Release == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Gate.Release(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get gate release time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate release time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Gate.SetRelease(strip.Index.Index, *cmd.Release); err != nil {
|
||||||
|
return fmt.Errorf("failed to set gate release time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d gate release time set to: %.2f ms\n", strip.Index.Index, *cmd.Release)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqCmdGroup struct {
|
||||||
|
On StripEqOnCmd `help:"Get or set the EQ on/off state of the strip." cmd:""`
|
||||||
|
Band struct {
|
||||||
|
Band int `arg:"" help:"The EQ band number."`
|
||||||
|
Gain StripEqBandGainCmd `help:"Get or set the gain of the EQ band." cmd:""`
|
||||||
|
Freq StripEqBandFreqCmd `help:"Get or set the frequency of the EQ band." cmd:""`
|
||||||
|
Q StripEqBandQCmd `help:"Get or set the Q factor of the EQ band." cmd:""`
|
||||||
|
Type StripEqBandTypeCmd `help:"Get or set the type of the EQ band." cmd:""`
|
||||||
|
} `help:"Commands for controlling a specific EQ band of the strip." arg:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqCmdGroup) Validate() error {
|
||||||
|
if cmd.Band.Band < 1 || cmd.Band.Band > 4 {
|
||||||
|
return fmt.Errorf("EQ band number must be between 1 and 4")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqOnCmd struct {
|
||||||
|
Enable *string `arg:"" help:"Whether to enable or disable the EQ." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqOnCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Enable == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Eq.On(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get EQ state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ state: %t\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Eq.SetOn(strip.Index.Index, *cmd.Enable == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set EQ state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ state set to: %s\n", strip.Index.Index, *cmd.Enable)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqBandGainCmd struct {
|
||||||
|
Gain *float64 `arg:"" help:"The gain to set for the EQ band (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqBandGainCmd) Run(ctx *context, strip *StripCmdGroup, stripEq *StripEqCmdGroup) error {
|
||||||
|
if cmd.Gain == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Eq.Gain(strip.Index.Index, stripEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get EQ band gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d gain: %.2f\n", strip.Index.Index, stripEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Eq.SetGain(strip.Index.Index, stripEq.Band.Band, *cmd.Gain); err != nil {
|
||||||
|
return fmt.Errorf("failed to set EQ band gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d gain set to: %.2f\n", strip.Index.Index, stripEq.Band.Band, *cmd.Gain)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqBandFreqCmd struct {
|
||||||
|
Freq *float64 `arg:"" help:"The frequency to set for the EQ band (in Hz)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqBandFreqCmd) Run(ctx *context, strip *StripCmdGroup, stripEq *StripEqCmdGroup) error {
|
||||||
|
if cmd.Freq == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Eq.Frequency(strip.Index.Index, stripEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get EQ band frequency: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d frequency: %.2f Hz\n", strip.Index.Index, stripEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Eq.SetFrequency(strip.Index.Index, stripEq.Band.Band, *cmd.Freq); err != nil {
|
||||||
|
return fmt.Errorf("failed to set EQ band frequency: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(
|
||||||
|
ctx.Out,
|
||||||
|
"Strip %d EQ band %d frequency set to: %.2f Hz\n",
|
||||||
|
strip.Index.Index,
|
||||||
|
stripEq.Band.Band,
|
||||||
|
*cmd.Freq,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqBandQCmd struct {
|
||||||
|
Q *float64 `arg:"" help:"The Q factor to set for the EQ band." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqBandQCmd) Run(ctx *context, strip *StripCmdGroup, stripEq *StripEqCmdGroup) error {
|
||||||
|
if cmd.Q == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Eq.Q(strip.Index.Index, stripEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get EQ band Q factor: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d Q factor: %.2f\n", strip.Index.Index, stripEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Eq.SetQ(strip.Index.Index, stripEq.Band.Band, *cmd.Q); err != nil {
|
||||||
|
return fmt.Errorf("failed to set EQ band Q factor: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d Q factor set to: %.2f\n", strip.Index.Index, stripEq.Band.Band, *cmd.Q)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripEqBandTypeCmd struct {
|
||||||
|
Type *string `arg:"" help:"The type to set for the EQ band." optional:"" enum:"lcut,lshv,peq,veq,hshv,hcut"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripEqBandTypeCmd) Run(ctx *context, strip *StripCmdGroup, stripEq *StripEqCmdGroup) error {
|
||||||
|
if cmd.Type == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Eq.Type(strip.Index.Index, stripEq.Band.Band)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get EQ band type: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d type: %s\n", strip.Index.Index, stripEq.Band.Band, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Eq.SetType(strip.Index.Index, stripEq.Band.Band, *cmd.Type); err != nil {
|
||||||
|
return fmt.Errorf("failed to set EQ band type: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d EQ band %d type set to: %s\n", strip.Index.Index, stripEq.Band.Band, *cmd.Type)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompCmdGroup struct {
|
||||||
|
On StripCompOnCmd `help:"Get or set the compressor on/off state of the strip." cmd:""`
|
||||||
|
Mode StripCompModeCmd `help:"Get or set the compressor mode of the strip." cmd:""`
|
||||||
|
Threshold StripCompThresholdCmd `help:"Get or set the compressor threshold of the strip." cmd:""`
|
||||||
|
Ratio StripCompRatioCmd `help:"Get or set the compressor ratio of the strip." cmd:""`
|
||||||
|
Mix StripCompMixCmd `help:"Get or set the compressor mix of the strip." cmd:""`
|
||||||
|
Makeup StripCompMakeupCmd `help:"Get or set the compressor makeup gain of the strip." cmd:""`
|
||||||
|
Attack StripCompAttackCmd `help:"Get or set the compressor attack time of the strip." cmd:""`
|
||||||
|
Hold StripCompHoldCmd `help:"Get or set the compressor hold time of the strip." cmd:""`
|
||||||
|
Release StripCompReleaseCmd `help:"Get or set the compressor release time of the strip." cmd:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompOnCmd struct {
|
||||||
|
Enable *string `arg:"" help:"Whether to enable or disable the compressor." optional:"" enum:"true,false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompOnCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Enable == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.On(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor state: %t\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetOn(strip.Index.Index, *cmd.Enable == "true"); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor state: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor state set to: %s\n", strip.Index.Index, *cmd.Enable)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompModeCmd struct {
|
||||||
|
Mode *string `arg:"" help:"The compressor mode to set." optional:"" enum:"comp,exp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompModeCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Mode == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Mode(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor mode: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor mode: %s\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetMode(strip.Index.Index, *cmd.Mode); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor mode: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor mode set to: %s\n", strip.Index.Index, *cmd.Mode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompThresholdCmd struct {
|
||||||
|
Threshold *float64 `arg:"" help:"The compressor threshold to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompThresholdCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Threshold == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Threshold(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor threshold: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor threshold: %.2f\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetThreshold(strip.Index.Index, *cmd.Threshold); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor threshold: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor threshold set to: %.2f\n", strip.Index.Index, *cmd.Threshold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompRatioCmd struct {
|
||||||
|
Ratio *float64 `arg:"" help:"The compressor ratio to set." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompRatioCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Ratio == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Ratio(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor ratio: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor ratio: %.2f\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetRatio(strip.Index.Index, *cmd.Ratio); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor ratio: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor ratio set to: %.2f\n", strip.Index.Index, *cmd.Ratio)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompMixCmd struct {
|
||||||
|
Mix *float64 `arg:"" help:"The compressor mix to set (0-100%)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompMixCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Mix == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Mix(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor mix: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor mix: %.2f%%\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetMix(strip.Index.Index, *cmd.Mix); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor mix: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor mix set to: %.2f%%\n", strip.Index.Index, *cmd.Mix)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompMakeupCmd struct {
|
||||||
|
Makeup *float64 `arg:"" help:"The compressor makeup gain to set (in dB)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompMakeupCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Makeup == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Makeup(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor makeup gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor makeup gain: %.2f\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetMakeup(strip.Index.Index, *cmd.Makeup); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor makeup gain: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor makeup gain set to: %.2f\n", strip.Index.Index, *cmd.Makeup)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompAttackCmd struct {
|
||||||
|
Attack *float64 `arg:"" help:"The compressor attack time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompAttackCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Attack == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Attack(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor attack time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor attack time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetAttack(strip.Index.Index, *cmd.Attack); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor attack time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor attack time set to: %.2f ms\n", strip.Index.Index, *cmd.Attack)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompHoldCmd struct {
|
||||||
|
Hold *float64 `arg:"" help:"The compressor hold time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompHoldCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Hold == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Hold(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor hold time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor hold time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetHold(strip.Index.Index, *cmd.Hold); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor hold time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor hold time set to: %.2f ms\n", strip.Index.Index, *cmd.Hold)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type StripCompReleaseCmd struct {
|
||||||
|
Release *float64 `arg:"" help:"The compressor release time to set (in ms)." optional:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *StripCompReleaseCmd) Run(ctx *context, strip *StripCmdGroup) error {
|
||||||
|
if cmd.Release == nil {
|
||||||
|
resp, err := ctx.Client.Strip.Comp.Release(strip.Index.Index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get compressor release time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor release time: %.2f ms\n", strip.Index.Index, resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Client.Strip.Comp.SetRelease(strip.Index.Index, *cmd.Release); err != nil {
|
||||||
|
return fmt.Errorf("failed to set compressor release time: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctx.Out, "Strip %d compressor release time set to: %.2f ms\n", strip.Index.Index, *cmd.Release)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user