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 Duration time.Duration MaxListeners int StartAt time.Time } func (s *Song) ArtistTitle() string { return s.Artist + " - " + s.Title } func (s *Song) DurationString() string { if s.Duration.Hours() > 0 { return time.UnixMilli(s.Duration.Milliseconds()).Format("15:04:05") } return time.UnixMilli(s.Duration.Milliseconds()).Format("04:05") } func (s *Song) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Artist string `json:"artist"` Title string `json:"title"` DurationMill int64 `json:"duration_milliseconds"` Duration string `json:"duration"` MaxListeners int `json:"listeners"` StartAt string `json:"start_at"` }{ Artist: s.Artist, Title: s.Title, DurationMill: s.Duration.Milliseconds(), Duration: s.DurationString(), 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 sl.current.StartAt.Year() == 1 { sl.current = newSong return } 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() if sl.current.StartAt.Year() == 1 { return nil } 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 } func (sl *SongList) Len() int { return sl.listMaxLen }