From 163d195032c3cd7b101753f24dc7fa9b423298a9 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 20 Mar 2023 18:14:02 -0700 Subject: [PATCH] use coverArt ID instead of album ID to fetch images --- backend/albumiterator.go | 8 +++---- backend/app.go | 4 ++-- backend/imagemanager.go | 50 +++++++++++++++++++-------------------- backend/librarymanager.go | 2 +- ui/bottompanel.go | 2 +- ui/browsing/albumpage.go | 16 ++++--------- ui/widgets/albumgrid.go | 4 ++-- 7 files changed, 40 insertions(+), 46 deletions(-) diff --git a/backend/albumiterator.go b/backend/albumiterator.go index 8bb12c8..7a81d10 100644 --- a/backend/albumiterator.go +++ b/backend/albumiterator.go @@ -126,7 +126,7 @@ func (r *baseIter) Next() *subsonic.AlbumID3 { r.prefetchedPos = 1 if r.l.PreCacheCoverFn != nil { for _, album := range albums { - go r.l.PreCacheCoverFn(album.ID) + go r.l.PreCacheCoverFn(album.CoverArt) } } @@ -230,7 +230,7 @@ func (s *searchIter) addNewAlbums(al []*subsonic.AlbumID3) { } s.prefetched = append(s.prefetched, album) if s.l.PreCacheCoverFn != nil { - go s.l.PreCacheCoverFn(album.ID) + go s.l.PreCacheCoverFn(album.CoverArt) } s.albumIDset[album.ID] = true } @@ -284,7 +284,7 @@ func (r *randomIter) Next() *subsonic.AlbumID3 { if _, ok := r.albumIDSet[album.ID]; !ok { r.prefetched = append(r.prefetched, album) if r.l.PreCacheCoverFn != nil { - go r.l.PreCacheCoverFn(album.ID) + go r.l.PreCacheCoverFn(album.CoverArt) } r.albumIDSet[album.ID] = true } @@ -305,7 +305,7 @@ func (r *randomIter) Next() *subsonic.AlbumID3 { hitCount++ r.prefetched = append(r.prefetched, album) if r.l.PreCacheCoverFn != nil { - go r.l.PreCacheCoverFn(album.ID) + go r.l.PreCacheCoverFn(album.CoverArt) } r.albumIDSet[album.ID] = true } diff --git a/backend/app.go b/backend/app.go index ea69da9..3715e41 100644 --- a/backend/app.go +++ b/backend/app.go @@ -55,8 +55,8 @@ func StartupApp() (*App, error) { a.PlaybackManager = NewPlaybackManager(a.bgrndCtx, a.ServerManager, a.Player) a.LibraryManager = NewLibraryManager(a.ServerManager) a.ImageManager = NewImageManager(a.bgrndCtx, a.ServerManager, configdir.LocalCache(AppName)) - a.LibraryManager.PreCacheCoverFn = func(albumID string) { - _, _ = a.ImageManager.GetAlbumThumbnail(albumID) + a.LibraryManager.PreCacheCoverFn = func(coverID string) { + _, _ = a.ImageManager.GetAlbumThumbnail(coverID) } return a, nil diff --git a/backend/imagemanager.go b/backend/imagemanager.go index 45f79f4..6dce73f 100644 --- a/backend/imagemanager.go +++ b/backend/imagemanager.go @@ -45,39 +45,39 @@ func NewImageManager(ctx context.Context, s *ServerManager, baseCacheDir string) return i } -func (i *ImageManager) GetAlbumThumbnailFromCache(albumID string) (image.Image, bool) { - img, err := i.thumbnailCache.GetExtendTTL(albumID, i.thumbnailCache.DefaultTTL) +func (i *ImageManager) GetAlbumThumbnailFromCache(coverID string) (image.Image, bool) { + img, err := i.thumbnailCache.GetExtendTTL(coverID, i.thumbnailCache.DefaultTTL) if err == nil && img != nil { return img, true } return nil, false } -func (i *ImageManager) GetAlbumThumbnail(albumID string) (image.Image, error) { - if im, ok := i.GetAlbumThumbnailFromCache(albumID); ok { +func (i *ImageManager) GetAlbumThumbnail(coverID string) (image.Image, error) { + if im, ok := i.GetAlbumThumbnailFromCache(coverID); ok { return im, nil } - return i.fetchAndCacheCoverFromDiskOrServer(albumID, i.thumbnailCache.DefaultTTL) + return i.fetchAndCacheCoverFromDiskOrServer(coverID, i.thumbnailCache.DefaultTTL) } -func (i *ImageManager) GetAlbumThumbnailWithTTL(albumID string, ttl time.Duration) (image.Image, error) { +func (i *ImageManager) GetAlbumThumbnailWithTTL(coverID string, ttl time.Duration) (image.Image, error) { // in-memory cache - if img, err := i.thumbnailCache.GetWithNewTTL(albumID, ttl); err == nil { + if img, err := i.thumbnailCache.GetWithNewTTL(coverID, ttl); err == nil { return img, nil } - return i.fetchAndCacheCoverFromDiskOrServer(albumID, ttl) + return i.fetchAndCacheCoverFromDiskOrServer(coverID, ttl) } -func (i *ImageManager) GetFullSizeAlbumCover(albumID string) (image.Image, error) { - if i.cachedFullSizeCoverID == albumID { +func (i *ImageManager) GetFullSizeAlbumCover(coverID string) (image.Image, error) { + if i.cachedFullSizeCoverID == coverID { return i.cachedFullSizeCover, nil } - im, err := i.s.Server.GetCoverArt(albumID, nil) + im, err := i.s.Server.GetCoverArt(coverID, nil) if err != nil { return nil, err } i.cachedFullSizeCover = im - i.cachedFullSizeCoverID = albumID + i.cachedFullSizeCoverID = coverID return im, nil } @@ -126,43 +126,43 @@ func (i *ImageManager) fetchRemoteArtistImage(url string) (image.Image, error) { return nil, err } -func (i *ImageManager) fetchAndCacheCoverFromDiskOrServer(albumID string, ttl time.Duration) (image.Image, error) { +func (i *ImageManager) fetchAndCacheCoverFromDiskOrServer(coverID string, ttl time.Duration) (image.Image, error) { // on disc cache - path := i.filePathForCover(albumID) + path := i.filePathForCover(coverID) if i.ensureCoverCacheDir() != "" { if s, err := os.Stat(path); err == nil { - go i.checkRefreshLocalCover(s, albumID, ttl) + go i.checkRefreshLocalCover(s, coverID, ttl) if img, ok := i.loadLocalImage(path); ok { - i.thumbnailCache.SetWithTTL(albumID, img, ttl) + i.thumbnailCache.SetWithTTL(coverID, img, ttl) return img, nil } } } - return i.fetchAndCacheCoverFromServer(albumID, ttl) + return i.fetchAndCacheCoverFromServer(coverID, ttl) } -func (i *ImageManager) fetchAndCacheCoverFromServer(albumID string, ttl time.Duration) (image.Image, error) { - img, err := i.s.Server.GetCoverArt(albumID, map[string]string{"size": "300"}) +func (i *ImageManager) fetchAndCacheCoverFromServer(coverID string, ttl time.Duration) (image.Image, error) { + img, err := i.s.Server.GetCoverArt(coverID, map[string]string{"size": "300"}) if err != nil { return nil, err } if i.ensureCoverCacheDir() != "" { - path := i.filePathForCover(albumID) + path := i.filePathForCover(coverID) _ = i.writeJpeg(img, path) } - i.thumbnailCache.SetWithTTL(albumID, img, ttl) + i.thumbnailCache.SetWithTTL(coverID, img, ttl) return img, nil } -func (i *ImageManager) checkRefreshLocalCover(stat os.FileInfo, albumID string, ttl time.Duration) { +func (i *ImageManager) checkRefreshLocalCover(stat os.FileInfo, coverID string, ttl time.Duration) { if time.Since(stat.ModTime()) > CachedImageValidTime { - i.fetchAndCacheCoverFromServer(albumID, ttl) + i.fetchAndCacheCoverFromServer(coverID, ttl) } } -func (i *ImageManager) filePathForCover(albumID string) string { - return filepath.Join(i.ensureCoverCacheDir(), fmt.Sprintf("%s.jpg", albumID)) +func (i *ImageManager) filePathForCover(coverID string) string { + return filepath.Join(i.ensureCoverCacheDir(), fmt.Sprintf("%s.jpg", coverID)) } func (i *ImageManager) filePathForArtistImage(id string) string { diff --git a/backend/librarymanager.go b/backend/librarymanager.go index 8ad7801..f33bae4 100644 --- a/backend/librarymanager.go +++ b/backend/librarymanager.go @@ -9,7 +9,7 @@ type AlbumIterator interface { } type LibraryManager struct { - PreCacheCoverFn func(string) + PreCacheCoverFn func(coverID string) s *ServerManager } diff --git a/ui/bottompanel.go b/ui/bottompanel.go index f1bde78..4c78f16 100644 --- a/ui/bottompanel.go +++ b/ui/bottompanel.go @@ -95,7 +95,7 @@ func (bp *BottomPanel) onSongChange(song *subsonic.Child, _ *subsonic.Child) { // be in cache for the next song if it's from the same album, or // if the user navigates to the album page for the track imgTTLSec := song.Duration + 30 - im, _ = bp.ImageManager.GetAlbumThumbnailWithTTL(song.AlbumID, time.Duration(imgTTLSec)*time.Second) + im, _ = bp.ImageManager.GetAlbumThumbnailWithTTL(song.CoverArt, time.Duration(imgTTLSec)*time.Second) } bp.NowPlaying.Update(song.Title, song.Artist, song.Album, im) } diff --git a/ui/browsing/albumpage.go b/ui/browsing/albumpage.go index 96cf0ac..a4eaf03 100644 --- a/ui/browsing/albumpage.go +++ b/ui/browsing/albumpage.go @@ -129,6 +129,7 @@ type AlbumPageHeader struct { widget.BaseWidget albumID string + coverID string artistID string genre string @@ -151,11 +152,7 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader { a.cover = widgets.NewTappableImage(func() { go a.showPopUpCover() }) a.cover.FillMode = canvas.ImageFillContain a.cover.SetMinSize(fyne.NewSize(225, 225)) - // due to cache warming we can probably immediately set the cover - // and not have to set it asynchronously in the Update function - if im, ok := page.im.GetAlbumThumbnailFromCache(page.albumID); ok { - a.cover.Image.Image = im - } + a.titleLabel = widget.NewRichTextWithText("") a.titleLabel.Wrapping = fyne.TextTruncate a.titleLabel.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{ @@ -201,6 +198,7 @@ func (a *AlbumPageHeader) CreateRenderer() fyne.WidgetRenderer { func (a *AlbumPageHeader) Update(album *subsonic.AlbumID3, im *backend.ImageManager) { a.albumID = album.ID + a.coverID = album.CoverArt a.artistID = album.ArtistID a.titleLabel.Segments[0].(*widget.TextSegment).Text = album.Name a.artistLabel.SetText(album.Artist) @@ -210,12 +208,8 @@ func (a *AlbumPageHeader) Update(album *subsonic.AlbumID3, im *backend.ImageMana a.toggleFavButton.IsFavorited = !album.Starred.IsZero() a.Refresh() - // cover image was already loaded from cache in consructor - if a.albumID == album.ID && a.cover.Image.Image != nil { - return - } go func() { - if cover, err := im.GetAlbumThumbnail(album.ID); err == nil { + if cover, err := im.GetAlbumThumbnail(album.CoverArt); err == nil { a.cover.Image.Image = cover a.cover.Refresh() } else { @@ -233,7 +227,7 @@ func (a *AlbumPageHeader) toggleFavorited() { } func (a *AlbumPageHeader) showPopUpCover() { - cover, err := a.page.im.GetFullSizeAlbumCover(a.albumID) + cover, err := a.page.im.GetFullSizeAlbumCover(a.coverID) if err != nil { log.Printf("error getting full size album cover: %s", err.Error()) return diff --git a/ui/widgets/albumgrid.go b/ui/widgets/albumgrid.go index 64a9ba4..92af97c 100644 --- a/ui/widgets/albumgrid.go +++ b/ui/widgets/albumgrid.go @@ -154,7 +154,7 @@ func (ag *AlbumGrid) doUpdateAlbumCard(albumIdx int, ac *AlbumCard) { ac.ImgLoadCancel() ac.ImgLoadCancel = nil } - if img, ok := ag.imageFetcher.GetAlbumThumbnailFromCache(album.ID); ok { + if img, ok := ag.imageFetcher.GetAlbumThumbnailFromCache(album.CoverArt); ok { ac.Cover.SetImage(img) } else { ac.Cover.SetImageResource(res.ResAlbumplaceholderPng) @@ -162,7 +162,7 @@ func (ag *AlbumGrid) doUpdateAlbumCard(albumIdx int, ac *AlbumCard) { ctx, cancel := context.WithCancel(context.Background()) ac.ImgLoadCancel = cancel go func(ctx context.Context) { - i, err := ag.imageFetcher.GetAlbumThumbnail(album.ID) + i, err := ag.imageFetcher.GetAlbumThumbnail(album.CoverArt) select { case <-ctx.Done(): return