mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 13:07:36 +03:00
Rename 'Cover' to the more generic term 'Artwork'
This commit is contained in:
parent
cefdeee495
commit
2b59d4b87a
9 changed files with 81 additions and 81 deletions
|
@ -41,8 +41,8 @@ func CreateAppRouter() *app.Router {
|
|||
func CreateSubsonicAPIRouter() (*subsonic.Router, error) {
|
||||
dataStore := persistence.New()
|
||||
browser := engine.NewBrowser(dataStore)
|
||||
coverCache := core.NewImageCache()
|
||||
cover := core.NewCover(dataStore, coverCache)
|
||||
artworkCache := core.NewImageCache()
|
||||
artwork := core.NewArtwork(dataStore, artworkCache)
|
||||
nowPlayingRepository := engine.NewNowPlayingRepository()
|
||||
listGenerator := engine.NewListGenerator(dataStore, nowPlayingRepository)
|
||||
users := engine.NewUsers(dataStore)
|
||||
|
@ -54,7 +54,7 @@ func CreateSubsonicAPIRouter() (*subsonic.Router, error) {
|
|||
transcodingCache := core.NewTranscodingCache()
|
||||
mediaStreamer := core.NewMediaStreamer(dataStore, transcoderTranscoder, transcodingCache)
|
||||
players := engine.NewPlayers(dataStore)
|
||||
router := subsonic.New(browser, cover, listGenerator, users, playlists, ratings, scrobbler, search, mediaStreamer, players)
|
||||
router := subsonic.New(browser, artwork, listGenerator, users, playlists, ratings, scrobbler, search, mediaStreamer, players)
|
||||
return router, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -24,39 +24,39 @@ import (
|
|||
"github.com/disintegration/imaging"
|
||||
)
|
||||
|
||||
type Cover interface {
|
||||
type Artwork interface {
|
||||
Get(ctx context.Context, id string, size int, out io.Writer) error
|
||||
}
|
||||
|
||||
type CoverCache FileCache
|
||||
type ArtworkCache FileCache
|
||||
|
||||
func NewCover(ds model.DataStore, cache CoverCache) Cover {
|
||||
return &cover{ds: ds, cache: cache}
|
||||
func NewArtwork(ds model.DataStore, cache ArtworkCache) Artwork {
|
||||
return &artwork{ds: ds, cache: cache}
|
||||
}
|
||||
|
||||
type cover struct {
|
||||
type artwork struct {
|
||||
ds model.DataStore
|
||||
cache FileCache
|
||||
}
|
||||
|
||||
type coverInfo struct {
|
||||
c *cover
|
||||
type imageInfo struct {
|
||||
c *artwork
|
||||
path string
|
||||
size int
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
func (ci *coverInfo) String() string {
|
||||
func (ci *imageInfo) String() string {
|
||||
return fmt.Sprintf("%s.%d.%s.%d", ci.path, ci.size, ci.lastUpdate.Format(time.RFC3339Nano), conf.Server.CoverJpegQuality)
|
||||
}
|
||||
|
||||
func (c *cover) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
||||
path, lastUpdate, err := c.getCoverPath(ctx, id)
|
||||
func (c *artwork) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
||||
path, lastUpdate, err := c.getImagePath(ctx, id)
|
||||
if err != nil && err != model.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
|
||||
info := &coverInfo{
|
||||
info := &imageInfo{
|
||||
c: c,
|
||||
path: path,
|
||||
size: size,
|
||||
|
@ -73,7 +73,7 @@ func (c *cover) Get(ctx context.Context, id string, size int, out io.Writer) err
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *cover) getCoverPath(ctx context.Context, id string) (path string, lastUpdated time.Time, err error) {
|
||||
func (c *artwork) getImagePath(ctx context.Context, id string) (path string, lastUpdated time.Time, err error) {
|
||||
// If id is an album cover ID
|
||||
if strings.HasPrefix(id, "al-") {
|
||||
log.Trace(ctx, "Looking for album art", "id", id)
|
||||
|
@ -102,10 +102,10 @@ func (c *cover) getCoverPath(ctx context.Context, id string) (path string, lastU
|
|||
|
||||
// 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)
|
||||
return c.getCoverPath(ctx, "al-"+mf.AlbumID)
|
||||
return c.getImagePath(ctx, "al-"+mf.AlbumID)
|
||||
}
|
||||
|
||||
func (c *cover) getCover(ctx context.Context, path string, size int) (reader io.Reader, err error) {
|
||||
func (c *artwork) getArtwork(ctx context.Context, path string, size int) (reader io.Reader, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.Warn(ctx, "Error extracting image", "path", path, "size", size, err)
|
||||
|
@ -114,7 +114,7 @@ func (c *cover) getCover(ctx context.Context, path string, size int) (reader io.
|
|||
}()
|
||||
|
||||
if path == "" {
|
||||
return nil, errors.New("empty path given for cover")
|
||||
return nil, errors.New("empty path given for artwork")
|
||||
}
|
||||
|
||||
var data []byte
|
||||
|
@ -184,13 +184,13 @@ func readFromFile(path string) ([]byte, error) {
|
|||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func NewImageCache() CoverCache {
|
||||
func NewImageCache() ArtworkCache {
|
||||
return NewFileCache("Image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems,
|
||||
func(ctx context.Context, arg fmt.Stringer) (io.Reader, error) {
|
||||
info := arg.(*coverInfo)
|
||||
reader, err := info.c.getCover(ctx, info.path, info.size)
|
||||
info := arg.(*imageInfo)
|
||||
reader, err := info.c.getArtwork(ctx, info.path, info.size)
|
||||
if err != nil {
|
||||
log.Error(ctx, "Error loading cover 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 reader, nil
|
|
@ -15,8 +15,8 @@ import (
|
|||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Cover", func() {
|
||||
var cover Cover
|
||||
var _ = Describe("Artwork", func() {
|
||||
var artwork Artwork
|
||||
var ds model.DataStore
|
||||
ctx := log.NewContext(context.TODO())
|
||||
|
||||
|
@ -32,57 +32,57 @@ var _ = Describe("Cover", func() {
|
|||
conf.Server.ImageCacheSize = "100MB"
|
||||
cache := NewImageCache()
|
||||
Eventually(func() bool { return cache.Ready() }).Should(BeTrue())
|
||||
cover = NewCover(ds, cache)
|
||||
artwork = NewArtwork(ds, cache)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
os.RemoveAll(conf.Server.DataFolder)
|
||||
})
|
||||
|
||||
It("retrieves the external cover art for an album", func() {
|
||||
It("retrieves the external artwork art for an album", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "al-444", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "al-444", 0, buf)).To(BeNil())
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(format).To(Equal("jpeg"))
|
||||
})
|
||||
|
||||
It("retrieves the embedded cover art for an album", func() {
|
||||
It("retrieves the embedded artwork art for an album", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "al-222", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "al-222", 0, buf)).To(BeNil())
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(format).To(Equal("jpeg"))
|
||||
})
|
||||
|
||||
It("returns the default cover if album does not have cover", func() {
|
||||
It("returns the default artwork if album does not have artwork", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "al-333", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "al-333", 0, buf)).To(BeNil())
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(format).To(Equal("png"))
|
||||
})
|
||||
|
||||
It("returns the default cover if album is not found", func() {
|
||||
It("returns the default artwork if album is not found", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "al-0101", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "al-0101", 0, buf)).To(BeNil())
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(format).To(Equal("png"))
|
||||
})
|
||||
|
||||
It("retrieves the original cover art from a media_file", func() {
|
||||
It("retrieves the original artwork art from a media_file", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "123", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "123", 0, buf)).To(BeNil())
|
||||
|
||||
img, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
|
@ -91,20 +91,20 @@ var _ = Describe("Cover", func() {
|
|||
Expect(img.Bounds().Size().Y).To(Equal(600))
|
||||
})
|
||||
|
||||
It("retrieves the album cover art if media_file does not have one", func() {
|
||||
It("retrieves the album artwork art if media_file does not have one", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "456", 0, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "456", 0, buf)).To(BeNil())
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(format).To(Equal("jpeg"))
|
||||
})
|
||||
|
||||
It("resized cover art as requested", func() {
|
||||
It("resized artwork art as requested", func() {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "123", 200, buf)).To(BeNil())
|
||||
Expect(artwork.Get(ctx, "123", 200, buf)).To(BeNil())
|
||||
|
||||
img, format, err := image.Decode(bytes.NewReader(buf.Bytes()))
|
||||
Expect(err).To(BeNil())
|
||||
|
@ -118,14 +118,14 @@ var _ = Describe("Cover", func() {
|
|||
ds.Album(ctx).(*persistence.MockAlbum).SetError(true)
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "al-222", 0, buf)).To(MatchError("Error!"))
|
||||
Expect(artwork.Get(ctx, "al-222", 0, buf)).To(MatchError("Error!"))
|
||||
})
|
||||
|
||||
It("returns err if gets error from media_file table", func() {
|
||||
ds.MediaFile(ctx).(*persistence.MockMediaFile).SetError(true)
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
Expect(cover.Get(ctx, "123", 0, buf)).To(MatchError("Error!"))
|
||||
Expect(artwork.Get(ctx, "123", 0, buf)).To(MatchError("Error!"))
|
||||
})
|
||||
})
|
||||
})
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
var Set = wire.NewSet(
|
||||
NewCover,
|
||||
NewArtwork,
|
||||
NewMediaStreamer,
|
||||
NewTranscodingCache,
|
||||
NewImageCache,
|
||||
|
|
|
@ -23,7 +23,7 @@ type Handler = func(http.ResponseWriter, *http.Request) (*responses.Subsonic, er
|
|||
|
||||
type Router struct {
|
||||
Browser engine.Browser
|
||||
Cover core.Cover
|
||||
Artwork core.Artwork
|
||||
ListGenerator engine.ListGenerator
|
||||
Playlists engine.Playlists
|
||||
Ratings engine.Ratings
|
||||
|
@ -36,10 +36,10 @@ type Router struct {
|
|||
mux http.Handler
|
||||
}
|
||||
|
||||
func New(browser engine.Browser, cover core.Cover, listGenerator engine.ListGenerator, users engine.Users,
|
||||
func New(browser engine.Browser, artwork core.Artwork, listGenerator engine.ListGenerator, users engine.Users,
|
||||
playlists engine.Playlists, ratings engine.Ratings, scrobbler engine.Scrobbler, search engine.Search,
|
||||
streamer core.MediaStreamer, players engine.Players) *Router {
|
||||
r := &Router{Browser: browser, Cover: cover, ListGenerator: listGenerator, Playlists: playlists,
|
||||
r := &Router{Browser: browser, Artwork: artwork, ListGenerator: listGenerator, Playlists: playlists,
|
||||
Ratings: ratings, Scrobbler: scrobbler, Search: search, Users: users, Streamer: streamer, Players: players}
|
||||
r.mux = r.routes()
|
||||
return r
|
||||
|
|
|
@ -14,11 +14,11 @@ import (
|
|||
)
|
||||
|
||||
type MediaRetrievalController struct {
|
||||
cover core.Cover
|
||||
artwork core.Artwork
|
||||
}
|
||||
|
||||
func NewMediaRetrievalController(cover core.Cover) *MediaRetrievalController {
|
||||
return &MediaRetrievalController{cover: cover}
|
||||
func NewMediaRetrievalController(artwork core.Artwork) *MediaRetrievalController {
|
||||
return &MediaRetrievalController{artwork: artwork}
|
||||
}
|
||||
|
||||
func (c *MediaRetrievalController) GetAvatar(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
|
||||
|
@ -41,12 +41,12 @@ func (c *MediaRetrievalController) GetCoverArt(w http.ResponseWriter, r *http.Re
|
|||
size := utils.ParamInt(r, "size", 0)
|
||||
|
||||
w.Header().Set("cache-control", "public, max-age=315360000")
|
||||
err = c.cover.Get(r.Context(), id, size, w)
|
||||
err = c.artwork.Get(r.Context(), id, size, w)
|
||||
|
||||
switch {
|
||||
case err == model.ErrNotFound:
|
||||
log.Error(r, "Couldn't find coverArt", "id", id, err)
|
||||
return nil, NewError(responses.ErrorDataNotFound, "Cover not found")
|
||||
return nil, NewError(responses.ErrorDataNotFound, "Artwork not found")
|
||||
case err != nil:
|
||||
log.Error(r, "Error retrieving coverArt", "id", id, err)
|
||||
return nil, NewError(responses.ErrorGeneric, "Internal Error")
|
||||
|
|
|
@ -11,44 +11,27 @@ import (
|
|||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type fakeCover struct {
|
||||
data string
|
||||
err error
|
||||
recvId string
|
||||
recvSize int
|
||||
}
|
||||
|
||||
func (c *fakeCover) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
||||
if c.err != nil {
|
||||
return c.err
|
||||
}
|
||||
c.recvId = id
|
||||
c.recvSize = size
|
||||
_, err := out.Write([]byte(c.data))
|
||||
return err
|
||||
}
|
||||
|
||||
var _ = Describe("MediaRetrievalController", func() {
|
||||
var controller *MediaRetrievalController
|
||||
var cover *fakeCover
|
||||
var artwork *fakeArtwork
|
||||
var w *httptest.ResponseRecorder
|
||||
|
||||
BeforeEach(func() {
|
||||
cover = &fakeCover{}
|
||||
controller = NewMediaRetrievalController(cover)
|
||||
artwork = &fakeArtwork{}
|
||||
controller = NewMediaRetrievalController(artwork)
|
||||
w = httptest.NewRecorder()
|
||||
})
|
||||
|
||||
Describe("GetCoverArt", func() {
|
||||
It("should return data for that id", func() {
|
||||
cover.data = "image data"
|
||||
artwork.data = "image data"
|
||||
r := newGetRequest("id=34", "size=128")
|
||||
_, err := controller.GetCoverArt(w, r)
|
||||
|
||||
Expect(err).To(BeNil())
|
||||
Expect(cover.recvId).To(Equal("34"))
|
||||
Expect(cover.recvSize).To(Equal(128))
|
||||
Expect(w.Body.String()).To(Equal(cover.data))
|
||||
Expect(artwork.recvId).To(Equal("34"))
|
||||
Expect(artwork.recvSize).To(Equal(128))
|
||||
Expect(w.Body.String()).To(Equal(artwork.data))
|
||||
})
|
||||
|
||||
It("should fail if missing id parameter", func() {
|
||||
|
@ -59,15 +42,15 @@ var _ = Describe("MediaRetrievalController", func() {
|
|||
})
|
||||
|
||||
It("should fail when the file is not found", func() {
|
||||
cover.err = model.ErrNotFound
|
||||
artwork.err = model.ErrNotFound
|
||||
r := newGetRequest("id=34", "size=128")
|
||||
_, err := controller.GetCoverArt(w, r)
|
||||
|
||||
Expect(err).To(MatchError("Cover not found"))
|
||||
Expect(err).To(MatchError("Artwork not found"))
|
||||
})
|
||||
|
||||
It("should fail when there is an unknown error", func() {
|
||||
cover.err = errors.New("weird error")
|
||||
artwork.err = errors.New("weird error")
|
||||
r := newGetRequest("id=34", "size=128")
|
||||
_, err := controller.GetCoverArt(w, r)
|
||||
|
||||
|
@ -75,3 +58,20 @@ var _ = Describe("MediaRetrievalController", func() {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
type fakeArtwork struct {
|
||||
data string
|
||||
err error
|
||||
recvId string
|
||||
recvSize int
|
||||
}
|
||||
|
||||
func (c *fakeArtwork) Get(ctx context.Context, id string, size int, out io.Writer) error {
|
||||
if c.err != nil {
|
||||
return c.err
|
||||
}
|
||||
c.recvId = id
|
||||
c.recvSize = size
|
||||
_, err := out.Write([]byte(c.data))
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ func initUsersController(router *Router) *UsersController {
|
|||
}
|
||||
|
||||
func initMediaRetrievalController(router *Router) *MediaRetrievalController {
|
||||
cover := router.Cover
|
||||
mediaRetrievalController := NewMediaRetrievalController(cover)
|
||||
artwork := router.Artwork
|
||||
mediaRetrievalController := NewMediaRetrievalController(artwork)
|
||||
return mediaRetrievalController
|
||||
}
|
||||
|
||||
|
@ -75,5 +75,5 @@ var allProviders = wire.NewSet(
|
|||
NewSearchingController,
|
||||
NewUsersController,
|
||||
NewMediaRetrievalController,
|
||||
NewStreamController, wire.FieldsOf(new(*Router), "Browser", "Cover", "ListGenerator", "Playlists", "Ratings", "Scrobbler", "Search", "Streamer"),
|
||||
NewStreamController, wire.FieldsOf(new(*Router), "Browser", "Artwork", "ListGenerator", "Playlists", "Ratings", "Scrobbler", "Search", "Streamer"),
|
||||
)
|
||||
|
|
|
@ -16,7 +16,7 @@ var allProviders = wire.NewSet(
|
|||
NewUsersController,
|
||||
NewMediaRetrievalController,
|
||||
NewStreamController,
|
||||
wire.FieldsOf(new(*Router), "Browser", "Cover", "ListGenerator", "Playlists", "Ratings", "Scrobbler", "Search", "Streamer"),
|
||||
wire.FieldsOf(new(*Router), "Browser", "Artwork", "ListGenerator", "Playlists", "Ratings", "Scrobbler", "Search", "Streamer"),
|
||||
)
|
||||
|
||||
func initSystemController(router *Router) *SystemController {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue