mirror of
https://github.com/onyx-and-iris/xair-cli.git
synced 2026-02-26 08:19:11 +00:00
- add package comments - fix redeclaration of built-in min/max - add comments to exported types - remove unused parameters
156 lines
3.6 KiB
Go
156 lines
3.6 KiB
Go
// Package xair provides a client for controlling XAir and X32 mixers using OSC messages.
|
|
package xair
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/charmbracelet/log"
|
|
"github.com/hypebeast/go-osc/osc"
|
|
)
|
|
|
|
// XAirClient is a client for controlling XAir mixers.
|
|
type XAirClient struct { // nolint: revive
|
|
client
|
|
Main *Main
|
|
Strip *Strip
|
|
Bus *Bus
|
|
HeadAmp *HeadAmp
|
|
Snapshot *Snapshot
|
|
DCA *DCA
|
|
}
|
|
|
|
// NewXAirClient creates a new XAirClient instance with optional engine configuration.
|
|
func NewXAirClient(mixerIP string, mixerPort int, opts ...EngineOption) (*XAirClient, error) {
|
|
e, err := newEngine(mixerIP, mixerPort, kindXAir, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c := &XAirClient{
|
|
client: client{e, InfoResponse{}},
|
|
}
|
|
c.Main = newMainStereo(&c.client)
|
|
c.Strip = newStrip(&c.client)
|
|
c.Bus = newBus(&c.client)
|
|
c.HeadAmp = newHeadAmp(&c.client)
|
|
c.Snapshot = newSnapshot(&c.client)
|
|
c.DCA = newDCA(&c.client)
|
|
|
|
return c, nil
|
|
}
|
|
|
|
// X32Client is a client for controlling X32 mixers.
|
|
type X32Client struct { // nolint: revive
|
|
client
|
|
Main *Main
|
|
MainMono *Main
|
|
Matrix *Matrix
|
|
Strip *Strip
|
|
Bus *Bus
|
|
HeadAmp *HeadAmp
|
|
Snapshot *Snapshot
|
|
DCA *DCA
|
|
}
|
|
|
|
// NewX32Client creates a new X32Client instance with optional engine configuration.
|
|
func NewX32Client(mixerIP string, mixerPort int, opts ...EngineOption) (*X32Client, error) {
|
|
e, err := newEngine(mixerIP, mixerPort, kindX32, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c := &X32Client{
|
|
client: client{e, InfoResponse{}},
|
|
}
|
|
c.Main = newMainStereo(&c.client)
|
|
c.MainMono = newMainMono(&c.client)
|
|
c.Matrix = newMatrix(&c.client)
|
|
c.Strip = newStrip(&c.client)
|
|
c.Bus = newBus(&c.client)
|
|
c.HeadAmp = newHeadAmp(&c.client)
|
|
c.Snapshot = newSnapshot(&c.client)
|
|
c.DCA = newDCA(&c.client)
|
|
|
|
return c, nil
|
|
}
|
|
|
|
type client struct {
|
|
*engine
|
|
Info InfoResponse
|
|
}
|
|
|
|
// StartListening begins listening for messages in a goroutine.
|
|
func (c *client) StartListening() {
|
|
go c.receiveLoop()
|
|
log.Debugf("Started listening on %s...", c.engine.conn.LocalAddr().String())
|
|
}
|
|
|
|
// Close stops the client and closes the connection.
|
|
func (c *client) Close() {
|
|
close(c.done)
|
|
if c.conn != nil {
|
|
c.conn.Close()
|
|
}
|
|
}
|
|
|
|
// SendMessage sends an OSC message to the mixer using the unified connection.
|
|
func (c *client) SendMessage(address string, args ...any) error {
|
|
return c.sendToAddress(c.mixerAddr, address, args...)
|
|
}
|
|
|
|
// ReceiveMessage receives an OSC message from the mixer.
|
|
func (c *client) ReceiveMessage() (*osc.Message, error) {
|
|
t := time.Tick(c.timeout)
|
|
select {
|
|
case <-t:
|
|
return nil, fmt.Errorf("timeout waiting for response")
|
|
case msg := <-c.respChan:
|
|
if msg == nil {
|
|
return nil, fmt.Errorf("no message received")
|
|
}
|
|
return msg, nil
|
|
}
|
|
}
|
|
|
|
// RequestInfo requests mixer information.
|
|
func (c *client) RequestInfo() (InfoResponse, error) {
|
|
var info InfoResponse
|
|
err := c.SendMessage("/xinfo")
|
|
if err != nil {
|
|
return info, err
|
|
}
|
|
|
|
msg, err := c.ReceiveMessage()
|
|
if err != nil {
|
|
return info, err
|
|
}
|
|
if len(msg.Arguments) == 4 {
|
|
if host, ok := msg.Arguments[0].(string); ok {
|
|
info.Host = host
|
|
}
|
|
if name, ok := msg.Arguments[1].(string); ok {
|
|
info.Name = name
|
|
}
|
|
if model, ok := msg.Arguments[2].(string); ok {
|
|
info.Model = model
|
|
}
|
|
if firmware, ok := msg.Arguments[3].(string); ok {
|
|
info.Firmware = firmware
|
|
}
|
|
}
|
|
c.Info = info
|
|
|
|
return info, nil
|
|
}
|
|
|
|
// KeepAlive sends keep-alive message (required for multi-client usage).
|
|
func (c *client) KeepAlive() error {
|
|
return c.SendMessage("/xremote")
|
|
}
|
|
|
|
// RequestStatus requests mixer status.
|
|
func (c *client) RequestStatus() error {
|
|
return c.SendMessage("/status")
|
|
}
|