fixed TODOs, first checkpoint saving queue on server
This commit is contained in:
+40
-8
@@ -31,6 +31,7 @@ const (
|
||||
configFile = "config.toml"
|
||||
portableDir = "supersonic_portable"
|
||||
savedQueueFile = "saved_queue.json"
|
||||
savedUnshuffledQueueFile = "saved_unshuffled_queue.json"
|
||||
themesDir = "themes"
|
||||
audioCacheSubdir = "audio"
|
||||
)
|
||||
@@ -549,30 +550,61 @@ func (a *App) SavePlayQueueIfEnabled() {
|
||||
queueServer = qs
|
||||
}
|
||||
}
|
||||
SavePlayQueue(a.ServerManager.ServerID.String(), a.PlaybackManager, path.Join(a.configDir, savedQueueFile), queueServer)
|
||||
SavePlayQueue(a.ServerManager.ServerID.String(), a.PlaybackManager.GetActivePlayQueue(), a.PlaybackManager, path.Join(a.configDir, savedQueueFile), queueServer)
|
||||
if a.Config.Playback.Shuffle {
|
||||
// if shuffle, also save the unshuffeled queue to enable unshuffling on restarting supersonic
|
||||
SavePlayQueue(a.ServerManager.ServerID.String(), a.PlaybackManager.GetPlayQueue(), a.PlaybackManager, path.Join(a.configDir, savedUnshuffledQueueFile), queueServer)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) LoadSavedPlayQueue() error {
|
||||
queueFilePath := path.Join(a.configDir, savedQueueFile)
|
||||
queue, err := LoadPlayQueue(queueFilePath, a.ServerManager, a.Config.Application.SaveQueueToServer)
|
||||
playQueue, err := LoadPlayQueue(queueFilePath, a.ServerManager, a.Config.Application.SaveQueueToServer)
|
||||
var unshuffledPlayQueue *SavedPlayQueue
|
||||
|
||||
if a.Config.Playback.Shuffle {
|
||||
unshuffledQueueFilePath := path.Join(a.configDir, savedUnshuffledQueueFile)
|
||||
unshuffledPlayQueue, err = LoadPlayQueue(unshuffledQueueFilePath, a.ServerManager, a.Config.Application.SaveQueueToServer) //unshuffledPlayQueue is only stored locally
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(queue.Tracks) == 0 {
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(playQueue.Tracks) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(a.PlaybackManager.GetPlayQueue()) > 0 {
|
||||
if len(a.PlaybackManager.GetActivePlayQueue()) > 0 {
|
||||
// don't restore play queue if the user has already queued new tracks
|
||||
return nil
|
||||
}
|
||||
|
||||
a.PlaybackManager.LoadTracks(queue.Tracks, Replace, false)
|
||||
if queue.TrackIndex >= 0 && queue.TrackIndex < len(queue.Tracks) {
|
||||
a.PlaybackManager.LoadTracks(playQueue.Tracks, Replace, false)
|
||||
if playQueue.TrackIndex >= 0 && playQueue.TrackIndex < len(playQueue.Tracks) {
|
||||
// TODO: This isn't ideal but doesn't seem to cause an audible play-for-a-split-second artifact
|
||||
a.PlaybackManager.PlayTrackAt(queue.TrackIndex)
|
||||
a.PlaybackManager.PlayTrackAt(playQueue.TrackIndex)
|
||||
a.PlaybackManager.Pause()
|
||||
time.Sleep(100 * time.Millisecond) // MPV seek fails if run quickly after
|
||||
a.PlaybackManager.SeekSeconds(queue.TimePos)
|
||||
a.PlaybackManager.SeekSeconds(playQueue.TimePos)
|
||||
}
|
||||
|
||||
if a.Config.Playback.Shuffle {
|
||||
// check if queue was changed server side
|
||||
// if playQueue.items same as unshuffledPlayQueue.items
|
||||
// set shuffle to false, only load normal playqueue
|
||||
if len(playQueue.Tracks) != len(unshuffledPlayQueue.Tracks) {
|
||||
// queue was changed server side, no need to compare elements
|
||||
a.PlaybackManager.SetShuffle(false)
|
||||
} else {
|
||||
//TODO_SHUFFLE: implement
|
||||
|
||||
//shuffled := sharedutil.CopyTrackSliceToMediaItemSlice(playQueue.Tracks)
|
||||
//unshuffled := sharedutil.CopyTrackSliceToMediaItemSlice(unshuffledPlayQueue.Tracks)
|
||||
|
||||
//a.PlaybackManager.engine.setPlayQueue(unshuffled)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+18
-21
@@ -250,6 +250,14 @@ func (p *playbackEngine) setShuffledPlayQueue(items []mediaprovider.MediaItem) {
|
||||
p.shuffledPlayQueue = items
|
||||
}
|
||||
|
||||
func (p *playbackEngine) setActivePlayQueue(items []mediaprovider.MediaItem) {
|
||||
if p.shuffle {
|
||||
p.setShuffledPlayQueue(items)
|
||||
} else {
|
||||
p.setPlayQueue(items)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *playbackEngine) getPlayQueueItemAt(idx int) mediaprovider.MediaItem {
|
||||
return p.getPlayQueue()[idx]
|
||||
}
|
||||
@@ -263,6 +271,10 @@ func (p *playbackEngine) GetPlayQueueDeepCopy() []mediaprovider.MediaItem {
|
||||
return deepCopyMediaItemSlice(p.getPlayQueue())
|
||||
}
|
||||
|
||||
func (p *playbackEngine) GetShuffledPlayQueueDeepCopy() []mediaprovider.MediaItem {
|
||||
return deepCopyMediaItemSlice(p.getPlayQueue())
|
||||
}
|
||||
|
||||
func (p *playbackEngine) GetActivePlayQueueDeepCopy() []mediaprovider.MediaItem {
|
||||
return deepCopyMediaItemSlice(p.getActivePlayQueue())
|
||||
}
|
||||
@@ -314,8 +326,7 @@ func (p *playbackEngine) GetLoopMode() LoopMode {
|
||||
return p.loopMode
|
||||
}
|
||||
|
||||
// TODO_SHUFFLE: rename?
|
||||
func (p *playbackEngine) GetNewNowPlayingIdx(items []mediaprovider.MediaItem) int {
|
||||
func (p *playbackEngine) GetNowPlayingIdxFrom(items []mediaprovider.MediaItem) int {
|
||||
newNowPlayingIdx := -1
|
||||
if p.nowPlayingIdx >= 0 {
|
||||
nowPlayingID := p.getPlayQueueItemAt(p.nowPlayingIdx).Metadata().ID
|
||||
@@ -340,10 +351,10 @@ func (p *playbackEngine) SetShuffle(shuffle bool) {
|
||||
rand.Shuffle(len(shuffledQueue), func(i, j int) {
|
||||
shuffledQueue[i], shuffledQueue[j] = shuffledQueue[j], shuffledQueue[i]
|
||||
})
|
||||
p.shuffledPlayQueue = sharedutil.ReorderItems(shuffledQueue, []int{p.GetNewNowPlayingIdx(shuffledQueue)}, 0)
|
||||
p.shuffledPlayQueue = sharedutil.ReorderItems(shuffledQueue, []int{p.GetNowPlayingIdxFrom(shuffledQueue)}, 0)
|
||||
newNowPlayingIdx = 0
|
||||
} else {
|
||||
newNowPlayingIdx = p.GetNewNowPlayingIdx(p.playQueue)
|
||||
newNowPlayingIdx = p.GetNowPlayingIdxFrom(p.playQueue)
|
||||
}
|
||||
|
||||
p.shuffle = shuffle
|
||||
@@ -460,7 +471,7 @@ func (p *playbackEngine) LoadItems(items []mediaprovider.MediaItem, insertQueueM
|
||||
// Load tracks into the play queue.
|
||||
// If replacing the current queue (!appendToQueue), playback will be stopped.
|
||||
func (p *playbackEngine) LoadTracks(tracks []*mediaprovider.Track, insertQueueMode InsertQueueMode, shuffle bool) error {
|
||||
newTracks := copyTrackSliceToMediaItemSlice(tracks)
|
||||
newTracks := sharedutil.CopyTrackSliceToMediaItemSlice(tracks)
|
||||
return p.doLoaditems(newTracks, insertQueueMode, shuffle)
|
||||
}
|
||||
|
||||
@@ -501,13 +512,7 @@ func (p *playbackEngine) LoadRadioStation(radio *mediaprovider.RadioStation, ins
|
||||
if insertMode == InsertNext {
|
||||
insertIdx = p.nowPlayingIdx + 1
|
||||
}
|
||||
new := make([]mediaprovider.MediaItem, p.getPlayQueueLength()+1)
|
||||
firstHalf := p.playQueue[:insertIdx]
|
||||
copy(new, firstHalf)
|
||||
new[len(firstHalf)] = radio
|
||||
copy(new[len(firstHalf)+1:], p.playQueue[insertIdx:]) //TODO_SHUFFLE: Test shuffle with radio stations
|
||||
p.setPlayQueue(new)
|
||||
|
||||
p.insertItemsIntoPlayQueueAt([]mediaprovider.MediaItem{radio}, insertIdx)
|
||||
p.invokeNoArgCallbacks(p.onQueueChange)
|
||||
}
|
||||
|
||||
@@ -584,7 +589,7 @@ func (p *playbackEngine) RemoveTracksFromQueue(idxs []int) {
|
||||
// remove tracks by ID from playQueue
|
||||
ids := p.GetTrackIdsFromIdx(idxs)
|
||||
newPlayQueue := make([]mediaprovider.MediaItem, 0, p.getPlayQueueLength()-len(idxs))
|
||||
for _, tr := range p.playQueue { //TODO_SHUFFLE: Rework this to use a func for getPlayQueue
|
||||
for _, tr := range p.getPlayQueue() {
|
||||
if slices.Contains(ids, tr.Metadata().ID) {
|
||||
//remove id from id list, handles having the same track present multiple times in playQueue
|
||||
idx := slices.Index(ids, tr.Metadata().ID)
|
||||
@@ -935,14 +940,6 @@ func deepCopyMediaItemSlice(tracks []mediaprovider.MediaItem) []mediaprovider.Me
|
||||
return newTracks
|
||||
}
|
||||
|
||||
func copyTrackSliceToMediaItemSlice(tracks []*mediaprovider.Track) []mediaprovider.MediaItem {
|
||||
newTracks := make([]mediaprovider.MediaItem, len(tracks))
|
||||
for i, tr := range tracks {
|
||||
newTracks[i] = tr.Copy()
|
||||
}
|
||||
return newTracks
|
||||
}
|
||||
|
||||
func (p *playbackEngine) invokeOnSongChangeCallbacks() {
|
||||
if p.callbacksDisabled {
|
||||
return
|
||||
|
||||
@@ -385,7 +385,7 @@ func (p *PlaybackManager) LoadPlaylist(playlistID string, insertQueueMode Insert
|
||||
// Load tracks into the play queue.
|
||||
// If replacing the current queue (!appendToQueue), playback will be stopped.
|
||||
func (p *PlaybackManager) LoadTracks(tracks []*mediaprovider.Track, insertQueueMode InsertQueueMode, shuffle bool) {
|
||||
items := copyTrackSliceToMediaItemSlice(tracks)
|
||||
items := sharedutil.CopyTrackSliceToMediaItemSlice(tracks)
|
||||
p.cmdQueue.LoadItems(items, insertQueueMode, shuffle)
|
||||
}
|
||||
|
||||
@@ -565,10 +565,18 @@ func (p *PlaybackManager) fetchAndPlayTracks(fetchFn func() ([]*mediaprovider.Tr
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PlaybackManager) GetActivePlayQueue() []mediaprovider.MediaItem {
|
||||
return p.engine.GetActivePlayQueueDeepCopy()
|
||||
}
|
||||
|
||||
func (p *PlaybackManager) GetPlayQueue() []mediaprovider.MediaItem {
|
||||
return p.engine.GetPlayQueueDeepCopy()
|
||||
}
|
||||
|
||||
func (p *PlaybackManager) GetShuffledPlayQueue() []mediaprovider.MediaItem {
|
||||
return p.engine.GetShuffledPlayQueueDeepCopy()
|
||||
}
|
||||
|
||||
// Any time the user changes the favorite status of a track elsewhere in the app,
|
||||
// this should be called to ensure the in-memory track model is updated.
|
||||
func (p *PlaybackManager) OnTrackFavoriteStatusChanged(id string, fav bool) {
|
||||
@@ -640,7 +648,6 @@ func (p *PlaybackManager) SetAutoplay(autoplay bool) {
|
||||
|
||||
func (p *PlaybackManager) SetShuffle(shuffle bool) {
|
||||
p.cfg.Shuffle = shuffle
|
||||
fmt.Println("Setting shuffle in config")
|
||||
p.engine.SetShuffle(shuffle)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ type serializedSavedPlayQueue struct {
|
||||
|
||||
// SavePlayQueue saves the current play queue and playback position to a JSON file.
|
||||
// If the provided CanSavePlayQueue server is non-nil, it will also save to the server.
|
||||
func SavePlayQueue(serverID string, pm *PlaybackManager, filepath string, server mediaprovider.CanSavePlayQueue) error {
|
||||
queue := pm.GetPlayQueue()
|
||||
func SavePlayQueue(serverID string, queue []mediaprovider.MediaItem, pm *PlaybackManager, filepath string, server mediaprovider.CanSavePlayQueue) error {
|
||||
stats := pm.PlaybackStatus()
|
||||
trackIdx := pm.NowPlayingIndex()
|
||||
|
||||
|
||||
@@ -186,3 +186,11 @@ func DownloadFileWithContext(ctx context.Context, url string, destPath string) (
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func CopyTrackSliceToMediaItemSlice(tracks []*mediaprovider.Track) []mediaprovider.MediaItem {
|
||||
newTracks := make([]mediaprovider.MediaItem, len(tracks))
|
||||
for i, tr := range tracks {
|
||||
newTracks[i] = tr.Copy()
|
||||
}
|
||||
return newTracks
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user