Compare commits

..

No commits in common. "main" and "v0.3.2" have entirely different histories.
main ... v0.3.2

15 changed files with 63 additions and 1849 deletions

View File

@ -38,7 +38,7 @@ Use "xair-cli [command] --help" for more information about a command.
### Examples
*Fade out main LR all the way to -∞ over a 5s duration*
*Fade out main LR all the way to -∞*
```console
xair-cli main fadeout
@ -46,9 +46,9 @@ xair-cli main fadeout
*enable phantom power and set the gain to 28.0dB over a 10s duration for strip 09*
```console
xair-cli headamp phantom 9 on
xair-cli headamp 9 phantom on
xair-cli headamp gain 9 28.0 --duration 10s
xair-cli headamp 9 gain 28.0 --duration 10s
```
*set strip 09 send level for bus 5 to -18.0dB*
@ -56,22 +56,15 @@ xair-cli headamp gain 9 28.0 --duration 10s
xair-cli strip send 9 5 -- -18.0
```
*enable eq for strip 01*
```console
xair-cli strip eq on 1 true
```
*rename bus 01 to 'vocal mix'*
```console
xair-cli bus name 1 'vocal mix'
xair-cli bus 1 name 'vocal mix'
```
For every command/subcommand there exists a `--help` flag which you can use to get usage information.
### Notes
This CLI is useful if just want to run some commands on the terminal using a single binary, no further downloads. However, there exists an alternative you should check out that has wider support of the XAir OSC protocol including support for operations like batch commands and network discovery (which I have no plans to implement on this CLI). Check out [dc-xair-cli](https://pypi.org/project/dc-xair-cli/) on pypi.
I've only implemented the parts I personally need, I don't know how much more I intend to add.
### License

View File

@ -254,640 +254,16 @@ var busNameCmd = &cobra.Command{
},
}
// 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
},
}
// 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(busCompThresholdCmd)
busCompCmd.AddCommand(busCompRatioCmd)
busCompCmd.AddCommand(busCompMixCmd)
busCompCmd.AddCommand(busCompMakeUpCmd)
busCompCmd.AddCommand(busCompAttackCmd)
busCompCmd.AddCommand(busCompHoldCmd)
busCompCmd.AddCommand(busCompReleaseCmd)
}

View File

@ -203,7 +203,7 @@ var stripFadeInCmd = &cobra.Command{
stripIndex := mustConvToInt(args[0])
duration, err := cmd.Flags().GetDuration("duration")
duration, err := cmd.Flags().GetFloat64("duration")
if err != nil {
return fmt.Errorf("Error getting duration flag: %w", err)
}
@ -224,7 +224,7 @@ var stripFadeInCmd = &cobra.Command{
return nil
}
stepDelay := time.Duration(duration.Seconds()*1000/totalSteps) * time.Millisecond
stepDelay := time.Duration(duration*1000/totalSteps) * time.Millisecond
for currentFader < target {
currentFader += 1.0
@ -235,7 +235,7 @@ var stripFadeInCmd = &cobra.Command{
time.Sleep(stepDelay)
}
cmd.Printf("Strip %d faded in to %.2f dB over %.2f seconds\n", stripIndex, target, duration.Seconds())
cmd.Printf("Strip %d faded in to %.2f dB over %.2f seconds\n", stripIndex, target, duration)
return nil
},
}
@ -333,727 +333,18 @@ If a name argument is provided, the strip name is set to that value.`,
},
}
// stripGateCmd represents the strip Gate command.
var stripGateCmd = &cobra.Command{
Short: "Commands to control the Gate of individual strips.",
Long: `Commands to control the Gate of individual strips, including turning the Gate on or off.`,
Use: "gate",
Run: func(cmd *cobra.Command, _ []string) {
cmd.Help()
},
}
// stripGateOnCmd represents the strip Gate on command.
var stripGateOnCmd = &cobra.Command{
Short: "Get or set the Gate on/off status of a strip",
Long: `Get or set the Gate on/off status of a specific strip.
If no status argument is provided, the current Gate status is retrieved.
If "true" or "1" is provided as an argument, the Gate is turned on.
If "false" or "0" is provided, the Gate is turned off.`,
Use: "on [strip number] [true|false]",
Example: ` # Get the current Gate status of strip 1
xair-cli strip gate on 1
# Turn on Gate for strip 1
xair-cli strip gate on 1 true
# Turn off Gate for strip 1
xair-cli strip gate on 1 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) < 1 {
return fmt.Errorf("Please provide a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
on, err := client.Strip.Gate.On(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Gate on status: %w", err)
}
cmd.Printf("Strip %d Gate on: %v\n", stripIndex, on)
return nil
}
var on bool
switch args[1] {
case "true", "1":
on = true
case "false", "0":
on = false
default:
return fmt.Errorf("Invalid Gate status. Use true/false or 1/0")
}
err := client.Strip.Gate.SetOn(stripIndex, on)
if err != nil {
return fmt.Errorf("Error setting strip Gate on status: %w", err)
}
if on {
cmd.Printf("Strip %d Gate turned on successfully\n", stripIndex)
} else {
cmd.Printf("Strip %d Gate turned off successfully\n", stripIndex)
}
return nil
},
}
// stripEqCmd represents the strip EQ command.
var stripEqCmd = &cobra.Command{
Short: "Commands to control the EQ of individual strips.",
Long: `Commands to control the EQ of individual strips, including turning the EQ on or off.`,
Use: "eq",
Run: func(cmd *cobra.Command, _ []string) {
cmd.Help()
},
}
// stripEqOnCmd represents the strip EQ on command.
var stripEqOnCmd = &cobra.Command{
Short: "Get or set the EQ on/off status of a strip",
Long: `Get or set the EQ on/off status of a specific strip.
If no status argument is provided, the current EQ status is retrieved.
If "true" or "1" is provided as an argument, the EQ is turned on.
If "false" or "0" is provided, the EQ is turned off.`,
Use: "on [strip number] [true|false]",
Example: ` # Get the current EQ status of strip 1
xair-cli strip eq on 1
# Turn on EQ for strip 1
xair-cli strip eq on 1 true
# Turn off EQ for strip 1
xair-cli strip eq on 1 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) < 1 {
return fmt.Errorf("Please provide a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
on, err := client.Strip.Eq.On(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip EQ on status: %w", err)
}
cmd.Printf("Strip %d EQ on: %v\n", stripIndex, on)
return nil
}
var on bool
switch args[1] {
case "true", "1":
on = true
case "false", "0":
on = false
default:
return fmt.Errorf("Invalid EQ status. Use true/false or 1/0")
}
err := client.Strip.Eq.SetOn(stripIndex, on)
if err != nil {
return fmt.Errorf("Error setting strip EQ on status: %w", err)
}
if on {
cmd.Printf("Strip %d EQ turned on successfully\n", stripIndex)
} else {
cmd.Printf("Strip %d EQ turned off successfully\n", stripIndex)
}
return nil
},
}
// stripEqGainCmd represents the strip EQ Gain command.
var stripEqGainCmd = &cobra.Command{
Short: "Get or set the EQ band gain for a strip",
Long: "Get or set the EQ band gain for a specific strip and band.",
Use: "gain [strip 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 strip number and band number")
}
stripIndex, bandIndex := func() (int, int) {
return mustConvToInt(args[0]), mustConvToInt(args[1])
}()
if len(args) == 2 {
currentGain, err := client.Strip.Eq.Gain(stripIndex, bandIndex)
if err != nil {
return fmt.Errorf("Error getting strip EQ band gain: %w", err)
}
cmd.Printf("Strip %d EQ band %d gain: %.2f dB\n", stripIndex, bandIndex, currentGain)
return nil
}
if len(args) < 3 {
return fmt.Errorf("Please provide a gain in dB")
}
gain := mustConvToFloat64(args[2])
err := client.Strip.Eq.SetGain(stripIndex, bandIndex, gain)
if err != nil {
return fmt.Errorf("Error setting strip EQ band gain: %w", err)
}
cmd.Printf("Strip %d EQ band %d gain set to %.2f dB\n", stripIndex, bandIndex, gain)
return nil
},
}
// stripEqFreqCmd represents the strip EQ Frequency command.
var stripEqFreqCmd = &cobra.Command{
Short: "Get or set the EQ band frequency for a strip",
Long: "Get or set the EQ band frequency for a specific strip and band.",
Use: "freq [strip 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 strip number and band number")
}
stripIndex, bandIndex := func() (int, int) {
return mustConvToInt(args[0]), mustConvToInt(args[1])
}()
if len(args) == 2 {
currentFreq, err := client.Strip.Eq.Frequency(stripIndex, bandIndex)
if err != nil {
return fmt.Errorf("Error getting strip EQ band frequency: %w", err)
}
cmd.Printf("Strip %d EQ band %d frequency: %.2f Hz\n", stripIndex, bandIndex, currentFreq)
return nil
}
if len(args) < 3 {
return fmt.Errorf("Please provide a frequency in Hz")
}
freq := mustConvToFloat64(args[2])
err := client.Strip.Eq.SetFrequency(stripIndex, bandIndex, freq)
if err != nil {
return fmt.Errorf("Error setting strip EQ band frequency: %w", err)
}
cmd.Printf("Strip %d EQ band %d frequency set to %.2f Hz\n", stripIndex, bandIndex, freq)
return nil
},
}
// stripEqQCmd represents the strip EQ Q command.
var stripEqQCmd = &cobra.Command{
Short: "Get or set the EQ band Q factor for a strip",
Long: "Get or set the EQ band Q factor for a specific strip and band.",
Use: "q [strip 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 strip number and band number")
}
stripIndex, bandIndex := func() (int, int) {
return mustConvToInt(args[0]), mustConvToInt(args[1])
}()
if len(args) == 2 {
currentQ, err := client.Strip.Eq.Q(stripIndex, bandIndex)
if err != nil {
return fmt.Errorf("Error getting strip EQ band Q factor: %w", err)
}
cmd.Printf("Strip %d EQ band %d Q factor: %.2f\n", stripIndex, bandIndex, currentQ)
return nil
}
if len(args) < 3 {
return fmt.Errorf("Please provide a Q factor")
}
q := mustConvToFloat64(args[2])
err := client.Strip.Eq.SetQ(stripIndex, bandIndex, q)
if err != nil {
return fmt.Errorf("Error setting strip EQ band Q factor: %w", err)
}
cmd.Printf("Strip %d EQ band %d Q factor set to %.2f\n", stripIndex, bandIndex, q)
return nil
},
}
// stripEqTypeCmd represents the strip EQ Type command.
var stripEqTypeCmd = &cobra.Command{
Short: "Get or set the EQ band type for a strip",
Long: "Get or set the EQ band type for a specific strip and band.",
Use: "type [strip 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 strip number and band number")
}
stripIndex, 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.Strip.Eq.Type(stripIndex, bandIndex)
if err != nil {
return fmt.Errorf("Error getting strip EQ band type: %w", err)
}
cmd.Printf("Strip %d EQ band %d type: %s\n", stripIndex, bandIndex, eqTypeNames[currentType])
return nil
}
if len(args) < 3 {
return fmt.Errorf("Please provide a type")
}
eqType := indexOf(eqTypeNames, args[2])
if eqType == -1 {
return fmt.Errorf("Invalid EQ band type. Valid types are: %v", eqTypeNames)
}
err := client.Strip.Eq.SetType(stripIndex, bandIndex, eqType)
if err != nil {
return fmt.Errorf("Error setting strip EQ band type: %w", err)
}
cmd.Printf("Strip %d EQ band %d type set to %s\n", stripIndex, bandIndex, eqTypeNames[eqType])
return nil
},
}
// stripCompCmd represents the strip Compressor command.
var stripCompCmd = &cobra.Command{
Short: "Commands to control the Compressor of individual strips.",
Long: `Commands to control the Compressor of individual strips, including turning the Compressor on or off.`,
Use: "comp",
Run: func(cmd *cobra.Command, _ []string) {
cmd.Help()
},
}
// stripCompOnCmd represents the strip Compressor on command.
var stripCompOnCmd = &cobra.Command{
Short: "Get or set the Compressor on/off status of a strip",
Long: `Get or set the Compressor on/off status of a specific strip.
If no status argument is provided, the current Compressor status is retrieved.
If "true" or "1" is provided as an argument, the Compressor is turned on.
If "false" or "0" is provided, the Compressor is turned off.`,
Use: "on [strip number] [true|false]",
Example: ` # Get the current Compressor status of strip 1
xair-cli strip comp on 1
# Turn on Compressor for strip 1
xair-cli strip comp on 1 true
# Turn off Compressor for strip 1
xair-cli strip comp on 1 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) < 1 {
return fmt.Errorf("Please provide a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
on, err := client.Strip.Comp.On(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor on status: %w", err)
}
cmd.Printf("Strip %d Compressor on: %v\n", stripIndex, on)
return nil
}
var on bool
switch args[1] {
case "true", "1":
on = true
case "false", "0":
on = false
default:
return fmt.Errorf("Invalid Compressor status. Use true/false or 1/0")
}
err := client.Strip.Comp.SetOn(stripIndex, on)
if err != nil {
return fmt.Errorf("Error setting strip Compressor on status: %w", err)
}
if on {
cmd.Printf("Strip %d Compressor turned on successfully\n", stripIndex)
} else {
cmd.Printf("Strip %d Compressor turned off successfully\n", stripIndex)
}
return nil
},
}
// stripCompThresholdCmd represents the strip Compressor Threshold command.
var stripCompThresholdCmd = &cobra.Command{
Short: "Get or set the Compressor threshold for a strip",
Long: "Get or set the Compressor threshold for a specific strip.",
Use: "threshold [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentThreshold, err := client.Strip.Comp.Threshold(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor threshold: %w", err)
}
cmd.Printf("Strip %d Compressor threshold: %.2f dB\n", stripIndex, currentThreshold)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a threshold in dB")
}
threshold := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetThreshold(stripIndex, threshold)
if err != nil {
return fmt.Errorf("Error setting strip Compressor threshold: %w", err)
}
cmd.Printf("Strip %d Compressor threshold set to %.2f dB\n", stripIndex, threshold)
return nil
},
}
// stripCompRatioCmd represents the strip Compressor Ratio command.
var stripCompRatioCmd = &cobra.Command{
Short: "Get or set the Compressor ratio for a strip",
Long: "Get or set the Compressor ratio for a specific strip.",
Use: "ratio [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentRatio, err := client.Strip.Comp.Ratio(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor ratio: %w", err)
}
cmd.Printf("Strip %d Compressor ratio: %.2f\n", stripIndex, currentRatio)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a ratio")
}
ratio := mustConvToFloat64(args[1])
possibleValues := []float64{1.1, 1.3, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 7.0, 10, 20, 100}
if !contains(possibleValues, ratio) {
return fmt.Errorf("Invalid ratio value. Valid values are: %v", possibleValues)
}
err := client.Strip.Comp.SetRatio(stripIndex, ratio)
if err != nil {
return fmt.Errorf("Error setting strip Compressor ratio: %w", err)
}
cmd.Printf("Strip %d Compressor ratio set to %.2f\n", stripIndex, ratio)
return nil
},
}
// stripCompMixCmd represents the strip Compressor Mix command.
var stripCompMixCmd = &cobra.Command{
Short: "Get or set the Compressor mix for a strip",
Long: "Get or set the Compressor mix for a specific strip.",
Use: "mix [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentMix, err := client.Strip.Comp.Mix(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor mix: %w", err)
}
cmd.Printf("Strip %d Compressor mix: %.2f%%\n", stripIndex, currentMix)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a mix percentage")
}
mix := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetMix(stripIndex, mix)
if err != nil {
return fmt.Errorf("Error setting strip Compressor mix: %w", err)
}
cmd.Printf("Strip %d Compressor mix set to %.2f%%\n", stripIndex, mix)
return nil
},
}
// stripCompMakeUpCmd represents the strip Compressor Make-Up Gain command.
var stripCompMakeUpCmd = &cobra.Command{
Short: "Get or set the Compressor make-up gain for a strip",
Long: "Get or set the Compressor make-up gain for a specific strip.",
Use: "makeup [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentMakeUp, err := client.Strip.Comp.MakeUp(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor make-up gain: %w", err)
}
cmd.Printf("Strip %d Compressor make-up gain: %.2f dB\n", stripIndex, currentMakeUp)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a make-up gain in dB")
}
makeUp := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetMakeUp(stripIndex, makeUp)
if err != nil {
return fmt.Errorf("Error setting strip Compressor make-up gain: %w", err)
}
cmd.Printf("Strip %d Compressor make-up gain set to %.2f dB\n", stripIndex, makeUp)
return nil
},
}
// stripCompAttackCmd represents the strip Compressor Attack command.
var stripCompAttackCmd = &cobra.Command{
Short: "Get or set the Compressor attack time for a strip",
Long: "Get or set the Compressor attack time for a specific strip.",
Use: "attack [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentAttack, err := client.Strip.Comp.Attack(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor attack time: %w", err)
}
cmd.Printf("Strip %d Compressor attack time: %.2f ms\n", stripIndex, currentAttack)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide an attack time in ms")
}
attack := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetAttack(stripIndex, attack)
if err != nil {
return fmt.Errorf("Error setting strip Compressor attack time: %w", err)
}
cmd.Printf("Strip %d Compressor attack time set to %.2f ms\n", stripIndex, attack)
return nil
},
}
// stripCompHoldCmd represents the strip Compressor Hold command.
var stripCompHoldCmd = &cobra.Command{
Short: "Get or set the Compressor hold time for a strip",
Long: "Get or set the Compressor hold time for a specific strip.",
Use: "hold [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentHold, err := client.Strip.Comp.Hold(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor hold time: %w", err)
}
cmd.Printf("Strip %d Compressor hold time: %.2f ms\n", stripIndex, currentHold)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a hold time in ms")
}
hold := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetHold(stripIndex, hold)
if err != nil {
return fmt.Errorf("Error setting strip Compressor hold time: %w", err)
}
cmd.Printf("Strip %d Compressor hold time set to %.2f ms\n", stripIndex, hold)
return nil
},
}
// stripCompReleaseCmd represents the strip Compressor Release command.
var stripCompReleaseCmd = &cobra.Command{
Short: "Get or set the Compressor release time for a strip",
Long: "Get or set the Compressor release time for a specific strip.",
Use: "release [strip 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 a strip number")
}
stripIndex := mustConvToInt(args[0])
if len(args) == 1 {
currentRelease, err := client.Strip.Comp.Release(stripIndex)
if err != nil {
return fmt.Errorf("Error getting strip Compressor release time: %w", err)
}
cmd.Printf("Strip %d Compressor release time: %.2f ms\n", stripIndex, currentRelease)
return nil
}
if len(args) < 2 {
return fmt.Errorf("Please provide a release time in ms")
}
release := mustConvToFloat64(args[1])
err := client.Strip.Comp.SetRelease(stripIndex, release)
if err != nil {
return fmt.Errorf("Error setting strip Compressor release time: %w", err)
}
cmd.Printf("Strip %d Compressor release time set to %.2f ms\n", stripIndex, release)
return nil
},
}
func init() {
rootCmd.AddCommand(stripCmd)
stripCmd.AddCommand(stripMuteCmd)
stripCmd.AddCommand(stripFaderCmd)
stripCmd.AddCommand(stripFadeOutCmd)
stripFadeOutCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration of the fade out in seconds")
stripCmd.AddCommand(stripFadeInCmd)
stripFadeInCmd.Flags().DurationP("duration", "d", 5*time.Second, "Duration of the fade in in seconds")
stripCmd.AddCommand(stripSendCmd)
stripCmd.AddCommand(stripNameCmd)
stripCmd.AddCommand(stripGateCmd)
stripGateCmd.AddCommand(stripGateOnCmd)
stripCmd.AddCommand(stripEqCmd)
stripEqCmd.AddCommand(stripEqOnCmd)
stripEqCmd.AddCommand(stripEqGainCmd)
stripEqCmd.AddCommand(stripEqFreqCmd)
stripEqCmd.AddCommand(stripEqQCmd)
stripEqCmd.AddCommand(stripEqTypeCmd)
stripCmd.AddCommand(stripCompCmd)
stripCompCmd.AddCommand(stripCompOnCmd)
stripCompCmd.AddCommand(stripCompThresholdCmd)
stripCompCmd.AddCommand(stripCompRatioCmd)
stripCompCmd.AddCommand(stripCompMixCmd)
stripCompCmd.AddCommand(stripCompMakeUpCmd)
stripCompCmd.AddCommand(stripCompAttackCmd)
stripCompCmd.AddCommand(stripCompHoldCmd)
stripCompCmd.AddCommand(stripCompReleaseCmd)
}

View File

@ -21,18 +21,3 @@ func mustConvToInt(intStr string) int {
}
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
}

24
go.mod
View File

@ -11,17 +11,17 @@ require (
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.4.1 // indirect
github.com/charmbracelet/colorprofile v0.3.3 // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.11.4 // indirect
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
github.com/charmbracelet/x/ansi v0.10.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.9.0 // indirect
github.com/clipperhouse/displaywidth v0.4.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.3.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logfmt/logfmt v0.6.1 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@ -29,15 +29,15 @@ require (
github.com/muesli/termenv v0.16.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // 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
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // 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
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.28.0 // indirect
)

50
go.sum
View File

@ -1,23 +1,23 @@
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/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/colorprofile v0.3.3 h1:DjJzJtLP6/NZ8p7Cgjno0CKGr7wwRJGxWUwh2IyhfAI=
github.com/charmbracelet/colorprofile v0.3.3/go.mod h1:nB1FugsAbzq284eJcjfah2nhdSLppN2NqvfotkfRYP4=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
github.com/charmbracelet/x/ansi v0.11.4 h1:6G65PLu6HjmE858CnTUQY1LXT3ZUWwfvqEROLF8vqHI=
github.com/charmbracelet/x/ansi v0.11.4/go.mod h1:/5AZ+UfWExW3int5H5ugnsG/PWjNcSQcwYsHBlPFQN4=
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
github.com/charmbracelet/x/ansi v0.10.3 h1:3WoV9XN8uMEnFRZZ+vBPRy59TaIWa+gJodS4Vg5Fut0=
github.com/charmbracelet/x/ansi v0.10.3/go.mod h1:uQt8bOrq/xgXjlGcFMc8U2WYbnxyjrKhnvTQluvfCaE=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/displaywidth v0.4.1 h1:uVw9V8UDfnggg3K2U84VWY1YLQ/x2aKSCtkRyYozfoU=
github.com/clipperhouse/displaywidth v0.4.1/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/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.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -25,12 +25,12 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
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/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/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@ -56,8 +56,10 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
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=
@ -77,13 +79,13 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
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/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
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/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=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
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/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -4,17 +4,13 @@ import "fmt"
type Bus struct {
baseAddress string
client *Client
Eq *Eq
Comp *Comp
client Client
}
func NewBus(c *Client) *Bus {
func NewBus(c Client) *Bus {
return &Bus{
baseAddress: c.addressMap["bus"],
client: c,
Eq: newEqForBus(c),
Comp: newCompForBus(c),
}
}

View File

@ -58,10 +58,10 @@ func NewClient(mixerIP string, mixerPort int, opts ...Option) (*Client, error) {
c := &Client{
engine: *e,
}
c.Main = newMain(c)
c.Strip = NewStrip(c)
c.Bus = NewBus(c)
c.HeadAmp = NewHeadAmp(c)
c.Main = newMain(*c)
c.Strip = NewStrip(*c)
c.Bus = NewBus(*c)
c.HeadAmp = NewHeadAmp(*c)
return c, nil
}

View File

@ -1,209 +0,0 @@
package xair
import "fmt"
type Comp struct {
client *Client
baseAddress string
}
// Factory function to create Comp instance for Strip
func newCompForStrip(c *Client) *Comp {
return &Comp{
client: c,
baseAddress: c.addressMap["strip"],
}
}
// Factory function to create Comp instance for Bus
func newCompForBus(c *Client) *Comp {
return &Comp{
client: c,
baseAddress: c.addressMap["bus"],
}
}
// On retrieves the on/off status of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) On(index int) (bool, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/on"
err := c.client.SendMessage(address)
if err != nil {
return false, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return false, fmt.Errorf("unexpected argument type for Compressor on value")
}
return val != 0, nil
}
// SetOn sets the on/off status of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetOn(index int, on bool) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/on"
var value int32
if on {
value = 1
}
return c.client.SendMessage(address, value)
}
// Threshold retrieves the threshold value of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) Threshold(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/thr"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor threshold value")
}
return linGet(-60, 0, float64(val)), nil
}
// SetThreshold sets the threshold value of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetThreshold(index int, threshold float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/thr"
return c.client.SendMessage(address, float32(linSet(-60, 0, threshold)))
}
// Ratio retrieves the ratio value of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) Ratio(index int) (float32, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/ratio"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
possibleValues := []float32{1.1, 1.3, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 7.0, 10, 20, 100}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor ratio value")
}
return possibleValues[val], nil
}
// SetRatio sets the ratio value of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetRatio(index int, ratio float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/ratio"
possibleValues := []float32{1.1, 1.3, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 7.0, 10, 20, 100}
return c.client.SendMessage(address, int32(indexOf(possibleValues, float32(ratio))))
}
// Attack retrieves the attack time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) Attack(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/attack"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor attack value")
}
return linGet(0, 120, float64(val)), nil
}
// SetAttack sets the attack time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetAttack(index int, attack float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/attack"
return c.client.SendMessage(address, float32(linSet(0, 120, attack)))
}
// Hold retrieves the hold time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) Hold(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/hold"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor hold value")
}
return logGet(0.02, 2000, float64(val)), nil
}
// SetHold sets the hold time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetHold(index int, hold float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/hold"
return c.client.SendMessage(address, float32(logSet(0.02, 2000, hold)))
}
// Release retrieves the release time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) Release(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/release"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor release value")
}
return logGet(4, 4000, float64(val)), nil
}
// SetRelease sets the release time of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetRelease(index int, release float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/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).
func (c *Comp) MakeUp(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/mgain"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor make-up gain value")
}
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).
func (c *Comp) SetMakeUp(index int, makeUp float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/mgain"
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).
func (c *Comp) Mix(index int) (float64, error) {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/mix"
err := c.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-c.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for Compressor mix value")
}
return linGet(0, 100, float64(val)), nil
}
// SetMix sets the mix value of the Compressor for a specific strip or bus (1-based indexing).
func (c *Comp) SetMix(index int, mix float64) error {
address := fmt.Sprintf(c.baseAddress, index) + "/dyn/mix"
return c.client.SendMessage(address, float32(linSet(0, 100, mix)))
}

View File

@ -1,158 +0,0 @@
package xair
import "fmt"
type Eq struct {
client *Client
baseAddress string
}
// Factory function to create Eq instance for Strip
func newEqForStrip(c *Client) *Eq {
return &Eq{
client: c,
baseAddress: c.addressMap["strip"],
}
}
// Factory function to create Eq instance for Bus
func newEqForBus(c *Client) *Eq {
return &Eq{
client: c,
baseAddress: c.addressMap["bus"],
}
}
// On retrieves the on/off status of the EQ for a specific strip or bus (1-based indexing).
func (e *Eq) On(index int) (bool, error) {
address := fmt.Sprintf(e.baseAddress, index) + "/eq/on"
err := e.client.SendMessage(address)
if err != nil {
return false, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return false, fmt.Errorf("unexpected argument type for EQ on value")
}
return val != 0, nil
}
// SetOn sets the on/off status of the EQ for a specific strip or bus (1-based indexing).
func (e *Eq) SetOn(index int, on bool) error {
address := fmt.Sprintf(e.baseAddress, index) + "/eq/on"
var value int32
if on {
value = 1
}
return e.client.SendMessage(address, value)
}
func (e *Eq) Mode(index int) (int, error) {
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
err := e.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for EQ mode value")
}
return int(val), nil
}
func (e *Eq) SetMode(index int, mode int) error {
address := fmt.Sprintf(e.baseAddress, index) + "/eq/mode"
return e.client.SendMessage(address, int32(mode))
}
// Gain retrieves the gain for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) Gain(index int, band int) (float64, error) {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/g", band)
err := e.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for EQ gain value")
}
return linGet(-15, 15, float64(val)), nil
}
// SetGain sets the gain for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) SetGain(index int, band int, gain float64) error {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/g", band)
return e.client.SendMessage(address, float32(linSet(-15, 15, gain)))
}
// Frequency retrieves the frequency for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) Frequency(index int, band int) (float64, error) {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/f", band)
err := e.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for EQ frequency value")
}
return logGet(20, 20000, float64(val)), nil
}
// SetFrequency sets the frequency for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) SetFrequency(index int, band int, frequency float64) error {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/f", band)
return e.client.SendMessage(address, float32(logSet(20, 20000, frequency)))
}
// Q retrieves the Q factor for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) Q(index int, band int) (float64, error) {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/q", band)
err := e.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for EQ Q value")
}
return logGet(0.3, 10, 1.0-float64(val)), nil
}
// SetQ sets the Q factor for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) SetQ(index int, band int, q float64) error {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/q", band)
return e.client.SendMessage(address, float32(1.0-logSet(0.3, 10, q)))
}
// Type retrieves the type for a specific EQ band on a strip or bus (1-based indexing).
func (e *Eq) Type(index int, band int) (int, error) {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
err := e.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-e.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for EQ type value")
}
return int(val), nil
}
// 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 {
address := fmt.Sprintf(e.baseAddress, index) + fmt.Sprintf("/eq/%d/type", band)
return e.client.SendMessage(address, int32(eqType))
}

View File

@ -1,38 +0,0 @@
package xair
import "fmt"
type Gate struct {
client *Client
baseAddress string
}
func newGate(c *Client) *Gate {
return &Gate{client: c, baseAddress: c.addressMap["strip"]}
}
// On retrieves the on/off status of the Gate for a specific strip (1-based indexing).
func (g *Gate) On(index int) (bool, error) {
address := fmt.Sprintf(g.baseAddress, index) + "/gate/on"
err := g.client.SendMessage(address)
if err != nil {
return false, err
}
resp := <-g.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return false, fmt.Errorf("unexpected argument type for Gate on value")
}
return val != 0, nil
}
// SetOn sets the on/off status of the Gate for a specific strip (1-based indexing).
func (g *Gate) SetOn(index int, on bool) error {
address := fmt.Sprintf(g.baseAddress, index) + "/gate/on"
var value int32
if on {
value = 1
}
return g.client.SendMessage(address, value)
}

View File

@ -4,10 +4,10 @@ import "fmt"
type HeadAmp struct {
baseAddress string
client *Client
client Client
}
func NewHeadAmp(c *Client) *HeadAmp {
func NewHeadAmp(c Client) *HeadAmp {
return &HeadAmp{
baseAddress: c.addressMap["headamp"],
client: c,

View File

@ -3,10 +3,10 @@ package xair
import "fmt"
type Main struct {
client *Client
client Client
}
func newMain(c *Client) *Main {
func newMain(c Client) *Main {
return &Main{
client: c,
}

View File

@ -4,19 +4,13 @@ import "fmt"
type Strip struct {
baseAddress string
client *Client
Gate *Gate
Eq *Eq
Comp *Comp
client Client
}
func NewStrip(c *Client) *Strip {
func NewStrip(c Client) *Strip {
return &Strip{
baseAddress: c.addressMap["strip"],
client: c,
Gate: newGate(c),
Eq: newEqForStrip(c),
Comp: newCompForStrip(c),
}
}

View File

@ -10,14 +10,6 @@ func linSet(min float64, max float64, value float64) float64 {
return (value - min) / (max - min)
}
func logGet(min float64, max float64, value float64) float64 {
return min * math.Exp(math.Log(max/min)*value)
}
func logSet(min float64, max float64, value float64) float64 {
return math.Log(value/min) / math.Log(max/min)
}
func mustDbInto(db float64) float64 {
switch {
case db >= 10:
@ -56,13 +48,3 @@ func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(math.Round(num*output)) / output
}
// 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
}