diff --git a/internal/radio/song.go b/internal/radio/song.go new file mode 100644 index 0000000..112a78d --- /dev/null +++ b/internal/radio/song.go @@ -0,0 +1,70 @@ +package radio + +import ( + "encoding/json" + "sync" + "time" +) + +// Song_ stores artist and title of a song, a timestamp of when it started, and +// a maximum number of listeners. +type Song_ struct { + Artist string + Title string + MaxListeners int + StartAt time.Time +} + +func (s *Song_) ArtistTitle() string { + return s.Artist + " - " + s.Title +} + +func (s *Song_) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + Artist string `json:"artist"` + Title string `json:"title"` + MaxListeners int `json:"listeners"` + StartAt string `json:"start_at"` + }{ + Artist: s.Artist, + Title: s.Title, + MaxListeners: s.MaxListeners, + StartAt: s.StartAt.UTC().Format(time.RFC3339)}) +} + +type SongList struct { + mut sync.Mutex + current Song_ + lastSongs []Song_ + listMaxLen int +} + +func NewSongList(length int) *SongList { + return &SongList{listMaxLen: length, lastSongs: make([]Song_, 0, length)} +} + +// Add a new song that is currently playing and update a list. +func (sl *SongList) Add(newSong Song_) { + sl.mut.Lock() + defer sl.mut.Unlock() + if len(sl.lastSongs) == sl.listMaxLen { + sl.lastSongs = append(sl.lastSongs[1:], sl.current) + } else { + sl.lastSongs = append(sl.lastSongs, sl.current) + } + sl.current = newSong +} + +// Current returns a current playing song. +func (sl *SongList) Current() *Song_ { + sl.mut.Lock() + defer sl.mut.Unlock() + return &sl.current +} + +// List returns a list of lastly played songs. +func (sl *SongList) List() []Song_ { + sl.mut.Lock() + defer sl.mut.Unlock() + return sl.lastSongs +}