Move artwork handling to its own package
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package artwork
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/dhowden/tag"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/core/ffmpeg"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/resources"
|
||||
)
|
||||
|
||||
type sourceFunc func() (io.ReadCloser, string, error)
|
||||
|
||||
func (f sourceFunc) String() string {
|
||||
name := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
|
||||
name = strings.TrimPrefix(name, "github.com/navidrome/navidrome/core.")
|
||||
name = strings.TrimPrefix(name, "(*artwork).")
|
||||
name = strings.TrimSuffix(name, ".func1")
|
||||
return name
|
||||
}
|
||||
|
||||
func (a *artwork) fromAlbum(ctx context.Context, id model.ArtworkID) sourceFunc {
|
||||
return func() (io.ReadCloser, string, error) {
|
||||
r, path, err := a.get(ctx, id, 0)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return r, path, nil
|
||||
}
|
||||
}
|
||||
|
||||
func fromExternalFile(ctx context.Context, files string, pattern string) sourceFunc {
|
||||
return func() (io.ReadCloser, string, error) {
|
||||
for _, file := range filepath.SplitList(files) {
|
||||
_, name := filepath.Split(file)
|
||||
match, err := filepath.Match(pattern, strings.ToLower(name))
|
||||
if err != nil {
|
||||
log.Warn(ctx, "Error matching cover art file to pattern", "pattern", pattern, "file", file)
|
||||
continue
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
log.Warn(ctx, "Could not open cover art file", "file", file, err)
|
||||
continue
|
||||
}
|
||||
return f, file, err
|
||||
}
|
||||
return nil, "", fmt.Errorf("pattern '%s' not matched by files %v", pattern, files)
|
||||
}
|
||||
}
|
||||
|
||||
func fromTag(path string) sourceFunc {
|
||||
return func() (io.ReadCloser, string, error) {
|
||||
if path == "" {
|
||||
return nil, "", nil
|
||||
}
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
m, err := tag.ReadFrom(f)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
picture := m.Picture()
|
||||
if picture == nil {
|
||||
return nil, "", fmt.Errorf("no embedded image found in %s", path)
|
||||
}
|
||||
return io.NopCloser(bytes.NewReader(picture.Data)), path, nil
|
||||
}
|
||||
}
|
||||
|
||||
func fromFFmpegTag(ctx context.Context, ffmpeg ffmpeg.FFmpeg, path string) sourceFunc {
|
||||
return func() (io.ReadCloser, string, error) {
|
||||
if path == "" {
|
||||
return nil, "", nil
|
||||
}
|
||||
r, err := ffmpeg.ExtractImage(ctx, path)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer r.Close()
|
||||
buf := new(bytes.Buffer)
|
||||
_, err = io.Copy(buf, r)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return io.NopCloser(buf), path, nil
|
||||
}
|
||||
}
|
||||
|
||||
func fromPlaceholder() sourceFunc {
|
||||
return func() (io.ReadCloser, string, error) {
|
||||
r, _ := resources.FS().Open(consts.PlaceholderAlbumArt)
|
||||
return r, consts.PlaceholderAlbumArt, nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user