add headamp gain and phantom commands

This commit is contained in:
onyx-and-iris 2026-02-01 01:25:47 +00:00
parent 64b4be032f
commit fea29fade6
6 changed files with 256 additions and 31 deletions

146
cmd/headamp.go Normal file
View File

@ -0,0 +1,146 @@
package cmd
import (
"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.
Examples:
# Get gain level for headamp index 1
xairctl headamp gain 1
# Set gain level for headamp index 1 to 3.5 dB
xairctl headamp gain 1 3.5`,
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
client := ClientFromContext(cmd.Context())
if client == nil {
cmd.PrintErrln("OSC client not found in context")
return
}
if len(args) < 1 {
cmd.PrintErrln("Please provide a headamp index")
return
}
index := mustConvToInt(args[0])
if len(args) == 1 {
gain, err := client.HeadAmp.Gain(index)
if err != nil {
cmd.PrintErrln("Error getting headamp gain level:", err)
return
}
cmd.Printf("Headamp %d Gain: %.2f dB\n", index, gain)
return
}
if len(args) < 2 {
cmd.PrintErrln("Please provide a gain level in dB")
return
}
level := mustConvToFloat64(args[1])
err := client.HeadAmp.SetGain(index, level)
if err != nil {
cmd.PrintErrln("Error setting headamp gain level:", err)
return
}
cmd.Printf("Headamp %d Gain set to %.2f dB\n", index, level)
},
}
// 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),
Run: func(cmd *cobra.Command, args []string) {
client := ClientFromContext(cmd.Context())
if client == nil {
cmd.PrintErrln("OSC client not found in context")
return
}
if len(args) < 1 {
cmd.PrintErrln("Please provide a headamp index")
return
}
index := mustConvToInt(args[0])
if len(args) == 1 {
enabled, err := client.HeadAmp.PhantomPower(index)
if err != nil {
cmd.PrintErrln("Error getting headamp phantom power status:", err)
return
}
status := "disabled"
if enabled {
status = "enabled"
}
cmd.Printf("Headamp %d Phantom Power is %s\n", index, status)
return
}
if len(args) < 2 {
cmd.PrintErrln("Please provide phantom power status: on or off")
return
}
var enable bool
switch args[1] {
case "on", "enable":
enable = true
case "off", "disable":
enable = false
default:
cmd.PrintErrln("Invalid phantom power status. Use 'on' or 'off'")
return
}
err := client.HeadAmp.SetPhantomPower(index, enable)
if err != nil {
cmd.PrintErrln("Error setting headamp phantom power status:", err)
return
}
status := "disabled"
if enable {
status = "enabled"
}
cmd.Printf("Headamp %d Phantom Power %s successfully\n", index, status)
},
}
func init() {
rootCmd.AddCommand(headampCmd)
headampCmd.AddCommand(headampGainCmd)
headampCmd.AddCommand(headampPhantomPowerCmd)
}

View File

@ -1,13 +1,15 @@
package xair
var xairAddressMap = map[string]string{
"strip": "/ch/%02d",
"bus": "/bus/%01d",
"strip": "/ch/%02d",
"bus": "/bus/%01d",
"headamp": "/headamp/%02d",
}
var x32AddressMap = map[string]string{
"strip": "/ch/%02d",
"bus": "/bus/%02d",
"strip": "/ch/%02d",
"bus": "/bus/%02d",
"headamp": "/headamp/%02d",
}
func addressMapForMixerKind(kind MixerKind) map[string]string {

View File

@ -15,9 +15,10 @@ type parser interface {
type Client struct {
engine
Main *Main
Strip *Strip
Bus *Bus
Main *Main
Strip *Strip
Bus *Bus
HeadAmp *HeadAmp
}
// NewClient creates a new XAirClient instance
@ -60,6 +61,7 @@ func NewClient(mixerIP string, mixerPort int, opts ...Option) (*Client, error) {
c.Main = newMain(*c)
c.Strip = NewStrip(*c)
c.Bus = NewBus(*c)
c.HeadAmp = NewHeadAmp(*c)
return c, nil
}

67
internal/xair/headamp.go Normal file
View File

@ -0,0 +1,67 @@
package xair
import "fmt"
type HeadAmp struct {
baseAddress string
client Client
}
func NewHeadAmp(c Client) *HeadAmp {
return &HeadAmp{
baseAddress: c.addressMap["headamp"],
client: c,
}
}
// Gain gets the gain level for the specified headamp index.
func (h *HeadAmp) Gain(index int) (float64, error) {
address := fmt.Sprintf(h.baseAddress, index) + "/gain"
err := h.client.SendMessage(address)
if err != nil {
return 0, err
}
resp := <-h.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for headamp gain value")
}
return linGet(-12, 60, float64(val)), nil
}
// SetGain sets the gain level for the specified headamp index.
func (h *HeadAmp) SetGain(index int, level float64) error {
address := fmt.Sprintf(h.baseAddress, index) + "/gain"
return h.client.SendMessage(address, float32(linSet(-12, 60, level)))
}
// PhantomPower gets the phantom power status for the specified headamp index.
func (h *HeadAmp) PhantomPower(index int) (bool, error) {
address := fmt.Sprintf(h.baseAddress, index) + "/phantom"
err := h.client.SendMessage(address)
if err != nil {
return false, err
}
resp := <-h.client.respChan
val, ok := resp.Arguments[0].(int32)
if !ok {
return false, fmt.Errorf("unexpected argument type for phantom power value")
}
return val != 0, nil
}
// SetPhantomPower sets the phantom power status for the specified headamp index.
func (h *HeadAmp) SetPhantomPower(index int, enabled bool) error {
address := fmt.Sprintf(h.baseAddress, index) + "/phantom"
var val int32
if enabled {
val = 1
} else {
val = 0
}
return h.client.SendMessage(address, val)
}

View File

@ -15,8 +15,8 @@ func NewStrip(c Client) *Strip {
}
// Mute gets the mute status of the specified strip (1-based indexing).
func (s *Strip) Mute(strip int) (bool, error) {
address := fmt.Sprintf(s.baseAddress, strip) + "/mix/on"
func (s *Strip) Mute(index int) (bool, error) {
address := fmt.Sprintf(s.baseAddress, index) + "/mix/on"
err := s.client.SendMessage(address)
if err != nil {
return false, err
@ -63,28 +63,6 @@ func (s *Strip) SetFader(strip int, level float64) error {
return s.client.SendMessage(address, float32(mustDbInto(level)))
}
// MicGain requests the phantom gain for a specific strip (1-based indexing).
func (s *Strip) MicGain(strip int) (float64, error) {
address := fmt.Sprintf(s.baseAddress, strip) + "/mix/gain"
err := s.client.SendMessage(address)
if err != nil {
return 0, fmt.Errorf("failed to send strip gain request: %v", err)
}
resp := <-s.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for strip gain value")
}
return mustDbFrom(float64(val)), nil
}
// SetMicGain sets the phantom gain for a specific strip (1-based indexing).
func (s *Strip) SetMicGain(strip int, gain float32) error {
address := fmt.Sprintf(s.baseAddress, strip) + "/mix/gain"
return s.client.SendMessage(address, gain)
}
// Name requests the name for a specific strip
func (s *Strip) Name(strip int) (string, error) {
address := fmt.Sprintf(s.baseAddress, strip) + "/config/name"
@ -150,3 +128,25 @@ func (s *Strip) SetSendLevel(strip int, bus int, level float64) error {
address := fmt.Sprintf(s.baseAddress, strip) + fmt.Sprintf("/mix/%02d/level", bus)
return s.client.SendMessage(address, float32(mustDbInto(level)))
}
// MicGain requests the phantom gain for a specific strip (1-based indexing).
func (s *Strip) MicGain(strip int) (float64, error) {
address := fmt.Sprintf(s.baseAddress, strip) + "/mix/gain"
err := s.client.SendMessage(address)
if err != nil {
return 0, fmt.Errorf("failed to send strip gain request: %v", err)
}
resp := <-s.client.respChan
val, ok := resp.Arguments[0].(float32)
if !ok {
return 0, fmt.Errorf("unexpected argument type for strip gain value")
}
return mustDbFrom(float64(val)), nil
}
// SetMicGain sets the phantom gain for a specific strip (1-based indexing).
func (s *Strip) SetMicGain(strip int, gain float64) error {
address := fmt.Sprintf(s.baseAddress, strip) + "/mix/gain"
return s.client.SendMessage(address, float32(mustDbInto(gain)))
}

View File

@ -2,6 +2,14 @@ package xair
import "math"
func linGet(min float64, max float64, value float64) float64 {
return min + (max-min)*value
}
func linSet(min float64, max float64, value float64) float64 {
return (value - min) / (max - min)
}
func mustDbInto(db float64) float64 {
switch {
case db >= 10: