Uses cached original image when requesting a resized image
This commit is contained in:
+29
-20
@@ -44,6 +44,7 @@ type artwork struct {
|
|||||||
|
|
||||||
type imageInfo struct {
|
type imageInfo struct {
|
||||||
c *artwork
|
c *artwork
|
||||||
|
id string
|
||||||
path string
|
path string
|
||||||
size int
|
size int
|
||||||
lastUpdate time.Time
|
lastUpdate time.Time
|
||||||
@@ -53,20 +54,21 @@ func (ci *imageInfo) String() string {
|
|||||||
return fmt.Sprintf("%s.%d.%s.%d", ci.path, ci.size, ci.lastUpdate.Format(time.RFC3339Nano), conf.Server.CoverJpegQuality)
|
return fmt.Sprintf("%s.%d.%s.%d", ci.path, ci.size, ci.lastUpdate.Format(time.RFC3339Nano), conf.Server.CoverJpegQuality)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *artwork) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
func (a *artwork) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
||||||
path, lastUpdate, err := c.getImagePath(ctx, id)
|
path, lastUpdate, err := a.getImagePath(ctx, id)
|
||||||
if err != nil && err != model.ErrNotFound {
|
if err != nil && err != model.ErrNotFound {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := &imageInfo{
|
info := &imageInfo{
|
||||||
c: c,
|
c: a,
|
||||||
|
id: id,
|
||||||
path: path,
|
path: path,
|
||||||
size: size,
|
size: size,
|
||||||
lastUpdate: lastUpdate,
|
lastUpdate: lastUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := c.cache.Get(ctx, info)
|
r, err := a.cache.Get(ctx, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(ctx, "Error accessing image cache", "path", path, "size", size, err)
|
log.Error(ctx, "Error accessing image cache", "path", path, "size", size, err)
|
||||||
return err
|
return err
|
||||||
@@ -77,13 +79,13 @@ func (c *artwork) Get(ctx context.Context, id string, size int, out io.Writer) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *artwork) getImagePath(ctx context.Context, id string) (path string, lastUpdated time.Time, err error) {
|
func (a *artwork) getImagePath(ctx context.Context, id string) (path string, lastUpdated time.Time, err error) {
|
||||||
// If id is an album cover ID
|
// If id is an album cover ID
|
||||||
if strings.HasPrefix(id, "al-") {
|
if strings.HasPrefix(id, "al-") {
|
||||||
log.Trace(ctx, "Looking for album art", "id", id)
|
log.Trace(ctx, "Looking for album art", "id", id)
|
||||||
id = strings.TrimPrefix(id, "al-")
|
id = strings.TrimPrefix(id, "al-")
|
||||||
var al *model.Album
|
var al *model.Album
|
||||||
al, err = c.ds.Album(ctx).Get(id)
|
al, err = a.ds.Album(ctx).Get(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -97,11 +99,11 @@ func (c *artwork) getImagePath(ctx context.Context, id string) (path string, las
|
|||||||
|
|
||||||
// Check if id is a mediaFile cover id
|
// Check if id is a mediaFile cover id
|
||||||
var mf *model.MediaFile
|
var mf *model.MediaFile
|
||||||
mf, err = c.ds.MediaFile(ctx).Get(id)
|
mf, err = a.ds.MediaFile(ctx).Get(id)
|
||||||
|
|
||||||
// If it is not, may be an albumId
|
// If it is not, may be an albumId
|
||||||
if err == model.ErrNotFound {
|
if err == model.ErrNotFound {
|
||||||
return c.getImagePath(ctx, "al-"+id)
|
return a.getImagePath(ctx, "al-"+id)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -114,10 +116,10 @@ func (c *artwork) getImagePath(ctx context.Context, id string) (path string, las
|
|||||||
|
|
||||||
// if the mediaFile does not have a coverArt, fallback to the album cover
|
// if the mediaFile does not have a coverArt, fallback to the album cover
|
||||||
log.Trace(ctx, "Media file does not contain art. Falling back to album art", "id", id, "albumId", "al-"+mf.AlbumID)
|
log.Trace(ctx, "Media file does not contain art. Falling back to album art", "id", id, "albumId", "al-"+mf.AlbumID)
|
||||||
return c.getImagePath(ctx, "al-"+mf.AlbumID)
|
return a.getImagePath(ctx, "al-"+mf.AlbumID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *artwork) getArtwork(ctx context.Context, path string, size int) (reader io.Reader, err error) {
|
func (a *artwork) getArtwork(ctx context.Context, id string, path string, size int) (reader io.Reader, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(ctx, "Error extracting image", "path", path, "size", size, err)
|
log.Warn(ctx, "Error extracting image", "path", path, "size", size, err)
|
||||||
@@ -130,16 +132,23 @@ func (c *artwork) getArtwork(ctx context.Context, path string, size int) (reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
if utils.IsAudioFile(path) {
|
|
||||||
data, err = readFromTag(path)
|
|
||||||
} else {
|
|
||||||
data, err = readFromFile(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if size == 0 {
|
||||||
return
|
// If requested original size, just read from the file
|
||||||
} else if size > 0 {
|
if utils.IsAudioFile(path) {
|
||||||
data, err = resizeImage(bytes.NewReader(data), size)
|
data, err = readFromTag(path)
|
||||||
|
} else {
|
||||||
|
data, err = readFromFile(path)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If requested a resized image, get the original (possibly from cache) and resize it
|
||||||
|
a2 := NewArtwork(a.ds, a.cache)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = a2.Get(ctx, id, 0, buf)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err = resizeImage(buf, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm the image is valid. Costly, but necessary
|
// Confirm the image is valid. Costly, but necessary
|
||||||
@@ -200,7 +209,7 @@ func NewImageCache() ArtworkCache {
|
|||||||
return cache.NewFileCache("Image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems,
|
return cache.NewFileCache("Image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems,
|
||||||
func(ctx context.Context, arg fmt.Stringer) (io.Reader, error) {
|
func(ctx context.Context, arg fmt.Stringer) (io.Reader, error) {
|
||||||
info := arg.(*imageInfo)
|
info := arg.(*imageInfo)
|
||||||
reader, err := info.c.getArtwork(ctx, info.path, info.size)
|
reader, err := info.c.getArtwork(ctx, info.id, info.path, info.size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(ctx, "Error loading artwork art", "path", info.path, "size", info.size, err)
|
log.Error(ctx, "Error loading artwork art", "path", info.path, "size", info.size, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user