mirror of
https://github.com/onyx-and-iris/xair-cli.git
synced 2026-04-08 18:03:37 +00:00
migrate CLI component to Kong
This commit is contained in:
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
|
||||
}
|
||||
Reference in New Issue
Block a user