X-Git-Url: https://code.octet-stream.net/broadcaster/blobdiff_plain/8320951221d45c5f5f3d387c5cb4b97d9fa2094c..33a19d553807d171f6ba9f4dafe30f43bc4bab5e:/broadcaster-radio/status.go diff --git a/broadcaster-radio/status.go b/broadcaster-radio/status.go new file mode 100644 index 0000000..7836815 --- /dev/null +++ b/broadcaster-radio/status.go @@ -0,0 +1,140 @@ +package main + +import ( + "code.octet-stream.net/broadcaster/internal/protocol" + "encoding/json" + "golang.org/x/net/websocket" + "time" +) + +type BeginDelayStatus struct { + Playlist string + Seconds int + Filename string +} + +type BeginWaitForChannelStatus struct { + Playlist string + Filename string +} + +type BeginPlaybackStatus struct { + Playlist string + Filename string +} + +type StatusCollector struct { + Websocket chan *websocket.Conn + PlaylistBeginIdle chan bool + PlaylistBeginDelay chan BeginDelayStatus + PlaylistBeginWaitForChannel chan BeginWaitForChannelStatus + PlaylistBeginPlayback chan BeginPlaybackStatus + PTT chan bool + COS chan bool + Config chan RadioConfig + FilesInSync chan bool +} + +var statusCollector = NewStatusCollector() + +func NewStatusCollector() StatusCollector { + sc := StatusCollector{ + Websocket: make(chan *websocket.Conn), + PlaylistBeginIdle: make(chan bool), + PlaylistBeginDelay: make(chan BeginDelayStatus), + PlaylistBeginWaitForChannel: make(chan BeginWaitForChannelStatus), + PlaylistBeginPlayback: make(chan BeginPlaybackStatus), + PTT: make(chan bool), + COS: make(chan bool), + Config: make(chan RadioConfig), + FilesInSync: make(chan bool), + } + go runStatusCollector(sc) + return sc +} + +func runStatusCollector(sc StatusCollector) { + config := <-sc.Config + var msg protocol.StatusMessage + var lastSent protocol.StatusMessage + msg.T = protocol.StatusType + msg.TimeZone = config.TimeZone + msg.Status = protocol.StatusIdle + var ws *websocket.Conn + // Go 1.23: no need to stop tickers when finished + var ticker = time.NewTicker(time.Second * time.Duration(30)) + + for { + select { + case newWebsocket := <-sc.Websocket: + ws = newWebsocket + case <-ticker.C: + // should always be ticking at 1 second for these + if msg.Status == protocol.StatusDelay { + if msg.DelaySecondsRemaining > 0 { + msg.DelaySecondsRemaining -= 1 + } + } + if msg.Status == protocol.StatusChannelInUse { + msg.WaitingForChannelSeconds += 1 + } + if msg.Status == protocol.StatusPlaying { + msg.PlaybackSecondsElapsed += 1 + } + case <-sc.PlaylistBeginIdle: + msg.Status = protocol.StatusIdle + msg.DelaySecondsRemaining = 0 + msg.WaitingForChannelSeconds = 0 + msg.PlaybackSecondsElapsed = 0 + msg.Playlist = "" + msg.Filename = "" + // Update things more slowly when nothing's playing + ticker = time.NewTicker(time.Second * time.Duration(30)) + case delay := <-sc.PlaylistBeginDelay: + msg.Status = protocol.StatusDelay + msg.DelaySecondsRemaining = delay.Seconds + msg.WaitingForChannelSeconds = 0 + msg.PlaybackSecondsElapsed = 0 + msg.Playlist = delay.Playlist + msg.Filename = delay.Filename + // Align ticker with start of state change, make sure it's faster + ticker = time.NewTicker(time.Second * time.Duration(1)) + case wait := <-sc.PlaylistBeginWaitForChannel: + msg.Status = protocol.StatusChannelInUse + msg.DelaySecondsRemaining = 0 + msg.WaitingForChannelSeconds = 0 + msg.PlaybackSecondsElapsed = 0 + msg.Playlist = wait.Playlist + msg.Filename = wait.Filename + ticker = time.NewTicker(time.Second * time.Duration(1)) + case playback := <-sc.PlaylistBeginPlayback: + msg.Status = protocol.StatusPlaying + msg.DelaySecondsRemaining = 0 + msg.WaitingForChannelSeconds = 0 + msg.PlaybackSecondsElapsed = 0 + msg.Playlist = playback.Playlist + msg.Filename = playback.Filename + ticker = time.NewTicker(time.Second * time.Duration(1)) + case ptt := <-sc.PTT: + msg.PTT = ptt + case cos := <-sc.COS: + msg.COS = cos + case inSync := <-sc.FilesInSync: + msg.FilesInSync = inSync + } + msg.LocalTime = time.Now().Format(protocol.LocalTimeFormat) + msg.COS = cos.COSValue() + + if msg == lastSent { + continue + } + if ws != nil { + msgJson, _ := json.Marshal(msg) + if _, err := ws.Write(msgJson); err != nil { + // If websocket has failed, wait 'til we get a new one + ws = nil + } + lastSent = msg + } + } +}