package main import ( "flag" "fmt" "net" "os" "os/signal" "time" "git.lattuga.net/boyska/direttoforo/liquidsoap" "git.lattuga.net/boyska/direttoforo/uiserver" ) type State struct { Streams map[string]liquidsoap.Stream } func NewState() State { s := State{} s.Streams = make(map[string]liquidsoap.Stream) return s } func main() { liqfile := flag.String("liq", "foo.liq", "Path to liquidsoap script to run") bindpath := flag.String("bindpath", "/var/lib/direttoforo/ui.sock", "UNIX domain socket path for UIs") flag.Parse() state := NewState() netUIsock, err := net.Listen("unix", *bindpath) if err != nil { fmt.Fprintln(os.Stderr, "error binding UI socket!") fmt.Fprintln(os.Stderr, err) os.Exit(1) return } netUI := uiserver.NewNetUI(&state) go func() { err := netUI.Run(netUIsock) if err != nil { fmt.Fprintln(os.Stderr, "NetUI error", err) } }() killLs := make(chan struct{}) // when it is closed, liquidsoap will die killed := make(chan os.Signal, 1) signal.Notify(killed, os.Interrupt) // ctrl-c output, exit, err := liquidsoap.RunLiquidsoap(*liqfile, killLs) if err != nil { fmt.Fprintln(os.Stderr, "Error spawning liquidsoap", err) os.Exit(1) } go func(log <-chan liquidsoap.Output) { for { msg := <-log if msg.Msg != "" && msg.Level < 3 { fmt.Println("msg", msg) } } }(output) go func() { tick := time.Tick(3 * time.Second) for { <-tick t, err := liquidsoap.NewTelnet("localhost", 1234) if err != nil { fmt.Println("telnet connection errored", err) continue } t.Conn.SetDeadline(time.Now().Add(3 * time.Second)) outs, err := t.Outputs() if err != nil { fmt.Println("telnet cmd errored", err) continue } changed := false for name, enabled := range outs { if stream, exists := state.Streams[name]; exists { if stream.State != enabled { stream.State = enabled changed = true } state.Streams[name] = stream } else { state.Streams[name] = liquidsoap.Stream{State: enabled} changed = true } } t.Close() fmt.Println(changed, "state=", state) if changed { netUI.Update() } } }() for { select { case how := <-exit: // liquidsoap exits if !how.Success() { fmt.Fprintln(os.Stderr, "liquidsoap terminated,", how.Err) netUI.Close() os.Exit(1) } os.Exit(0) case <-killed: // we receive a SIGINT: ask liquidsoap to die is enough netUI.Close() close(killLs) fmt.Println("Closed by user interaction, waiting for liquidsoap to exit") // TODO: schedule a more aggressive SIGKILL if liquidsoap doesn't // exit soon } } }