From 7d3e942e3f866ebddb0e253ea012d9e2b758aaac Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 12 Nov 2023 20:19:51 -0800 Subject: [PATCH] playlist updates --- .../jellyfin/jellyfinmediaprovider.go | 29 ++++++++++++++----- backend/mediaprovider/mediaprovider.go | 11 ++++++- .../subsonic/subsonicmediaprovider.go | 9 ++++-- go.mod | 2 +- go.sum | 4 +-- ui/browsing/playlistpage.go | 12 ++++++-- ui/controller/controller.go | 4 +-- 7 files changed, 53 insertions(+), 18 deletions(-) diff --git a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go index 4b08237..2baf322 100644 --- a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go +++ b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go @@ -46,8 +46,8 @@ func (j *jellyfinMediaProvider) SetPrefetchCoverCallback(cb func(coverArtID stri j.prefetchCoverCB = cb } -func (jellyfinMediaProvider) CreatePlaylist(name string, trackIDs []string) error { - return errors.New("unimplemented") +func (j *jellyfinMediaProvider) CreatePlaylist(name string, trackIDs []string) error { + return j.client.CreatePlaylist(name, trackIDs) } func (j *jellyfinMediaProvider) DeletePlaylist(id string) error { @@ -58,12 +58,25 @@ func (s *jellyfinMediaProvider) EditPlaylist(id, name, description string, publi return errors.New("unimplemented") } -func (s *jellyfinMediaProvider) EditPlaylistTracks(id string, trackIDsToAdd []string, trackIndexesToRemove []int) error { - return errors.New("unimplemented") +func (j *jellyfinMediaProvider) AddPlaylistTracks(id string, trackIDsToAdd []string) error { + return j.client.AddSongsToPlaylist(id, trackIDsToAdd) } -func (s *jellyfinMediaProvider) ReplacePlaylistTracks(playlistID string, trackIDs []string) error { - return errors.New("unimplemented") +func (j *jellyfinMediaProvider) RemovePlaylistTracks(playlistID string, removeInfo []mediaprovider.IDAndIndex) error { + ids := sharedutil.MapSlice(removeInfo, func(x mediaprovider.IDAndIndex) string { return x.ID }) + return j.client.RemoveSongsFromPlaylist(playlistID, ids) +} + +func (j *jellyfinMediaProvider) ReplacePlaylistTracks(playlistID string, trackIDs []string) error { + trs, err := j.client.GetPlaylistSongs(playlistID) + if err != nil { + return err + } + idsToDelete := sharedutil.MapSlice(trs, func(t *jellyfin.Song) string { return t.Id }) + if err = j.client.RemoveSongsFromPlaylist(playlistID, idsToDelete); err != nil { + return err + } + return j.client.AddSongsToPlaylist(playlistID, trackIDs) } func (j *jellyfinMediaProvider) GetAlbum(albumID string) (*mediaprovider.AlbumWithTracks, error) { @@ -420,9 +433,9 @@ func toPlaylist(p *jellyfin.Playlist) *mediaprovider.Playlist { func fillPlaylist(p *jellyfin.Playlist, pl *mediaprovider.Playlist) { pl.Name = p.Name pl.ID = p.ID - //CoverArtID = pl.CoverArt + pl.CoverArtID = p.ID pl.Description = p.Overview - //.Owner = pl.Owner + //Owner = pl.Owner //Public = pl.Public pl.TrackCount = p.SongCount pl.Duration = int(p.RunTimeTicks / 1_000_000) diff --git a/backend/mediaprovider/mediaprovider.go b/backend/mediaprovider/mediaprovider.go index 25a68e9..1d9e91c 100644 --- a/backend/mediaprovider/mediaprovider.go +++ b/backend/mediaprovider/mediaprovider.go @@ -66,6 +66,11 @@ type Server interface { MediaProvider() MediaProvider } +type IDAndIndex struct { + ID string + Index int +} + type MediaProvider interface { SetPrefetchCoverCallback(cb func(coverArtID string)) @@ -115,7 +120,11 @@ type MediaProvider interface { EditPlaylist(id, name, description string, public bool) error - EditPlaylistTracks(id string, trackIDsToAdd []string, trackIndexesToRemove []int) error + AddPlaylistTracks(id string, trackIDsToAdd []string) error + + // Some MediaProviders use ids and others indexes for removing tracks, + // so need to supply both. + RemovePlaylistTracks(id string, trackRemoveInfo []IDAndIndex) error ReplacePlaylistTracks(id string, trackIDs []string) error diff --git a/backend/mediaprovider/subsonic/subsonicmediaprovider.go b/backend/mediaprovider/subsonic/subsonicmediaprovider.go index b546e67..b98e9e2 100644 --- a/backend/mediaprovider/subsonic/subsonicmediaprovider.go +++ b/backend/mediaprovider/subsonic/subsonicmediaprovider.go @@ -51,8 +51,13 @@ func (s *subsonicMediaProvider) EditPlaylist(id, name, description string, publi }) } -func (s *subsonicMediaProvider) EditPlaylistTracks(id string, trackIDsToAdd []string, trackIndexesToRemove []int) error { - return s.client.UpdatePlaylistTracks(id, trackIDsToAdd, trackIndexesToRemove) +func (s *subsonicMediaProvider) AddPlaylistTracks(id string, trackIDsToAdd []string) error { + return s.client.UpdatePlaylistTracks(id, trackIDsToAdd, nil) +} + +func (s *subsonicMediaProvider) RemovePlaylistTracks(id string, removeInfo []mediaprovider.IDAndIndex) error { + idx := sharedutil.MapSlice(removeInfo, func(x mediaprovider.IDAndIndex) int { return x.Index }) + return s.client.UpdatePlaylistTracks(id, nil, idx) } func (s *subsonicMediaProvider) GetTrack(trackID string) (*mediaprovider.Track, error) { diff --git a/go.mod b/go.mod index 52688f5..1baadbe 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( fyne.io/fyne/v2 v2.4.1 github.com/20after4/configdir v0.1.1 github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 - github.com/dweymouth/go-jellyfin v0.0.0-20231113004204-96b092385986 + github.com/dweymouth/go-jellyfin v0.0.0-20231113023851-8cce8cd32c59 github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee github.com/dweymouth/go-subsonic v0.0.0-20231105161622-54b5aec28363 github.com/fsnotify/fsnotify v1.6.0 diff --git a/go.sum b/go.sum index 37255fd..c0f9139 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 h1:mGvOb3zxl4vCLv+ github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1/go.mod h1:ZNCLJfehvEf34B7BbLKjgpsL9lyW7q938w/GY1XgV4E= github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231110162149-a0e470497555 h1:8S+d0LuwdTUEipEzFeXp8rNwTQD47dBdDOg9+FI1+Vw= github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231110162149-a0e470497555/go.mod h1:AWM1iPM2YfliduZ4u/kQzP9E6ARIWm0gg+57GpYzWro= -github.com/dweymouth/go-jellyfin v0.0.0-20231113004204-96b092385986 h1:5yZgruDoqH2Z09ZTHJckF7qHCGW2JrgutwyWpsIdpWI= -github.com/dweymouth/go-jellyfin v0.0.0-20231113004204-96b092385986/go.mod h1:BMwS4vdjEYf1gmjPGSKCzWP/I6YlI6fkefJ9nsjBjaU= +github.com/dweymouth/go-jellyfin v0.0.0-20231113023851-8cce8cd32c59 h1:qpIwMxwEYlE+OEB99FVaaIxaZ7RO6VW3pvOU1WFL9f0= +github.com/dweymouth/go-jellyfin v0.0.0-20231113023851-8cce8cd32c59/go.mod h1:BMwS4vdjEYf1gmjPGSKCzWP/I6YlI6fkefJ9nsjBjaU= github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY= github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee/go.mod h1:Ov0ieN90M7i+0k3OxhA/g1dozGs+UcPHDsMKqPgRDk0= github.com/dweymouth/go-subsonic v0.0.0-20231105161622-54b5aec28363 h1:MIH7MAWWPPVRKEKxz+RJubn+ycyQPimHn1Zvoxs1KRI= diff --git a/ui/browsing/playlistpage.go b/ui/browsing/playlistpage.go index 6a74f48..912fe3c 100644 --- a/ui/browsing/playlistpage.go +++ b/ui/browsing/playlistpage.go @@ -212,14 +212,19 @@ func (a *PlaylistPage) doSetNewTrackOrder(op sharedutil.TrackReorderOp) { } func (a *PlaylistPage) onRemoveSelectedFromPlaylist() { - sel := sharedutil.ToSet(a.tracklist.SelectedTrackIDs()) + ids := a.tracklist.SelectedTrackIDs() + sel := sharedutil.ToSet(ids) idxs := make([]int, 0, len(sel)) for i, tr := range a.tracks { if _, ok := sel[tr.ID]; ok { idxs = append(idxs, i) } } - a.sm.Server.EditPlaylistTracks(a.playlistID, nil, idxs) + idIndex := make([]mediaprovider.IDAndIndex, 0, len(ids)) + for i := 0; i < len(ids); i++ { + idIndex = append(idIndex, mediaprovider.IDAndIndex{ID: ids[i], Index: idxs[i]}) + } + a.sm.Server.RemovePlaylistTracks(a.playlistID, idIndex) a.tracklist.UnselectAll() a.Reload() } @@ -285,6 +290,9 @@ func NewPlaylistPageHeader(page *PlaylistPage) *PlaylistPageHeader { sharedutil.TracksToIDs(a.page.tracks)) }), fyne.NewMenuItem("Download...", func() { + if a.playlistInfo == nil { + return + } a.page.contr.ShowDownloadDialog(a.page.tracks, a.playlistInfo.Name) })) pop = widget.NewPopUpMenu(menu, fyne.CurrentApp().Driver().CanvasForObject(a)) diff --git a/ui/controller/controller.go b/ui/controller/controller.go index 4c3ab4e..8752390 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -269,8 +269,8 @@ func (m *Controller) DoAddTracksToPlaylistWorkflow(trackIDs []string) { if playlistChoice < 0 { go m.App.ServerManager.Server.CreatePlaylist(newPlaylistName, trackIDs) } else { - go m.App.ServerManager.Server.EditPlaylistTracks( - pls[playlistChoice].ID, trackIDs, nil /*tracksToRemove*/) + go m.App.ServerManager.Server.AddPlaylistTracks( + pls[playlistChoice].ID, trackIDs) } } m.haveModal = true