diff --git a/engine/cover.go b/engine/cover.go index deccc9414..9aa6c45ba 100644 --- a/engine/cover.go +++ b/engine/cover.go @@ -46,6 +46,18 @@ func (c *cover) Get(ctx context.Context, id string, size int, out io.Writer) err return err } + // If cache is disabled, just read the coverart directly from file + if c.cache == nil { + log.Trace(ctx, "Retrieving cover art from file", "path", path, "size", size, err) + reader, err := c.getCover(ctx, path, size) + if err != nil { + log.Error(ctx, "Error loading cover art", "path", path, "size", size, err) + } else { + _, err = io.Copy(out, reader) + } + return err + } + cacheKey := imageCacheKey(path, size, lastUpdate) r, w, err := c.cache.Get(cacheKey) if err != nil { @@ -158,5 +170,5 @@ func readFromTag(path string) ([]byte, error) { } func NewImageCache() (ImageCache, error) { - return newFileCache("image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems) + return newFileCache("Image", conf.Server.ImageCacheSize, consts.ImageCacheDir, consts.DefaultImageCacheMaxItems) } diff --git a/engine/cover_test.go b/engine/cover_test.go index ecc0f0f7f..213c974df 100644 --- a/engine/cover_test.go +++ b/engine/cover_test.go @@ -20,86 +20,106 @@ var _ = Describe("Cover", func() { ds = &persistence.MockDataStore{MockedTranscoding: &mockTranscodingRepository{}} ds.Album(ctx).(*persistence.MockAlbum).SetData(`[{"id": "222", "coverArtId": "123"}, {"id": "333", "coverArtId": ""}]`) ds.MediaFile(ctx).(*persistence.MockMediaFile).SetData(`[{"id": "123", "path": "tests/fixtures/test.mp3", "hasCoverArt": true, "updatedAt":"2020-04-02T21:29:31.6377Z"}]`) - cover = NewCover(ds, testCache) }) - It("retrieves the original cover art from an album", func() { - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "222", 0, buf)).To(BeNil()) - - _, format, err := image.Decode(bytes.NewReader(buf.Bytes())) - Expect(err).To(BeNil()) - Expect(format).To(Equal("jpeg")) - }) - - It("accepts albumIds with 'al-' prefix", func() { - buf := new(bytes.Buffer) - - Expect(cover.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() { - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "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() { - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "444", 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() { - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "123", 0, buf)).To(BeNil()) - - img, format, err := image.Decode(bytes.NewReader(buf.Bytes())) - Expect(err).To(BeNil()) - Expect(format).To(Equal("jpeg")) - Expect(img.Bounds().Size().X).To(Equal(600)) - Expect(img.Bounds().Size().Y).To(Equal(600)) - }) - - It("resized cover art as requested", func() { - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "123", 200, buf)).To(BeNil()) - - img, format, err := image.Decode(bytes.NewReader(buf.Bytes())) - Expect(err).To(BeNil()) - Expect(format).To(Equal("jpeg")) - Expect(img.Bounds().Size().X).To(Equal(200)) - Expect(img.Bounds().Size().Y).To(Equal(200)) - }) - - Context("Errors", func() { - It("returns err if gets error from album table", func() { - ds.Album(ctx).(*persistence.MockAlbum).SetError(true) - buf := new(bytes.Buffer) - - Expect(cover.Get(ctx, "222", 0, buf)).To(MatchError("Error!")) + Context("Cache is configured", func() { + BeforeEach(func() { + cover = NewCover(ds, testCache) }) - It("returns err if gets error from media_file table", func() { - ds.MediaFile(ctx).(*persistence.MockMediaFile).SetError(true) + It("retrieves the original cover art from an album", func() { buf := new(bytes.Buffer) - Expect(cover.Get(ctx, "123", 0, buf)).To(MatchError("Error!")) + Expect(cover.Get(ctx, "222", 0, buf)).To(BeNil()) + + _, format, err := image.Decode(bytes.NewReader(buf.Bytes())) + Expect(err).To(BeNil()) + Expect(format).To(Equal("jpeg")) + }) + + It("accepts albumIds with 'al-' prefix", func() { + buf := new(bytes.Buffer) + + Expect(cover.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() { + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "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() { + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "444", 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() { + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "123", 0, buf)).To(BeNil()) + + img, format, err := image.Decode(bytes.NewReader(buf.Bytes())) + Expect(err).To(BeNil()) + Expect(format).To(Equal("jpeg")) + Expect(img.Bounds().Size().X).To(Equal(600)) + Expect(img.Bounds().Size().Y).To(Equal(600)) + }) + + It("resized cover art as requested", func() { + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "123", 200, buf)).To(BeNil()) + + img, format, err := image.Decode(bytes.NewReader(buf.Bytes())) + Expect(err).To(BeNil()) + Expect(format).To(Equal("jpeg")) + Expect(img.Bounds().Size().X).To(Equal(200)) + Expect(img.Bounds().Size().Y).To(Equal(200)) + }) + + Context("Errors", func() { + It("returns err if gets error from album table", func() { + ds.Album(ctx).(*persistence.MockAlbum).SetError(true) + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "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!")) + }) + }) + }) + Context("Cache is NOT configured", func() { + BeforeEach(func() { + cover = NewCover(ds, nil) + }) + + It("retrieves the original cover art from an album", func() { + buf := new(bytes.Buffer) + + Expect(cover.Get(ctx, "222", 0, buf)).To(BeNil()) + + _, format, err := image.Decode(bytes.NewReader(buf.Bytes())) + Expect(err).To(BeNil()) + Expect(format).To(Equal("jpeg")) }) }) }) diff --git a/engine/file_caches.go b/engine/file_caches.go index 7ab573efa..6ff8cbe0f 100644 --- a/engine/file_caches.go +++ b/engine/file_caches.go @@ -12,6 +12,10 @@ import ( ) func newFileCache(name, cacheSize, cacheFolder string, maxItems int) (fscache.Cache, error) { + if cacheSize == "0" { + log.Warn(fmt.Sprintf("%s cache disabled", name)) + return nil, nil + } size, err := humanize.ParseBytes(cacheSize) if err != nil { size = consts.DefaultCacheSize diff --git a/engine/file_caches_test.go b/engine/file_caches_test.go index f3c76b179..3e49e17a2 100644 --- a/engine/file_caches_test.go +++ b/engine/file_caches_test.go @@ -29,5 +29,9 @@ var _ = Describe("File Caches", func() { It("creates the cache folder with invalid size", func() { Expect(newFileCache("test", "abc", "test", 10)).ToNot(BeNil()) }) + + It("returns empty if cache size is '0'", func() { + Expect(newFileCache("test", "0", "test", 10)).To(BeNil()) + }) }) }) diff --git a/engine/media_streamer.go b/engine/media_streamer.go index 50ad99544..c37c5f31a 100644 --- a/engine/media_streamer.go +++ b/engine/media_streamer.go @@ -213,5 +213,5 @@ func getFinalCachedSize(r fscache.ReadAtCloser) int64 { } func NewTranscodingCache() (TranscodingCache, error) { - return newFileCache("transcoding", conf.Server.TranscodingCacheSize, consts.TranscodingCacheDir, consts.DefaultTranscodingCacheMaxItems) + return newFileCache("Transcoding", conf.Server.TranscodingCacheSize, consts.TranscodingCacheDir, consts.DefaultTranscodingCacheMaxItems) }