fixed TODOs, first checkpoint saving queue on server

This commit is contained in:
Siiiiinth
2026-02-01 18:46:49 +01:00
parent e05542844a
commit 46c3fb15c4
5 changed files with 81 additions and 38 deletions
+45 -13
View File
@@ -28,11 +28,12 @@ import (
)
const (
configFile = "config.toml"
portableDir = "supersonic_portable"
savedQueueFile = "saved_queue.json"
themesDir = "themes"
audioCacheSubdir = "audio"
configFile = "config.toml"
portableDir = "supersonic_portable"
savedQueueFile = "saved_queue.json"
savedUnshuffledQueueFile = "saved_unshuffled_queue.json"
themesDir = "themes"
audioCacheSubdir = "audio"
)
var (
@@ -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 err != nil {
return err
}
if len(queue.Tracks) == 0 {
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
View File
@@ -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
+9 -2
View File
@@ -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)
}
+1 -2
View File
@@ -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()
+8
View File
@@ -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
}