diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 65ff30a2a..7fcfd5b9e 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -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 } diff --git a/core/cover.go b/core/artwork.go similarity index 79% rename from core/cover.go rename to core/artwork.go index 623e2e46b..4cf20c535 100644 --- a/core/cover.go +++ b/core/artwork.go @@ -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 diff --git a/core/cover_test.go b/core/artwork_test.go similarity index 73% rename from core/cover_test.go rename to core/artwork_test.go index 26ad8f528..3c69c3e74 100644 --- a/core/cover_test.go +++ b/core/artwork_test.go @@ -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!")) }) }) }) diff --git a/core/wire_providers.go b/core/wire_providers.go index f3ae654fb..45c94da79 100644 --- a/core/wire_providers.go +++ b/core/wire_providers.go @@ -6,7 +6,7 @@ import ( ) var Set = wire.NewSet( - NewCover, + NewArtwork, NewMediaStreamer, NewTranscodingCache, NewImageCache, diff --git a/server/subsonic/api.go b/server/subsonic/api.go index 7ec74ce92..8d6b1e8cc 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -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 diff --git a/server/subsonic/media_retrieval.go b/server/subsonic/media_retrieval.go index 2fe0ad617..fadc0d423 100644 --- a/server/subsonic/media_retrieval.go +++ b/server/subsonic/media_retrieval.go @@ -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") diff --git a/server/subsonic/media_retrieval_test.go b/server/subsonic/media_retrieval_test.go index bd6b4ca8d..08bf18900 100644 --- a/server/subsonic/media_retrieval_test.go +++ b/server/subsonic/media_retrieval_test.go @@ -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 +} diff --git a/server/subsonic/wire_gen.go b/server/subsonic/wire_gen.go index d67eb43de..872c02c24 100644 --- a/server/subsonic/wire_gen.go +++ b/server/subsonic/wire_gen.go @@ -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"), ) diff --git a/server/subsonic/wire_injectors.go b/server/subsonic/wire_injectors.go index 7956b50df..0a6761707 100644 --- a/server/subsonic/wire_injectors.go +++ b/server/subsonic/wire_injectors.go @@ -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 {