78 lines
1.4 KiB
Go
78 lines
1.4 KiB
Go
package osc
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type Value struct {
|
|
Type byte
|
|
Float float32
|
|
Int int32
|
|
Bool bool
|
|
Str string
|
|
}
|
|
|
|
type Handler func(address string, args []Value) error
|
|
|
|
type Server struct {
|
|
addr string
|
|
conn *net.UDPConn
|
|
handlers map[string]Handler
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewServer(host string, port int) *Server {
|
|
return &Server{
|
|
addr: fmt.Sprintf("%s:%d", host, port),
|
|
handlers: map[string]Handler{},
|
|
}
|
|
}
|
|
|
|
func (s *Server) Map(param string, h Handler) { s.handlers["/avatar/parameters/"+param] = h }
|
|
func (s *Server) Close() error { if s.conn != nil { return s.conn.Close() }; return nil }
|
|
|
|
func (s *Server) Serve() error {
|
|
addr, err := net.ResolveUDPAddr("udp", s.addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
conn, err := net.ListenUDP("udp", addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.conn = conn
|
|
buf := make([]byte, 2048)
|
|
for {
|
|
n, _, err := conn.ReadFromUDP(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
a, v, err := parseMessage(buf[:n])
|
|
if err != nil {
|
|
continue
|
|
}
|
|
s.mu.RLock()
|
|
h := s.handlers[a]
|
|
s.mu.RUnlock()
|
|
if h != nil {
|
|
_ = h(a, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseMessage(b []byte) (string, []Value, error) {
|
|
parts := bytes.SplitN(b, []byte{0}, 2)
|
|
if len(parts) == 0 {
|
|
return "", nil, fmt.Errorf("invalid osc")
|
|
}
|
|
address := string(parts[0])
|
|
if !strings.HasPrefix(address, "/") {
|
|
return "", nil, fmt.Errorf("invalid address")
|
|
}
|
|
return address, nil, nil
|
|
}
|