Add sACN input/output support and fix multi-source merging
- Add sACN/E1.31 protocol support for both input and output - from_proto = "sacn" to receive from sACN multicast - proto = "sacn" to output via sACN multicast - Fix remap engine to maintain persistent state per output universe - Multiple inputs targeting same output now merge correctly - Prevents flickering when multiple universes feed same output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
67
sacn/sender.go
Normal file
67
sacn/sender.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package sacn
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Sender sends sACN (E1.31) packets
|
||||
type Sender struct {
|
||||
conn *net.UDPConn
|
||||
sourceName string
|
||||
cid [16]byte
|
||||
sequences map[uint16]uint8
|
||||
seqMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewSender creates a new sACN sender
|
||||
func NewSender(sourceName string) (*Sender, error) {
|
||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate random CID
|
||||
var cid [16]byte
|
||||
rand.Read(cid[:])
|
||||
|
||||
return &Sender{
|
||||
conn: conn,
|
||||
sourceName: sourceName,
|
||||
cid: cid,
|
||||
sequences: make(map[uint16]uint8),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendDMX sends DMX data to a universe via multicast
|
||||
func (s *Sender) SendDMX(universe uint16, data []byte) error {
|
||||
s.seqMu.Lock()
|
||||
seq := s.sequences[universe]
|
||||
s.sequences[universe] = seq + 1
|
||||
s.seqMu.Unlock()
|
||||
|
||||
pkt := BuildDataPacket(universe, seq, s.sourceName, s.cid, data)
|
||||
addr := MulticastAddr(universe)
|
||||
|
||||
_, err := s.conn.WriteToUDP(pkt, addr)
|
||||
return err
|
||||
}
|
||||
|
||||
// SendDMXUnicast sends DMX data to a specific address
|
||||
func (s *Sender) SendDMXUnicast(addr *net.UDPAddr, universe uint16, data []byte) error {
|
||||
s.seqMu.Lock()
|
||||
seq := s.sequences[universe]
|
||||
s.sequences[universe] = seq + 1
|
||||
s.seqMu.Unlock()
|
||||
|
||||
pkt := BuildDataPacket(universe, seq, s.sourceName, s.cid, data)
|
||||
|
||||
_, err := s.conn.WriteToUDP(pkt, addr)
|
||||
return err
|
||||
}
|
||||
|
||||
// Close closes the sender
|
||||
func (s *Sender) Close() error {
|
||||
return s.conn.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user