]> code.octet-stream.net Git - broadcaster/blobdiff - internal/protocol/protocol.go
Add licence, etc.
[broadcaster] / internal / protocol / protocol.go
diff --git a/internal/protocol/protocol.go b/internal/protocol/protocol.go
new file mode 100644 (file)
index 0000000..e23da3a
--- /dev/null
@@ -0,0 +1,167 @@
+package protocol
+
+import (
+       "encoding/json"
+       "errors"
+       "fmt"
+)
+
+const (
+       StartTimeFormat = "2006-01-02T15:04"
+       LocalTimeFormat = "Mon _2 Jan 2006 15:04:05"
+
+       // Radio to server
+
+       AuthenticateType = "authenticate"
+       StatusType       = "status"
+
+       // Server to radio
+
+       FilesType     = "files"
+       PlaylistsType = "playlists"
+       StopType      = "stop"
+
+       // Status values
+
+       StatusIdle         = "idle"
+       StatusDelay        = "delay"
+       StatusChannelInUse = "channel_in_use"
+       StatusPlaying      = "playing"
+)
+
+// Base message type to determine what type of payload is expected.
+type Message struct {
+       T string
+}
+
+// Initial message from Radio to authenticate itself with a token string.
+type AuthenticateMessage struct {
+       T     string
+       Token string
+}
+
+// Server updates the radio with the list of files that currently exist.
+// This will be provided on connect and when there are any changes.
+// The radio is expected to obtain all these files and cache them locally.
+type FilesMessage struct {
+       T     string
+       Files []FileSpec
+}
+
+type PlaylistsMessage struct {
+       T         string
+       Playlists []PlaylistSpec
+}
+
+// Any playlist currently being played should be stopped and PTT disengaged.
+type StopMessage struct {
+       T string
+}
+
+type StatusMessage struct {
+       T string
+
+       // Status w.r.t. playing a playlist
+       Status string
+
+       // File being played or about to be played - empty string in idle status
+       Filename string
+
+       // Name of playlist being played - empty string in idle status
+       Playlist string
+
+       // Seconds until playback begins - never mind latency
+       DelaySecondsRemaining int
+
+       // Number of seconds file has been actually playing
+       PlaybackSecondsElapsed int
+
+       // Number of seconds waiting for channel to clear
+       WaitingForChannelSeconds int
+
+       PTT         bool
+       COS         bool
+       FilesInSync bool
+
+       // Timestamp of the current time on this radio, using LocalTimeFormat
+       LocalTime string
+
+       // Time zone in use, e.g. "Australia/Hobart"
+       TimeZone string
+}
+
+// Description of an individual file available in the broadcasting system.
+type FileSpec struct {
+       // Filename, e.g. "broadcast.wav"
+       Name string
+       // SHA-256 hash of the file's contents
+       Hash string
+}
+
+type PlaylistSpec struct {
+       Id        int
+       Name      string
+       StartTime string
+       Entries   []EntrySpec
+}
+
+type EntrySpec struct {
+       Filename     string
+       DelaySeconds int
+       IsRelative   bool
+}
+
+func ParseMessage(data []byte) (string, interface{}, error) {
+       var t Message
+       err := json.Unmarshal(data, &t)
+       if err != nil {
+               return "", nil, err
+       }
+
+       if t.T == AuthenticateType {
+               var auth AuthenticateMessage
+               err = json.Unmarshal(data, &auth)
+               if err != nil {
+                       return "", nil, err
+               }
+               return t.T, auth, nil
+       }
+
+       if t.T == FilesType {
+               var files FilesMessage
+               err = json.Unmarshal(data, &files)
+               if err != nil {
+                       return "", nil, err
+               }
+               return t.T, files, nil
+       }
+
+       if t.T == PlaylistsType {
+               var playlists PlaylistsMessage
+               err = json.Unmarshal(data, &playlists)
+               if err != nil {
+                       return "", nil, err
+               }
+               return t.T, playlists, nil
+       }
+
+       if t.T == StatusType {
+               var status StatusMessage
+               err = json.Unmarshal(data, &status)
+               if err != nil {
+                       return "", nil, err
+               }
+               return t.T, status, nil
+       }
+
+       if t.T == StopType {
+               var stop StopMessage
+               err = json.Unmarshal(data, &stop)
+               if err != nil {
+                       return "", nil, err
+               }
+               return t.T, stop, nil
+       }
+
+       return "", nil, errors.New(fmt.Sprintf("unknown message type %v", t.T))
+}