add GetFullSizeCoverArtAsync

This commit is contained in:
Drew Weymouth
2024-03-01 16:59:04 -08:00
parent 4023d9e76e
commit 9ed2d8502b
+46 -13
View File
@@ -136,20 +136,26 @@ func (i *ImageManager) GetFullSizeCoverArt(coverID string) (image.Image, error)
i.cachedFullSizeCoverAccessedAt = time.Now().UnixMilli() i.cachedFullSizeCoverAccessedAt = time.Now().UnixMilli()
return i.cachedFullSizeCover, nil return i.cachedFullSizeCover, nil
} }
if i.s.Server == nil { return i.getFullSizeCoverArtFromServer(context.Background(), coverID, nil)
return nil, errors.New("logged out") }
}
i.serverFetchSema <- struct{}{} // acquire // GetCoverThumbnailAsync asynchronously fetches the cover image for the given ID,
im, err := i.s.Server.GetCoverArt(coverID, 0) // and invokes the callback on completion. It returns a context.CancelFunc which can be used to
<-i.serverFetchSema // release // cancel the fetch. The callback will not be invoked if the fetch is cancelled before completion.
if err != nil { // The cancel func must be invoked to avoid resource leaks. Use GetCoverThumbnail if cancellation is not needed.
return nil, err func (i *ImageManager) GetFullSizeCoverArtAsync(coverID string, cb func(image.Image, error)) context.CancelFunc {
} ctx, cancel := context.WithCancel(context.Background())
i.cachedFullSizeCover = im go func() {
i.cachedFullSizeCoverID = coverID if i.cachedFullSizeCoverID == coverID {
i.cachedFullSizeCoverAccessedAt = time.Now().UnixMilli() i.cachedFullSizeCoverAccessedAt = time.Now().UnixMilli()
return im, nil if ctx.Err() == nil {
cb(i.cachedFullSizeCover, nil)
}
} else {
i.getFullSizeCoverArtFromServer(ctx, coverID, cb)
}
}()
return cancel
} }
// GetCoverArtURL returns the URL for the locally cached cover thumbnail, if it exists. // GetCoverArtURL returns the URL for the locally cached cover thumbnail, if it exists.
@@ -267,6 +273,33 @@ func (i *ImageManager) fetchAndCacheCoverFromServer(ctx context.Context, coverID
} }
} }
func (i *ImageManager) getFullSizeCoverArtFromServer(ctx context.Context, coverID string, cb func(image.Image, error)) (image.Image, error) {
if i.s.Server == nil {
err := errors.New("logged out")
if ctx.Err() == nil && cb != nil {
cb(nil, err)
}
return nil, err
}
select {
case <-ctx.Done():
return nil, context.Canceled
case i.serverFetchSema <- struct{}{}: // acquire
im, err := i.s.Server.GetCoverArt(coverID, 0)
<-i.serverFetchSema // release
if err == nil {
i.cachedFullSizeCover = im
i.cachedFullSizeCoverID = coverID
i.cachedFullSizeCoverAccessedAt = time.Now().UnixMilli()
}
if ctx.Err() == nil && cb != nil {
cb(im, err)
}
return im, err
}
}
func (i *ImageManager) checkRefreshLocalCover(stat os.FileInfo, coverID string, ttl time.Duration) { func (i *ImageManager) checkRefreshLocalCover(stat os.FileInfo, coverID string, ttl time.Duration) {
if time.Since(stat.ModTime()) > cachedImageValidTime { if time.Since(stat.ModTime()) > cachedImageValidTime {
i.fetchAndCacheCoverFromServer(context.Background(), coverID, ttl, nil) i.fetchAndCacheCoverFromServer(context.Background(), coverID, ttl, nil)