package main import ( "context" "encoding/json" "log" "sync" "time" "github.com/gorilla/websocket" "github.com/grafov/bcast" "github.com/kataras/go-events" ) type Websocket struct { sync.Mutex clients *bcast.Group } var ws *Websocket func init() { log.Println("ws.go loading..") ws = new(Websocket) ws.clients = bcast.NewGroup() go ws.clients.Broadcast(0) log.Println("ws.go done.") } type WSmsg struct { Event string Payload json.RawMessage } type Event struct { Event string `json:"event"` Payload any `json:"payload,omitempty"` } func (ws *Websocket) SendEvent(e Event) { ws.Lock() ws.clients.Send(e) ws.Unlock() } func (ws *Websocket) join(c *websocket.Conn) error { memb := ws.clients.Join() defer memb.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { ticker := time.NewTicker(30 * time.Second) for { select { case <-ctx.Done(): return case <-ticker.C: c.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(10*time.Second)) case msg := <-memb.Read: c.SetWriteDeadline(time.Now().Add(10 * time.Second)) c.WriteJSON(msg) } } }() c.SetPongHandler(func(d string) error { return nil }) msg, err := app.songInfoEvent("song_info") if err != nil { return err } vol := Event{"volume", map[string]float64{ "playlist": pl_volume.Volume, "ambiance": amb_volume.Volume, }} c.SetWriteDeadline(time.Now().Add(10 * time.Second)) c.WriteJSON(msg) c.WriteJSON(vol) if app.ambiance.Len() > 0 { msg := Event{"ambiance_play", map[string]string{ "id": app.curamb.Id, }} c.WriteJSON(msg) } else { msg := Event{"ambiance_stop", nil} c.WriteJSON(msg) } for { var msg WSmsg err := c.ReadJSON(&msg) if err != nil { return err } app.events.Emit(events.EventName(msg.Event), msg.Payload, memb) } }