main.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "net"
  6. "os"
  7. "os/signal"
  8. "time"
  9. "git.lattuga.net/boyska/direttoforo"
  10. "git.lattuga.net/boyska/direttoforo/liquidsoap"
  11. "git.lattuga.net/boyska/direttoforo/uiserver"
  12. )
  13. func main() {
  14. liqfile := flag.String("liq", "foo.liq", "Path to liquidsoap script to run")
  15. bindpath := flag.String("bindpath", "/var/lib/direttoforo/ui.sock", "UNIX domain socket path for UIs")
  16. flag.Parse()
  17. state := direttoforo.NewState()
  18. netUIsock, err := net.Listen("unix", *bindpath)
  19. if err != nil {
  20. fmt.Fprintln(os.Stderr, "error binding UI socket!")
  21. fmt.Fprintln(os.Stderr, err)
  22. os.Exit(1)
  23. return
  24. }
  25. netUI := uiserver.NewNetUI(&state)
  26. go func() {
  27. err := netUI.Run(netUIsock)
  28. if err != nil {
  29. fmt.Fprintln(os.Stderr, "NetUI error", err)
  30. }
  31. }()
  32. killLs := make(chan struct{}) // when it is closed, liquidsoap will die
  33. killed := make(chan os.Signal, 1)
  34. signal.Notify(killed, os.Interrupt) // ctrl-c
  35. output, exit, err := liquidsoap.RunLiquidsoap(*liqfile, killLs)
  36. if err != nil {
  37. fmt.Fprintln(os.Stderr, "Error spawning liquidsoap", err)
  38. os.Exit(1)
  39. }
  40. go func(log <-chan liquidsoap.Output) {
  41. for {
  42. msg := <-log
  43. if msg.Msg != "" && msg.Level < 3 {
  44. fmt.Println("msg", msg)
  45. }
  46. }
  47. }(output)
  48. go func() {
  49. tick := time.Tick(3 * time.Second)
  50. for {
  51. <-tick
  52. t, err := liquidsoap.NewTelnet("localhost", 1234)
  53. if err != nil {
  54. fmt.Println("telnet connection errored", err)
  55. continue
  56. }
  57. t.Conn.SetDeadline(time.Now().Add(3 * time.Second))
  58. outs, err := t.Outputs()
  59. if err != nil {
  60. if err.Error() != "EOF" {
  61. fmt.Println("telnet cmd errored", err)
  62. }
  63. continue
  64. }
  65. changed := false
  66. for name, newstream := range outs {
  67. if stream, exists := state.Streams[name]; exists {
  68. if newstream != stream {
  69. state.Streams[name] = newstream
  70. changed = true
  71. }
  72. } else {
  73. state.Streams[name] = newstream
  74. changed = true
  75. }
  76. }
  77. t.Close()
  78. if changed {
  79. fmt.Println("state=", state)
  80. netUI.Update()
  81. }
  82. }
  83. }()
  84. for {
  85. select {
  86. case how := <-exit: // liquidsoap exits
  87. if !how.Success() {
  88. fmt.Fprintln(os.Stderr, "liquidsoap terminated,", how.Err)
  89. netUI.Close()
  90. os.Exit(1)
  91. }
  92. os.Exit(0)
  93. case <-killed: // we receive a SIGINT: ask liquidsoap to die is enough
  94. netUI.Close()
  95. close(killLs)
  96. fmt.Println("Closed by user interaction, waiting for liquidsoap to exit")
  97. // TODO: schedule a more aggressive SIGKILL if liquidsoap doesn't
  98. // exit soon
  99. }
  100. }
  101. }