Add sACN unicast target support
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
# --artnet-listen=:6454 ArtNet listen address (empty to disable)
|
||||
# --artnet-broadcast=auto Broadcast addresses (comma-separated, or 'auto')
|
||||
|
||||
# Target addresses for ArtNet output universes
|
||||
# Each output universe needs a target IP (broadcast or unicast)
|
||||
# ArtPoll discovery will be sent to all unique target addresses
|
||||
# Target addresses for output universes
|
||||
# ArtNet: target IP (broadcast or unicast), ArtPoll discovery sent to all
|
||||
# sACN: unicast targets sent in addition to multicast
|
||||
[[target]]
|
||||
universe = "artnet:0.0.0"
|
||||
address = "2.255.255.255"
|
||||
@@ -16,6 +16,10 @@ address = "2.255.255.255"
|
||||
universe = "artnet:0.0.5"
|
||||
address = "10.50.255.255"
|
||||
|
||||
[[target]]
|
||||
universe = "sacn:1"
|
||||
address = "192.168.1.100"
|
||||
|
||||
# Address format:
|
||||
# proto:universe[:channels]
|
||||
#
|
||||
|
||||
53
main.go
53
main.go
@@ -25,7 +25,8 @@ type App struct {
|
||||
sacnSender *sacn.Sender
|
||||
discovery *artnet.Discovery
|
||||
engine *remap.Engine
|
||||
targets map[artnet.Universe]*net.UDPAddr
|
||||
artTargets map[artnet.Universe]*net.UDPAddr
|
||||
sacnTargets map[uint16][]*net.UDPAddr
|
||||
debug bool
|
||||
}
|
||||
|
||||
@@ -53,19 +54,28 @@ func main() {
|
||||
}
|
||||
|
||||
// Parse targets
|
||||
targets := make(map[artnet.Universe]*net.UDPAddr)
|
||||
artTargets := make(map[artnet.Universe]*net.UDPAddr)
|
||||
sacnTargets := make(map[uint16][]*net.UDPAddr)
|
||||
pollTargets := make(map[string]*net.UDPAddr) // dedupe by address string
|
||||
for _, t := range cfg.Targets {
|
||||
if t.Universe.Protocol != config.ProtocolArtNet {
|
||||
continue // only artnet targets need addresses
|
||||
}
|
||||
addr, err := parseTargetAddr(t.Address)
|
||||
switch t.Universe.Protocol {
|
||||
case config.ProtocolArtNet:
|
||||
addr, err := parseTargetAddr(t.Address, artnet.Port)
|
||||
if err != nil {
|
||||
log.Fatalf("target error: address=%q err=%v", t.Address, err)
|
||||
}
|
||||
targets[t.Universe.Universe] = addr
|
||||
artTargets[t.Universe.Universe] = addr
|
||||
pollTargets[addr.String()] = addr
|
||||
log.Printf("[config] target %s -> %s", t.Universe, addr)
|
||||
case config.ProtocolSACN:
|
||||
addr, err := parseTargetAddr(t.Address, sacn.Port)
|
||||
if err != nil {
|
||||
log.Fatalf("target error: address=%q err=%v", t.Address, err)
|
||||
}
|
||||
u := uint16(t.Universe.Universe)
|
||||
sacnTargets[u] = append(sacnTargets[u], addr)
|
||||
log.Printf("[config] target %s -> %s", t.Universe, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse broadcast addresses
|
||||
@@ -76,7 +86,7 @@ func main() {
|
||||
} else {
|
||||
for _, addrStr := range strings.Split(*artnetBroadcast, ",") {
|
||||
addrStr = strings.TrimSpace(addrStr)
|
||||
addr, err := parseTargetAddr(addrStr)
|
||||
addr, err := parseTargetAddr(addrStr, artnet.Port)
|
||||
if err != nil {
|
||||
log.Fatalf("broadcast error: address=%q err=%v", addrStr, err)
|
||||
}
|
||||
@@ -120,7 +130,8 @@ func main() {
|
||||
sacnSender: sacnSender,
|
||||
discovery: discovery,
|
||||
engine: engine,
|
||||
targets: targets,
|
||||
artTargets: artTargets,
|
||||
sacnTargets: sacnTargets,
|
||||
debug: *debug,
|
||||
}
|
||||
|
||||
@@ -208,16 +219,24 @@ func (a *App) sendOutputs(outputs []remap.Output) {
|
||||
for _, out := range outputs {
|
||||
switch out.Protocol {
|
||||
case config.ProtocolSACN:
|
||||
u := uint16(out.Universe)
|
||||
if a.debug {
|
||||
log.Printf("[->sacn] universe=%d", uint16(out.Universe))
|
||||
log.Printf("[->sacn] universe=%d", u)
|
||||
}
|
||||
if err := a.sacnSender.SendDMX(u, out.Data[:]); err != nil {
|
||||
log.Printf("[->sacn] error: universe=%d err=%v", u, err)
|
||||
}
|
||||
for _, target := range a.sacnTargets[u] {
|
||||
if a.debug {
|
||||
log.Printf("[->sacn] unicast dst=%s universe=%d", target.IP, u)
|
||||
}
|
||||
if err := a.sacnSender.SendDMXUnicast(target, u, out.Data[:]); err != nil {
|
||||
log.Printf("[->sacn] error: dst=%s err=%v", target.IP, err)
|
||||
}
|
||||
if err := a.sacnSender.SendDMX(uint16(out.Universe), out.Data[:]); err != nil {
|
||||
log.Printf("[->sacn] error: universe=%d err=%v", uint16(out.Universe), err)
|
||||
}
|
||||
|
||||
default: // ArtNet
|
||||
// Configured target takes priority over discovery
|
||||
if target, ok := a.targets[out.Universe]; ok {
|
||||
if target, ok := a.artTargets[out.Universe]; ok {
|
||||
if a.debug {
|
||||
log.Printf("[->artnet] dst=%s universe=%s", target.IP, out.Universe)
|
||||
}
|
||||
@@ -288,8 +307,8 @@ func parseListenAddr(s string) (*net.UDPAddr, error) {
|
||||
|
||||
// parseTargetAddr parses target address formats:
|
||||
// - "host:port" -> specific host and port
|
||||
// - "host" -> specific host, default ArtNet port
|
||||
func parseTargetAddr(s string) (*net.UDPAddr, error) {
|
||||
// - "host" -> specific host, default port
|
||||
func parseTargetAddr(s string, defaultPort int) (*net.UDPAddr, error) {
|
||||
var host string
|
||||
var port int
|
||||
|
||||
@@ -305,7 +324,7 @@ func parseTargetAddr(s string) (*net.UDPAddr, error) {
|
||||
}
|
||||
} else {
|
||||
host = s
|
||||
port = artnet.Port
|
||||
port = defaultPort
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
|
||||
Reference in New Issue
Block a user