2023-10-01 05:42:55 +04:00
|
|
|
package radio
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// Song stores artist and title of a song, a timestamp of when it started, its
|
|
|
|
// duration, and a maximum number of listeners.
|
2023-10-02 03:18:30 +04:00
|
|
|
type Song struct {
|
2023-10-01 05:42:55 +04:00
|
|
|
Artist string
|
|
|
|
Title string
|
2023-10-02 01:26:22 +04:00
|
|
|
Duration time.Duration
|
2023-10-01 05:42:55 +04:00
|
|
|
MaxListeners int
|
|
|
|
StartAt time.Time
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// ArtistTitle returns a concatination of an artist and a title with a hyphen
|
|
|
|
// between then.
|
2023-10-02 03:18:30 +04:00
|
|
|
func (s *Song) ArtistTitle() string {
|
2023-10-01 05:42:55 +04:00
|
|
|
return s.Artist + " - " + s.Title
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// DurationString returns song's duration as a string formatted as [H:]M:SS.
|
2023-10-02 03:52:26 +04:00
|
|
|
func (s *Song) DurationString() string {
|
2023-10-02 03:55:17 +04:00
|
|
|
if s.Duration.Hours() >= 1 {
|
2023-10-02 18:08:57 +04:00
|
|
|
return time.UnixMilli(s.Duration.Milliseconds()).Format("3:4:05")
|
2023-10-02 03:52:26 +04:00
|
|
|
}
|
2023-10-02 18:08:57 +04:00
|
|
|
return time.UnixMilli(s.Duration.Milliseconds()).Format("4:05")
|
2023-10-02 03:52:26 +04:00
|
|
|
}
|
|
|
|
|
2023-10-02 03:18:30 +04:00
|
|
|
func (s *Song) MarshalJSON() ([]byte, error) {
|
2023-10-01 05:42:55 +04:00
|
|
|
return json.Marshal(&struct {
|
|
|
|
Artist string `json:"artist"`
|
|
|
|
Title string `json:"title"`
|
2023-10-04 18:10:17 +04:00
|
|
|
DurationMill int64 `json:"duration_msec"`
|
2023-10-02 03:48:31 +04:00
|
|
|
Duration string `json:"duration"`
|
2023-10-01 05:42:55 +04:00
|
|
|
MaxListeners int `json:"listeners"`
|
|
|
|
StartAt string `json:"start_at"`
|
|
|
|
}{
|
|
|
|
Artist: s.Artist,
|
|
|
|
Title: s.Title,
|
2023-10-02 03:48:31 +04:00
|
|
|
DurationMill: s.Duration.Milliseconds(),
|
2023-10-02 03:52:26 +04:00
|
|
|
Duration: s.DurationString(),
|
2023-10-01 05:42:55 +04:00
|
|
|
MaxListeners: s.MaxListeners,
|
|
|
|
StartAt: s.StartAt.UTC().Format(time.RFC3339)})
|
|
|
|
}
|
|
|
|
|
|
|
|
type SongList struct {
|
2023-10-04 18:10:17 +04:00
|
|
|
sync.Mutex
|
|
|
|
current Song
|
|
|
|
lastSongs []Song
|
|
|
|
maxLen int
|
2023-10-01 05:42:55 +04:00
|
|
|
}
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// NewSongList returns a new SongList with a maximal length set with maxLen.
|
|
|
|
func NewSongList(maxLen int) *SongList {
|
|
|
|
return &SongList{maxLen: maxLen, lastSongs: make([]Song, 0, maxLen)}
|
2023-10-01 05:42:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add a new song that is currently playing and update a list.
|
2023-10-02 03:18:30 +04:00
|
|
|
func (sl *SongList) Add(newSong Song) {
|
2023-10-04 18:10:17 +04:00
|
|
|
sl.Lock()
|
|
|
|
defer sl.Unlock()
|
2023-10-01 06:37:47 +04:00
|
|
|
|
|
|
|
if sl.current.StartAt.Year() == 1 {
|
|
|
|
sl.current = newSong
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
if len(sl.lastSongs) == sl.maxLen {
|
2023-10-01 05:42:55 +04:00
|
|
|
sl.lastSongs = append(sl.lastSongs[1:], sl.current)
|
|
|
|
} else {
|
|
|
|
sl.lastSongs = append(sl.lastSongs, sl.current)
|
|
|
|
}
|
|
|
|
sl.current = newSong
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// Current returns a currently playing song.
|
2023-10-02 03:18:30 +04:00
|
|
|
func (sl *SongList) Current() *Song {
|
2023-10-04 18:10:17 +04:00
|
|
|
sl.Lock()
|
|
|
|
defer sl.Unlock()
|
2023-10-01 22:02:54 +04:00
|
|
|
if sl.current.StartAt.Year() == 1 {
|
|
|
|
return nil
|
|
|
|
}
|
2023-10-01 05:42:55 +04:00
|
|
|
return &sl.current
|
|
|
|
}
|
|
|
|
|
|
|
|
// List returns a list of lastly played songs.
|
2023-10-02 03:18:30 +04:00
|
|
|
func (sl *SongList) List() []Song {
|
2023-10-04 18:10:17 +04:00
|
|
|
sl.Lock()
|
|
|
|
defer sl.Unlock()
|
2023-10-01 05:42:55 +04:00
|
|
|
return sl.lastSongs
|
|
|
|
}
|
2023-10-02 03:18:30 +04:00
|
|
|
|
2023-10-04 18:10:17 +04:00
|
|
|
// MaxLen returns a maximal length of a list
|
|
|
|
func (sl *SongList) MaxLen() int {
|
|
|
|
return sl.maxLen
|
2023-10-02 03:18:30 +04:00
|
|
|
}
|