From 7793fd8fdb6fa579992980173062979445763681 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 24 Jun 2024 18:49:30 -0700 Subject: [PATCH] Refactor: move some playback-related functions to backend package --- .../helpers/{similar.go => other.go} | 19 +++++- .../jellyfin/jellyfinmediaprovider.go | 4 ++ backend/mediaprovider/mediaprovider.go | 2 + .../subsonic/subsonicmediaprovider.go | 4 ++ backend/playbackmanager.go | 42 +++++++++++++ ui/browsing/artistpage.go | 6 +- ui/controller/controller.go | 60 ++----------------- 7 files changed, 79 insertions(+), 58 deletions(-) rename backend/mediaprovider/helpers/{similar.go => other.go} (51%) diff --git a/backend/mediaprovider/helpers/similar.go b/backend/mediaprovider/helpers/other.go similarity index 51% rename from backend/mediaprovider/helpers/similar.go rename to backend/mediaprovider/helpers/other.go index f87871ee..7739da8c 100644 --- a/backend/mediaprovider/helpers/similar.go +++ b/backend/mediaprovider/helpers/other.go @@ -1,6 +1,8 @@ package helpers import ( + "fmt" + "github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/sharedutil" ) @@ -8,7 +10,6 @@ import ( func GetSimilarSongsFallback(mp mediaprovider.MediaProvider, track *mediaprovider.Track, count int) []*mediaprovider.Track { var tracks []*mediaprovider.Track if len(track.ArtistIDs) > 0 { - tracks, _ = mp.GetSimilarTracks(track.ArtistIDs[0], count) } if len(tracks) == 0 { tracks, _ = mp.GetRandomTracks(track.Genre, count) @@ -19,3 +20,19 @@ func GetSimilarSongsFallback(mp mediaprovider.MediaProvider, track *mediaprovide return t.ID != track.ID }) } + +func GetArtistTracks(mp mediaprovider.MediaProvider, artistID string) ([]*mediaprovider.Track, error) { + artist, err := mp.GetArtist(artistID) + if err != nil { + return nil, fmt.Errorf("error getting artist tracks: %v", err.Error()) + } + var allTracks []*mediaprovider.Track + for _, album := range artist.Albums { + album, err := mp.GetAlbum(album.ID) + if err != nil { + return nil, fmt.Errorf("error loading album tracks: %v", err.Error()) + } + allTracks = append(allTracks, album.Tracks...) + } + return allTracks, nil +} diff --git a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go index 8ad33edd..8f2742b3 100644 --- a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go +++ b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go @@ -145,6 +145,10 @@ func (j *jellyfinMediaProvider) GetArtist(artistID string) (*mediaprovider.Artis return artist, nil } +func (j *jellyfinMediaProvider) GetArtistTracks(artistID string) ([]*mediaprovider.Track, error) { + return helpers.GetArtistTracks(j, artistID) +} + func (j *jellyfinMediaProvider) GetArtistInfo(artistID string) (*mediaprovider.ArtistInfo, error) { ar, err := j.client.GetArtist(artistID) if err != nil { diff --git a/backend/mediaprovider/mediaprovider.go b/backend/mediaprovider/mediaprovider.go index c3d97d77..96070f15 100644 --- a/backend/mediaprovider/mediaprovider.go +++ b/backend/mediaprovider/mediaprovider.go @@ -181,6 +181,8 @@ type MediaProvider interface { GetArtist(artistID string) (*ArtistWithAlbums, error) + GetArtistTracks(artistID string) ([]*Track, error) + GetArtistInfo(artistID string) (*ArtistInfo, error) GetPlaylist(playlistID string) (*PlaylistWithTracks, error) diff --git a/backend/mediaprovider/subsonic/subsonicmediaprovider.go b/backend/mediaprovider/subsonic/subsonicmediaprovider.go index 28fff34e..7f17cae9 100644 --- a/backend/mediaprovider/subsonic/subsonicmediaprovider.go +++ b/backend/mediaprovider/subsonic/subsonicmediaprovider.go @@ -121,6 +121,10 @@ func (s *subsonicMediaProvider) GetArtist(artistID string) (*mediaprovider.Artis }, nil } +func (s *subsonicMediaProvider) GetArtistTracks(artistID string) ([]*mediaprovider.Track, error) { + return helpers.GetArtistTracks(s, artistID) +} + func (s *subsonicMediaProvider) GetArtistInfo(artistID string) (*mediaprovider.ArtistInfo, error) { info, err := s.client.GetArtistInfo2(artistID, map[string]string{}) if err != nil { diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 94f8a3b4..3542a657 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -4,6 +4,7 @@ import ( "context" "errors" "log" + "math/rand" "github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/backend/player" @@ -168,6 +169,47 @@ func (p *PlaybackManager) PlayTrack(trackID string) error { return p.PlayFromBeginning() } +func (p *PlaybackManager) ShuffleArtistAlbums(artistID string) { + artist, err := p.engine.sm.Server.GetArtist(artistID) + if err != nil { + log.Printf(err.Error()) + return + } + if len(artist.Albums) == 0 { + return + } + + rand.Shuffle(len(artist.Albums), func(i, j int) { + artist.Albums[i], artist.Albums[j] = artist.Albums[j], artist.Albums[i] + }) + p.StopAndClearPlayQueue() + for _, al := range artist.Albums { + p.LoadAlbum(al.ID, Append, false) + } + + if p.engine.replayGainCfg.Mode == ReplayGainAuto { + p.SetReplayGainMode(player.ReplayGainAlbum) + } + p.PlayFromBeginning() +} + +func (p *PlaybackManager) PlayArtistDiscography(artistID string, shuffleTracks bool) { + tr, err := p.engine.sm.Server.GetArtistTracks(artistID) + if err != nil { + log.Printf(err.Error()) + return + } + p.LoadTracks(tr, Replace, shuffleTracks) + if p.engine.replayGainCfg.Mode == ReplayGainAuto { + if shuffleTracks { + p.SetReplayGainMode(player.ReplayGainTrack) + } else { + p.SetReplayGainMode(player.ReplayGainAlbum) + } + } + p.PlayFromBeginning() +} + func (p *PlaybackManager) PlayFromBeginning() error { return p.engine.PlayTrackAt(0) } diff --git a/ui/browsing/artistpage.go b/ui/browsing/artistpage.go index 634e304f..51adb9f5 100644 --- a/ui/browsing/artistpage.go +++ b/ui/browsing/artistpage.go @@ -319,7 +319,7 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader { } a.favoriteBtn = widgets.NewFavoriteButton(func() { go a.toggleFavorited() }) a.playBtn = widget.NewButtonWithIcon("Play Discography", theme.MediaPlayIcon(), func() { - go a.artistPage.contr.PlayArtistDiscography(a.artistID, false /*shuffle*/) + go a.artistPage.pm.PlayArtistDiscography(a.artistID, false /*shuffle*/) }) a.playRadioBtn = widget.NewButtonWithIcon("Play Artist Radio", myTheme.ShuffleIcon, func() { // must not pass playArtistRadio func directly to NewButton @@ -332,11 +332,11 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader { a.menuBtn.OnTapped = func() { if pop == nil { shuffleTracks := fyne.NewMenuItem("Shuffle tracks", func() { - go a.artistPage.contr.PlayArtistDiscography(a.artistID, true /*shuffle*/) + go a.artistPage.pm.PlayArtistDiscography(a.artistID, true /*shuffle*/) }) shuffleTracks.Icon = myTheme.TracksIcon shuffleAlbums := fyne.NewMenuItem("Shuffle albums", func() { - go a.artistPage.contr.ShuffleArtistAlbums(a.artistID) + go a.artistPage.pm.ShuffleArtistAlbums(a.artistID) }) shuffleAlbums.Icon = myTheme.AlbumIcon menu := fyne.NewMenu("", shuffleTracks, shuffleAlbums) diff --git a/ui/controller/controller.go b/ui/controller/controller.go index d62869e6..cdfbbd7b 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -7,7 +7,6 @@ import ( "image" "io" "log" - "math/rand" "net/url" "os" "path/filepath" @@ -210,7 +209,7 @@ func (m *Controller) ConnectArtistGridActions(grid *widgets.GridView) { grid.OnPlayNext = func(artistID string) { go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.InsertNext, false) } - grid.OnPlay = func(artistID string, shuffle bool) { go m.PlayArtistDiscography(artistID, shuffle) } + grid.OnPlay = func(artistID string, shuffle bool) { go m.App.PlaybackManager.PlayArtistDiscography(artistID, shuffle) } grid.OnAddToQueue = func(artistID string) { go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.Append, false) } @@ -235,62 +234,15 @@ func (m *Controller) ConnectArtistGridActions(grid *widgets.GridView) { } func (m *Controller) GetArtistTracks(artistID string) []*mediaprovider.Track { - server := m.App.ServerManager.Server - if server == nil { - log.Println("error playing artist discography: logged out") - return nil - } - - artist, err := server.GetArtist(artistID) - if err != nil { - log.Printf("error getting artist discography: %v", err.Error()) - return nil - } - var allTracks []*mediaprovider.Track - for _, album := range artist.Albums { - album, err := server.GetAlbum(album.ID) - if err != nil { - log.Printf("error loading album tracks: %v", err.Error()) + if mp := m.App.ServerManager.Server; mp != nil { + if tr, err := mp.GetArtistTracks(artistID); err != nil { + log.Println(err.Error()) return nil - } - allTracks = append(allTracks, album.Tracks...) - } - return allTracks -} - -func (m *Controller) PlayArtistDiscography(artistID string, shuffleTracks bool) { - m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.Replace, shuffleTracks) - if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { - if shuffleTracks { - m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainTrack) } else { - m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainAlbum) + return tr } } - m.App.PlaybackManager.PlayFromBeginning() -} - -func (m *Controller) ShuffleArtistAlbums(artistID string) { - artist, err := m.App.ServerManager.Server.GetArtist(artistID) - if err != nil { - log.Printf("error getting artist discography: %v", err.Error()) - } - if len(artist.Albums) == 0 { - return - } - - rand.Shuffle(len(artist.Albums), func(i, j int) { - artist.Albums[i], artist.Albums[j] = artist.Albums[j], artist.Albums[i] - }) - m.App.PlaybackManager.StopAndClearPlayQueue() - for _, al := range artist.Albums { - m.App.PlaybackManager.LoadAlbum(al.ID, backend.Append, false) - } - - if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { - m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainAlbum) - } - m.App.PlaybackManager.PlayFromBeginning() + return nil } func (m *Controller) PromptForFirstServer() {