]> code.octet-stream.net Git - broadcaster/blob - radio/status.go
Allow web user to cancel transmission in progress
[broadcaster] / radio / status.go
1 package main
2
3 import (
4 "code.octet-stream.net/broadcaster/protocol"
5 "encoding/json"
6 "golang.org/x/net/websocket"
7 "time"
8 )
9
10 type BeginDelayStatus struct {
11 Playlist string
12 Seconds int
13 Filename string
14 }
15
16 type BeginWaitForChannelStatus struct {
17 Playlist string
18 Filename string
19 }
20
21 type BeginPlaybackStatus struct {
22 Playlist string
23 Filename string
24 }
25
26 type StatusCollector struct {
27 Websocket chan *websocket.Conn
28 PlaylistBeginIdle chan bool
29 PlaylistBeginDelay chan BeginDelayStatus
30 PlaylistBeginWaitForChannel chan BeginWaitForChannelStatus
31 PlaylistBeginPlayback chan BeginPlaybackStatus
32 PTT chan bool
33 COS chan bool
34 Config chan RadioConfig
35 FilesInSync chan bool
36 }
37
38 var statusCollector = NewStatusCollector()
39
40 func NewStatusCollector() StatusCollector {
41 sc := StatusCollector{
42 Websocket: make(chan *websocket.Conn),
43 PlaylistBeginIdle: make(chan bool),
44 PlaylistBeginDelay: make(chan BeginDelayStatus),
45 PlaylistBeginWaitForChannel: make(chan BeginWaitForChannelStatus),
46 PlaylistBeginPlayback: make(chan BeginPlaybackStatus),
47 PTT: make(chan bool),
48 COS: make(chan bool),
49 Config: make(chan RadioConfig),
50 FilesInSync: make(chan bool),
51 }
52 go runStatusCollector(sc)
53 return sc
54 }
55
56 func runStatusCollector(sc StatusCollector) {
57 config := <-sc.Config
58 var msg protocol.StatusMessage
59 var lastSent protocol.StatusMessage
60 msg.T = protocol.StatusType
61 msg.TimeZone = config.TimeZone
62 msg.Status = protocol.StatusIdle
63 var ws *websocket.Conn
64 // Go 1.23: no need to stop tickers when finished
65 var ticker = time.NewTicker(time.Second * time.Duration(30))
66
67 for {
68 select {
69 case newWebsocket := <-sc.Websocket:
70 ws = newWebsocket
71 case <-ticker.C:
72 // should always be ticking at 1 second for these
73 if msg.Status == protocol.StatusDelay {
74 if msg.DelaySecondsRemaining > 0 {
75 msg.DelaySecondsRemaining -= 1
76 }
77 }
78 if msg.Status == protocol.StatusChannelInUse {
79 msg.WaitingForChannelSeconds += 1
80 }
81 if msg.Status == protocol.StatusPlaying {
82 msg.PlaybackSecondsElapsed += 1
83 }
84 case <-sc.PlaylistBeginIdle:
85 msg.Status = protocol.StatusIdle
86 msg.DelaySecondsRemaining = 0
87 msg.WaitingForChannelSeconds = 0
88 msg.PlaybackSecondsElapsed = 0
89 msg.Playlist = ""
90 msg.Filename = ""
91 // Update things more slowly when nothing's playing
92 ticker = time.NewTicker(time.Second * time.Duration(30))
93 case delay := <-sc.PlaylistBeginDelay:
94 msg.Status = protocol.StatusDelay
95 msg.DelaySecondsRemaining = delay.Seconds
96 msg.WaitingForChannelSeconds = 0
97 msg.PlaybackSecondsElapsed = 0
98 msg.Playlist = delay.Playlist
99 msg.Filename = delay.Filename
100 // Align ticker with start of state change, make sure it's faster
101 ticker = time.NewTicker(time.Second * time.Duration(1))
102 case wait := <-sc.PlaylistBeginWaitForChannel:
103 msg.Status = protocol.StatusChannelInUse
104 msg.DelaySecondsRemaining = 0
105 msg.WaitingForChannelSeconds = 0
106 msg.PlaybackSecondsElapsed = 0
107 msg.Playlist = wait.Playlist
108 msg.Filename = wait.Filename
109 ticker = time.NewTicker(time.Second * time.Duration(1))
110 case playback := <-sc.PlaylistBeginPlayback:
111 msg.Status = protocol.StatusPlaying
112 msg.DelaySecondsRemaining = 0
113 msg.WaitingForChannelSeconds = 0
114 msg.PlaybackSecondsElapsed = 0
115 msg.Playlist = playback.Playlist
116 msg.Filename = playback.Filename
117 ticker = time.NewTicker(time.Second * time.Duration(1))
118 case ptt := <-sc.PTT:
119 msg.PTT = ptt
120 case cos := <-sc.COS:
121 msg.COS = cos
122 case inSync := <-sc.FilesInSync:
123 msg.FilesInSync = inSync
124 }
125 msg.LocalTime = time.Now().Format(protocol.LocalTimeFormat)
126 msg.COS = cos.COSValue()
127
128 if msg == lastSent {
129 continue
130 }
131 if ws != nil {
132 msgJson, _ := json.Marshal(msg)
133 if _, err := ws.Write(msgJson); err != nil {
134 // If websocket has failed, wait 'til we get a new one
135 ws = nil
136 }
137 lastSent = msg
138 }
139 }
140 }