upd func handles

This commit is contained in:
onyx-and-iris 2026-01-31 01:38:42 +00:00
parent 8c10df9ed2
commit aabe33c8e5

View File

@ -73,24 +73,24 @@ func NewClient(mixerIP string, mixerPort int, opts ...Option) (*Client, error) {
} }
// Start begins listening for messages in a goroutine // Start begins listening for messages in a goroutine
func (x *Client) StartListening() { func (c *Client) StartListening() {
go x.receiveLoop() go c.receiveLoop()
log.Debugf("Started listening on %s...", x.conn.LocalAddr().String()) log.Debugf("Started listening on %s...", c.conn.LocalAddr().String())
} }
// receiveLoop handles incoming OSC messages // receiveLoop handles incoming OSC messages
func (x *Client) receiveLoop() { func (c *Client) receiveLoop() {
buffer := make([]byte, 4096) buffer := make([]byte, 4096)
for { for {
select { select {
case <-x.done: case <-c.done:
return return
default: default:
// Set read timeout to avoid blocking forever // Set read timeout to avoid blocking forever
x.conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c.conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, _, err := x.conn.ReadFromUDP(buffer) n, _, err := c.conn.ReadFromUDP(buffer)
if err != nil { if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() { if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
// Timeout is expected, continue loop // Timeout is expected, continue loop
@ -98,7 +98,7 @@ func (x *Client) receiveLoop() {
} }
// Check if we're shutting down to avoid logging expected errors // Check if we're shutting down to avoid logging expected errors
select { select {
case <-x.done: case <-c.done:
return return
default: default:
log.Errorf("Read error: %v", err) log.Errorf("Read error: %v", err)
@ -106,19 +106,19 @@ func (x *Client) receiveLoop() {
} }
} }
msg, err := x.parseOSCMessage(buffer[:n]) msg, err := c.parseOSCMessage(buffer[:n])
if err != nil { if err != nil {
log.Errorf("Failed to parse OSC message: %v", err) log.Errorf("Failed to parse OSC message: %v", err)
continue continue
} }
x.respChan <- msg c.respChan <- msg
} }
} }
} }
// parseOSCMessage parses raw bytes into an OSC message with improved error handling // parseOSCMessage parses raw bytes into an OSC message with improved error handling
func (x *Client) parseOSCMessage(data []byte) (*osc.Message, error) { func (c *Client) parseOSCMessage(data []byte) (*osc.Message, error) {
msg, err := x.parser.Parse(data) msg, err := c.parser.Parse(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -127,20 +127,20 @@ func (x *Client) parseOSCMessage(data []byte) (*osc.Message, error) {
} }
// Stop stops the client and closes the connection // Stop stops the client and closes the connection
func (x *Client) Stop() { func (c *Client) Stop() {
close(x.done) close(c.done)
if x.conn != nil { if c.conn != nil {
x.conn.Close() c.conn.Close()
} }
} }
// SendMessage sends an OSC message to the mixer using the unified connection // SendMessage sends an OSC message to the mixer using the unified connection
func (x *Client) SendMessage(address string, args ...any) error { func (c *Client) SendMessage(address string, args ...any) error {
return x.SendToAddress(x.mixerAddr, address, args...) return c.SendToAddress(c.mixerAddr, address, args...)
} }
// SendToAddress sends an OSC message to a specific address (enables replying to different ports) // SendToAddress sends an OSC message to a specific address (enables replying to different ports)
func (x *Client) SendToAddress(addr *net.UDPAddr, oscAddress string, args ...any) error { func (c *Client) SendToAddress(addr *net.UDPAddr, oscAddress string, args ...any) error {
msg := osc.NewMessage(oscAddress) msg := osc.NewMessage(oscAddress)
for _, arg := range args { for _, arg := range args {
msg.Append(arg) msg.Append(arg)
@ -163,18 +163,18 @@ func (x *Client) SendToAddress(addr *net.UDPAddr, oscAddress string, args ...any
return fmt.Errorf("failed to marshal message: %v", err) return fmt.Errorf("failed to marshal message: %v", err)
} }
_, err = x.conn.WriteToUDP(data, addr) _, err = c.conn.WriteToUDP(data, addr)
return err return err
} }
// RequestInfo requests mixer information // RequestInfo requests mixer information
func (x *Client) RequestInfo() (error, InfoResponse) { func (c *Client) RequestInfo() (error, InfoResponse) {
err := x.SendMessage("/xinfo") err := c.SendMessage("/xinfo")
if err != nil { if err != nil {
return err, InfoResponse{} return err, InfoResponse{}
} }
val := <-x.respChan val := <-c.respChan
var info InfoResponse var info InfoResponse
if len(val.Arguments) >= 3 { if len(val.Arguments) >= 3 {
info.Host = val.Arguments[0].(string) info.Host = val.Arguments[0].(string)
@ -185,26 +185,26 @@ func (x *Client) RequestInfo() (error, InfoResponse) {
} }
// KeepAlive sends keep-alive message (required for multi-client usage) // KeepAlive sends keep-alive message (required for multi-client usage)
func (x *Client) KeepAlive() error { func (c *Client) KeepAlive() error {
return x.SendMessage("/xremote") return c.SendMessage("/xremote")
} }
// RequestStatus requests mixer status // RequestStatus requests mixer status
func (x *Client) RequestStatus() error { func (c *Client) RequestStatus() error {
return x.SendMessage("/status") return c.SendMessage("/status")
} }
/* STRIP METHODS */ /* STRIP METHODS */
// StripMute gets mute state for a specific strip (1-based indexing) // StripMute gets mute state for a specific strip (1-based indexing)
func (x *Client) StripMute(strip int) (bool, error) { func (c *Client) StripMute(strip int) (bool, error) {
address := fmt.Sprintf("/ch/%02d/mix/on", strip) address := fmt.Sprintf("/ch/%02d/mix/on", strip)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return false, err return false, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(int32) val, ok := resp.Arguments[0].(int32)
if !ok { if !ok {
return false, fmt.Errorf("unexpected argument type for strip mute value") return false, fmt.Errorf("unexpected argument type for strip mute value")
@ -213,24 +213,24 @@ func (x *Client) StripMute(strip int) (bool, error) {
} }
// SetStripMute sets mute state for a specific strip (1-based indexing) // SetStripMute sets mute state for a specific strip (1-based indexing)
func (x *Client) SetStripMute(strip int, muted bool) error { func (c *Client) SetStripMute(strip int, muted bool) error {
address := fmt.Sprintf("/ch/%02d/mix/on", strip) address := fmt.Sprintf("/ch/%02d/mix/on", strip)
var value int32 = 0 var value int32 = 0
if !muted { if !muted {
value = 1 value = 1
} }
return x.SendMessage(address, value) return c.SendMessage(address, value)
} }
// StripFader requests the current fader level for a strip // StripFader requests the current fader level for a strip
func (x *Client) StripFader(strip int) (float64, error) { func (c *Client) StripFader(strip int) (float64, error) {
address := fmt.Sprintf("/ch/%02d/mix/fader", strip) address := fmt.Sprintf("/ch/%02d/mix/fader", strip)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return 0, err return 0, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(float32) val, ok := resp.Arguments[0].(float32)
if !ok { if !ok {
return 0, fmt.Errorf("unexpected argument type for fader value") return 0, fmt.Errorf("unexpected argument type for fader value")
@ -240,20 +240,20 @@ func (x *Client) StripFader(strip int) (float64, error) {
} }
// SetStripFader sets the fader level for a specific strip (1-based indexing) // SetStripFader sets the fader level for a specific strip (1-based indexing)
func (x *Client) SetStripFader(strip int, level float64) error { func (c *Client) SetStripFader(strip int, level float64) error {
address := fmt.Sprintf("/ch/%02d/mix/fader", strip) address := fmt.Sprintf("/ch/%02d/mix/fader", strip)
return x.SendMessage(address, float32(mustDbInto(level))) return c.SendMessage(address, float32(mustDbInto(level)))
} }
// StripMicGain requests the phantom gain for a specific strip // StripMicGain requests the phantom gain for a specific strip
func (x *Client) StripMicGain(strip int) (float64, error) { func (c *Client) StripMicGain(strip int) (float64, error) {
address := fmt.Sprintf("/ch/%02d/mix/gain", strip) address := fmt.Sprintf("/ch/%02d/mix/gain", strip)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return 0, fmt.Errorf("failed to send strip gain request: %v", err) return 0, fmt.Errorf("failed to send strip gain request: %v", err)
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(float32) val, ok := resp.Arguments[0].(float32)
if !ok { if !ok {
return 0, fmt.Errorf("unexpected argument type for strip gain value") return 0, fmt.Errorf("unexpected argument type for strip gain value")
@ -262,20 +262,20 @@ func (x *Client) StripMicGain(strip int) (float64, error) {
} }
// SetStripMicGain sets the phantom gain for a specific strip (1-based indexing) // SetStripMicGain sets the phantom gain for a specific strip (1-based indexing)
func (x *Client) SetStripMicGain(strip int, gain float32) error { func (c *Client) SetStripMicGain(strip int, gain float32) error {
address := fmt.Sprintf("/ch/%02d/mix/gain", strip) address := fmt.Sprintf("/ch/%02d/mix/gain", strip)
return x.SendMessage(address, gain) return c.SendMessage(address, gain)
} }
// StripName requests the name for a specific strip // StripName requests the name for a specific strip
func (x *Client) StripName(strip int) (string, error) { func (c *Client) StripName(strip int) (string, error) {
address := fmt.Sprintf("/ch/%02d/config/name", strip) address := fmt.Sprintf("/ch/%02d/config/name", strip)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to send strip name request: %v", err) return "", fmt.Errorf("failed to send strip name request: %v", err)
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(string) val, ok := resp.Arguments[0].(string)
if !ok { if !ok {
return "", fmt.Errorf("unexpected argument type for strip name value") return "", fmt.Errorf("unexpected argument type for strip name value")
@ -284,20 +284,20 @@ func (x *Client) StripName(strip int) (string, error) {
} }
// SetStripName sets the name for a specific strip // SetStripName sets the name for a specific strip
func (x *Client) SetStripName(strip int, name string) error { func (c *Client) SetStripName(strip int, name string) error {
address := fmt.Sprintf("/ch/%02d/config/name", strip) address := fmt.Sprintf("/ch/%02d/config/name", strip)
return x.SendMessage(address, name) return c.SendMessage(address, name)
} }
// StripColor requests the color for a specific strip // StripColor requests the color for a specific strip
func (x *Client) StripColor(strip int) (int32, error) { func (c *Client) StripColor(strip int) (int32, error) {
address := fmt.Sprintf("/ch/%02d/config/color", strip) address := fmt.Sprintf("/ch/%02d/config/color", strip)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return 0, fmt.Errorf("failed to send strip color request: %v", err) return 0, fmt.Errorf("failed to send strip color request: %v", err)
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(int32) val, ok := resp.Arguments[0].(int32)
if !ok { if !ok {
return 0, fmt.Errorf("unexpected argument type for strip color value") return 0, fmt.Errorf("unexpected argument type for strip color value")
@ -306,23 +306,23 @@ func (x *Client) StripColor(strip int) (int32, error) {
} }
// SetStripColor sets the color for a specific strip (0-15) // SetStripColor sets the color for a specific strip (0-15)
func (x *Client) SetStripColor(strip int, color int32) error { func (c *Client) SetStripColor(strip int, color int32) error {
address := fmt.Sprintf("/ch/%02d/config/color", strip) address := fmt.Sprintf("/ch/%02d/config/color", strip)
return x.SendMessage(address, color) return c.SendMessage(address, color)
} }
/* BUS METHODS */ /* BUS METHODS */
// BusMute requests the current mute status for a bus // BusMute requests the current mute status for a bus
func (x *Client) BusMute(bus int) (bool, error) { func (c *Client) BusMute(bus int) (bool, error) {
formatter := x.addressMap["bus"] formatter := c.addressMap["bus"]
address := fmt.Sprintf(formatter, bus) + "/mix/on" address := fmt.Sprintf(formatter, bus) + "/mix/on"
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return false, err return false, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(int32) val, ok := resp.Arguments[0].(int32)
if !ok { if !ok {
return false, fmt.Errorf("unexpected argument type for bus mute value") return false, fmt.Errorf("unexpected argument type for bus mute value")
@ -331,25 +331,25 @@ func (x *Client) BusMute(bus int) (bool, error) {
} }
// SetBusMute sets the mute status for a specific bus (1-based indexing) // SetBusMute sets the mute status for a specific bus (1-based indexing)
func (x *Client) SetBusMute(bus int, muted bool) error { func (c *Client) SetBusMute(bus int, muted bool) error {
formatter := x.addressMap["bus"] formatter := c.addressMap["bus"]
address := fmt.Sprintf(formatter, bus) + "/mix/on" address := fmt.Sprintf(formatter, bus) + "/mix/on"
var value int32 = 0 var value int32 = 0
if !muted { if !muted {
value = 1 value = 1
} }
return x.SendMessage(address, value) return c.SendMessage(address, value)
} }
// BusFader requests the current fader level for a bus // BusFader requests the current fader level for a bus
func (x *Client) BusFader(bus int) (float64, error) { func (c *Client) BusFader(bus int) (float64, error) {
address := fmt.Sprintf("/bus/%01d/mix/fader", bus) address := fmt.Sprintf("/bus/%01d/mix/fader", bus)
err := x.SendMessage(address) err := c.SendMessage(address)
if err != nil { if err != nil {
return 0, err return 0, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(float32) val, ok := resp.Arguments[0].(float32)
if !ok { if !ok {
return 0, fmt.Errorf("unexpected argument type for bus fader value") return 0, fmt.Errorf("unexpected argument type for bus fader value")
@ -359,21 +359,21 @@ func (x *Client) BusFader(bus int) (float64, error) {
} }
// SetBusFader sets the fader level for a specific bus (1-based indexing) // SetBusFader sets the fader level for a specific bus (1-based indexing)
func (x *Client) SetBusFader(bus int, level float64) error { func (c *Client) SetBusFader(bus int, level float64) error {
address := fmt.Sprintf("/bus/%01d/mix/fader", bus) address := fmt.Sprintf("/bus/%01d/mix/fader", bus)
return x.SendMessage(address, float32(mustDbInto(level))) return c.SendMessage(address, float32(mustDbInto(level)))
} }
/* MAIN LR METHODS */ /* MAIN LR METHODS */
// MainLRFader requests the current main L/R fader level // MainLRFader requests the current main L/R fader level
func (x *Client) MainLRFader() (float64, error) { func (c *Client) MainLRFader() (float64, error) {
err := x.SendMessage("/lr/mix/fader") err := c.SendMessage("/lr/mix/fader")
if err != nil { if err != nil {
return 0, err return 0, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(float32) val, ok := resp.Arguments[0].(float32)
if !ok { if !ok {
return 0, fmt.Errorf("unexpected argument type for main LR fader value") return 0, fmt.Errorf("unexpected argument type for main LR fader value")
@ -382,18 +382,18 @@ func (x *Client) MainLRFader() (float64, error) {
} }
// SetMainLRFader sets the main L/R fader level // SetMainLRFader sets the main L/R fader level
func (x *Client) SetMainLRFader(level float64) error { func (c *Client) SetMainLRFader(level float64) error {
return x.SendMessage("/lr/mix/fader", float32(mustDbInto(level))) return c.SendMessage("/lr/mix/fader", float32(mustDbInto(level)))
} }
// MainLRMute requests the current main L/R mute status // MainLRMute requests the current main L/R mute status
func (x *Client) MainLRMute() (bool, error) { func (c *Client) MainLRMute() (bool, error) {
err := x.SendMessage("/lr/mix/on") err := c.SendMessage("/lr/mix/on")
if err != nil { if err != nil {
return false, err return false, err
} }
resp := <-x.respChan resp := <-c.respChan
val, ok := resp.Arguments[0].(int32) val, ok := resp.Arguments[0].(int32)
if !ok { if !ok {
return false, fmt.Errorf("unexpected argument type for main LR mute value") return false, fmt.Errorf("unexpected argument type for main LR mute value")
@ -402,10 +402,10 @@ func (x *Client) MainLRMute() (bool, error) {
} }
// SetMainLRMute sets the main L/R mute status // SetMainLRMute sets the main L/R mute status
func (x *Client) SetMainLRMute(muted bool) error { func (c *Client) SetMainLRMute(muted bool) error {
var value int32 = 0 var value int32 = 0
if !muted { if !muted {
value = 1 value = 1
} }
return x.SendMessage("/lr/mix/on", value) return c.SendMessage("/lr/mix/on", value)
} }