From ec085cf22ee41304531cab4dabc7dd4c1dc09e4f Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 24 Mar 2024 10:13:32 -0700 Subject: [PATCH] Fix #350: add option to shuffle artist's discography by albums of tracks --- ui/browsing/artistpage.go | 41 ++++++++++++++++++++++--------------- ui/controller/controller.go | 32 +++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/ui/browsing/artistpage.go b/ui/browsing/artistpage.go index b237e50..e942a7f 100644 --- a/ui/browsing/artistpage.go +++ b/ui/browsing/artistpage.go @@ -323,26 +323,36 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader { }) a.playRadioBtn = widget.NewButtonWithIcon("Play Artist Radio", myTheme.ShuffleIcon, a.artistPage.playArtistRadio) - // TODO: Uncomment when at least one media provider supports sharing artists. - // a.shareMenuItem = fyne.NewMenuItem("Share...", func() { + var pop *widget.PopUpMenu + a.menuBtn = widget.NewButtonWithIcon("", theme.MoreHorizontalIcon(), nil) + a.menuBtn.OnTapped = func() { + if pop == nil { + shuffleTracks := fyne.NewMenuItem("Shuffle tracks", func() { + go a.artistPage.contr.PlayArtistDiscography(a.artistID, true /*shuffle*/) + }) + shuffleTracks.Icon = myTheme.TracksIcon + shuffleAlbums := fyne.NewMenuItem("Shuffle albums", func() { + go a.artistPage.contr.ShuffleArtistAlbums(a.artistID) + }) + shuffleAlbums.Icon = myTheme.AlbumIcon + menu := fyne.NewMenu("", shuffleTracks, shuffleAlbums) + pop = widget.NewPopUpMenu(menu, fyne.CurrentApp().Driver().CanvasForObject(a)) + } + pos := fyne.CurrentApp().Driver().AbsolutePositionForObject(a.menuBtn) + pop.ShowAtPosition(fyne.NewPos(pos.X, pos.Y+a.menuBtn.Size().Height)) + } + + // TODO: Uncomment and merge into OnTapped above when at least one media provider supports sharing artists. + // shareMenuItem = fyne.NewMenuItem("Share...", func() { // a.artistPage.contr.ShowShareDialog(a.artistID) // }) // a.shareMenuItem.Icon = myTheme.ShareIcon - // var pop *widget.PopUpMenu - // a.menuBtn = widget.NewButtonWithIcon("", theme.MoreHorizontalIcon(), nil) - // a.menuBtn.OnTapped = func() { - // if pop == nil { - // menu := fyne.NewMenu("", a.shareMenuItem) - // pop = widget.NewPopUpMenu(menu, fyne.CurrentApp().Driver().CanvasForObject(a)) - // } - // pos := fyne.CurrentApp().Driver().AbsolutePositionForObject(a.menuBtn) - // pop.ShowAtPosition(fyne.NewPos(pos.X, pos.Y+a.menuBtn.Size().Height)) - // } + // // canShareArtists := false // if r, canShare := a.artistPage.mp.(mediaprovider.SupportsSharing); canShare { // canShareArtists = r.CanShareArtists() // } - // a.shareMenuItem.Disabled = !canShareArtists + // shareMenuItem.Disabled = !canShareArtists a.biographyDisp.Wrapping = fyne.TextWrapWord a.biographyDisp.Truncation = fyne.TextTruncateEllipsis @@ -433,10 +443,7 @@ func (a *ArtistPageHeader) toggleFavorited() { } func (a *ArtistPageHeader) createContainer() { - btnContainer := container.NewHBox(util.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn) - if a.menuBtn != nil { - btnContainer.Add(a.menuBtn) - } + btnContainer := container.NewHBox(util.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn, a.menuBtn) a.container = util.AddHeaderBackground( container.NewBorder(nil, nil, a.artistImage, nil, diff --git a/ui/controller/controller.go b/ui/controller/controller.go index f600144..cb14e23 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -7,6 +7,7 @@ import ( "image" "io" "log" + "math/rand" "net/url" "os" "path/filepath" @@ -231,8 +232,35 @@ func (m *Controller) GetArtistTracks(artistID string) []*mediaprovider.Track { return allTracks } -func (m *Controller) PlayArtistDiscography(artistID string, shuffle bool) { - m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), false, shuffle) +func (m *Controller) PlayArtistDiscography(artistID string, shuffleTracks bool) { + m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), false, shuffleTracks) + if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { + if shuffleTracks { + m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainTrack) + } else { + m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainAlbum) + } + } + 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, true /*append*/, false /*shuffle*/) + } + if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { m.App.PlaybackManager.SetReplayGainMode(player.ReplayGainAlbum) }