diff --git a/frontend/src/Album/AlbumCover.js b/frontend/src/Album/AlbumCover.js
index 657cc038a..538fa5db8 100644
--- a/frontend/src/Album/AlbumCover.js
+++ b/frontend/src/Album/AlbumCover.js
@@ -1,175 +1,25 @@
-import _ from 'lodash';
import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import LazyLoad from 'react-lazyload';
+import React from 'react';
+import ArtistImage from 'Artist/ArtistImage';
const coverPlaceholder = 'data:image/png;base64,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';
-function findCover(images) {
- return _.find(images, { coverType: 'cover' });
-}
-
-function getCoverUrl(cover, size) {
- if (cover) {
- if (cover.url.contains('lastWrite=') || (/^https?:/).test(cover.url)) {
- // Remove protocol
- let url = cover.url.replace(/^https?:/, '');
- url = url.replace('cover.jpg', `cover-${size}.jpg`);
-
- return url;
- }
- }
-}
-
-class AlbumCover extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- const pixelRatio = Math.floor(window.devicePixelRatio);
-
- const {
- images,
- size
- } = props;
-
- const cover = findCover(images);
-
- this.state = {
- pixelRatio,
- cover,
- coverUrl: getCoverUrl(cover, pixelRatio * size),
- isLoaded: false,
- hasError: false
- };
- }
-
- componentDidUpdate(prevProps) {
- const {
- images,
- size
- } = this.props;
-
- const {
- cover,
- pixelRatio
- } = this.state;
-
- const nextCover = findCover(images);
-
- if (nextCover && (!cover || nextCover.url !== cover.url)) {
- this.setState({
- cover: nextCover,
- coverUrl: getCoverUrl(nextCover, pixelRatio * size),
- hasError: false,
- isLoaded: true
- });
- }
-
- // The cover could not be loaded..
- if (!nextCover && (this.props !== prevProps)) {
- this.setState({
- cover: undefined,
- coverUrl: coverPlaceholder,
- hasError: true
- });
- }
- }
-
- //
- // Listeners
-
- onError = () => {
- this.setState({ hasError: true });
- }
-
- onLoad = () => {
- this.setState({
- isLoaded: true,
- hasError: false
- });
- }
-
- //
- // Render
-
- render() {
- const {
- className,
- style,
- size,
- lazy,
- overflow
- } = this.props;
-
- const {
- coverUrl,
- hasError,
- isLoaded
- } = this.state;
-
- if (hasError || !coverUrl) {
- return (
-
- );
- }
-
- if (lazy) {
- return (
-
- }
- >
-
-
- );
- }
-
- return (
-
- );
- }
+function AlbumCover(props) {
+ return (
+
+ );
}
AlbumCover.propTypes = {
- className: PropTypes.string,
- style: PropTypes.object,
- images: PropTypes.arrayOf(PropTypes.object).isRequired,
- size: PropTypes.number.isRequired,
- lazy: PropTypes.bool.isRequired,
- overflow: PropTypes.bool.isRequired
+ size: PropTypes.number.isRequired
};
AlbumCover.defaultProps = {
- size: 250,
- lazy: true,
- overflow: false
+ size: 250
};
export default AlbumCover;
diff --git a/frontend/src/Album/Details/AlbumDetails.js b/frontend/src/Album/Details/AlbumDetails.js
index 36fd795f7..f2288b00f 100644
--- a/frontend/src/Album/Details/AlbumDetails.js
+++ b/frontend/src/Album/Details/AlbumDetails.js
@@ -301,7 +301,7 @@ class AlbumDetails extends Component {
diff --git a/frontend/src/Artist/ArtistImage.js b/frontend/src/Artist/ArtistImage.js
index 576a354a1..6ae479a18 100644
--- a/frontend/src/Artist/ArtistImage.js
+++ b/frontend/src/Artist/ArtistImage.js
@@ -10,6 +10,7 @@ function getUrl(image, coverType, size) {
if (image) {
// Remove protocol
let url = image.url.replace(/^https?:/, '');
+
url = url.replace(`${coverType}.jpg`, `${coverType}-${size}.jpg`);
return url;
@@ -24,7 +25,7 @@ class ArtistImage extends Component {
constructor(props, context) {
super(props, context);
- const pixelRatio = Math.floor(window.devicePixelRatio);
+ const pixelRatio = Math.ceil(window.devicePixelRatio);
const {
images,
diff --git a/frontend/src/Artist/Details/ArtistDetails.js b/frontend/src/Artist/Details/ArtistDetails.js
index 74dc1d4c6..85831a955 100644
--- a/frontend/src/Artist/Details/ArtistDetails.js
+++ b/frontend/src/Artist/Details/ArtistDetails.js
@@ -353,7 +353,7 @@ class ArtistDetails extends Component {
diff --git a/src/Lidarr.Api.V1/Albums/AlbumModule.cs b/src/Lidarr.Api.V1/Albums/AlbumModule.cs
index 25acab4c4..e09eb8204 100644
--- a/src/Lidarr.Api.V1/Albums/AlbumModule.cs
+++ b/src/Lidarr.Api.V1/Albums/AlbumModule.cs
@@ -12,6 +12,7 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Download;
using NzbDrone.Core.Music.Events;
using NzbDrone.Core.MediaFiles.Events;
+using NzbDrone.Core.MediaCover;
namespace Lidarr.Api.V1.Albums
{
@@ -23,13 +24,14 @@ namespace Lidarr.Api.V1.Albums
{
protected readonly IReleaseService _releaseService;
-
+
public AlbumModule(IAlbumService albumService,
IReleaseService releaseService,
IArtistStatisticsService artistStatisticsService,
+ IMapCoversToLocal coverMapper,
IUpgradableSpecification upgradableSpecification,
IBroadcastSignalRMessage signalRBroadcaster)
- : base(albumService, artistStatisticsService, upgradableSpecification, signalRBroadcaster)
+ : base(albumService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
{
_releaseService = releaseService;
GetResourceAll = GetAlbums;
diff --git a/src/Lidarr.Api.V1/Albums/AlbumModuleWithSignalR.cs b/src/Lidarr.Api.V1/Albums/AlbumModuleWithSignalR.cs
index 3e44d469a..4c7b4f873 100644
--- a/src/Lidarr.Api.V1/Albums/AlbumModuleWithSignalR.cs
+++ b/src/Lidarr.Api.V1/Albums/AlbumModuleWithSignalR.cs
@@ -7,6 +7,7 @@ using NzbDrone.Core.Music;
using NzbDrone.Core.ArtistStats;
using NzbDrone.SignalR;
using Lidarr.Http;
+using NzbDrone.Core.MediaCover;
namespace Lidarr.Api.V1.Albums
{
@@ -15,15 +16,18 @@ namespace Lidarr.Api.V1.Albums
protected readonly IAlbumService _albumService;
protected readonly IArtistStatisticsService _artistStatisticsService;
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
+ protected readonly IMapCoversToLocal _coverMapper;
protected AlbumModuleWithSignalR(IAlbumService albumService,
IArtistStatisticsService artistStatisticsService,
+ IMapCoversToLocal coverMapper,
IUpgradableSpecification qualityUpgradableSpecification,
IBroadcastSignalRMessage signalRBroadcaster)
: base(signalRBroadcaster)
{
_albumService = albumService;
_artistStatisticsService = artistStatisticsService;
+ _coverMapper = coverMapper;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
GetResourceById = GetAlbum;
@@ -62,6 +66,7 @@ namespace Lidarr.Api.V1.Albums
}
FetchAndLinkAlbumStatistics(resource);
+ MapCoversToLocal(resource);
return resource;
}
@@ -86,6 +91,7 @@ namespace Lidarr.Api.V1.Albums
var artistStats = _artistStatisticsService.ArtistStatistics();
LinkArtistStatistics(result, artistStats);
+ MapCoversToLocal(result.ToArray());
return result;
}
@@ -114,5 +120,13 @@ namespace Lidarr.Api.V1.Albums
}
}
+
+ private void MapCoversToLocal(params AlbumResource[] albums)
+ {
+ foreach (var albumResource in albums)
+ {
+ _coverMapper.ConvertToLocalUrls(albumResource.Id, MediaCoverEntity.Album, albumResource.Images);
+ }
+ }
}
}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistModule.cs b/src/Lidarr.Api.V1/Artist/ArtistModule.cs
index f33c4a817..552ce404b 100644
--- a/src/Lidarr.Api.V1/Artist/ArtistModule.cs
+++ b/src/Lidarr.Api.V1/Artist/ArtistModule.cs
@@ -181,7 +181,7 @@ namespace Lidarr.Api.V1.Artist
{
foreach (var artistResource in artists)
{
- _coverMapper.ConvertToLocalUrls(artistResource.Id, artistResource.Images);
+ _coverMapper.ConvertToLocalUrls(artistResource.Id, MediaCoverEntity.Artist, artistResource.Images);
}
}
diff --git a/src/Lidarr.Api.V1/MediaCovers/MediaCoverModule.cs b/src/Lidarr.Api.V1/MediaCovers/MediaCoverModule.cs
index 8b5f880cf..70d0cee8c 100644
--- a/src/Lidarr.Api.V1/MediaCovers/MediaCoverModule.cs
+++ b/src/Lidarr.Api.V1/MediaCovers/MediaCoverModule.cs
@@ -12,7 +12,8 @@ namespace Lidarr.Api.V1.MediaCovers
{
private static readonly Regex RegexResizedImage = new Regex(@"-\d+\.jpg$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- private const string MEDIA_COVER_ROUTE = @"/(?\d+)/(?(.+)\.(jpg|png|gif))";
+ private const string MEDIA_COVER_ARTIST_ROUTE = @"/Artist/(?\d+)/(?(.+)\.(jpg|png|gif))";
+ private const string MEDIA_COVER_ALBUM_ROUTE = @"/Album/(?\d+)/(?(.+)\.(jpg|png|gif))";
private readonly IAppFolderInfo _appFolderInfo;
private readonly IDiskProvider _diskProvider;
@@ -22,10 +23,11 @@ namespace Lidarr.Api.V1.MediaCovers
_appFolderInfo = appFolderInfo;
_diskProvider = diskProvider;
- Get[MEDIA_COVER_ROUTE] = options => GetMediaCover(options.artistId, options.filename);
+ Get[MEDIA_COVER_ARTIST_ROUTE] = options => GetArtistMediaCover(options.artistId, options.filename);
+ Get[MEDIA_COVER_ALBUM_ROUTE] = options => GetAlbumMediaCover(options.artistId, options.filename);
}
- private Response GetMediaCover(int artistId, string filename)
+ private Response GetArtistMediaCover(int artistId, string filename)
{
var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", artistId.ToString(), filename);
@@ -43,5 +45,24 @@ namespace Lidarr.Api.V1.MediaCovers
return new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath));
}
+
+ private Response GetAlbumMediaCover(int albumId, string filename)
+ {
+ var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", "Albums", albumId.ToString(), filename);
+
+ if (!_diskProvider.FileExists(filePath) || _diskProvider.GetFileSize(filePath) == 0)
+ {
+ // Return the full sized image if someone requests a non-existing resized one.
+ // TODO: This code can be removed later once everyone had the update for a while.
+ var basefilePath = RegexResizedImage.Replace(filePath, ".jpg");
+ if (basefilePath == filePath || !_diskProvider.FileExists(basefilePath))
+ {
+ return new NotFoundResponse();
+ }
+ filePath = basefilePath;
+ }
+
+ return new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath));
+ }
}
}
diff --git a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs
index 4877cb48b..52e3e093f 100644
--- a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs
+++ b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs
@@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Mocker.GetMock().Setup(c => c.FileExists(It.IsAny()))
.Returns(true);
- Subject.ConvertToLocalUrls(12, covers);
+ Subject.ConvertToLocalUrls(12, MediaCoverEntity.Artist, covers);
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg?lastWrite=1234");
@@ -75,10 +75,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Mocker.GetMock().Setup(c => c.FileExists(It.IsAny()))
.Returns(true);
- Subject.ConvertToLocalUrls(12, covers, 6);
+ Subject.ConvertToLocalUrls(6, MediaCoverEntity.Album, covers);
- covers.Single().Url.Should().Be("/MediaCover/12/6/disc.jpg?lastWrite=1234");
+ covers.Single().Url.Should().Be("/MediaCover/Albums/6/disc.jpg?lastWrite=1234");
}
[Test]
@@ -90,7 +90,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
};
- Subject.ConvertToLocalUrls(12, covers);
+ Subject.ConvertToLocalUrls(12, MediaCoverEntity.Artist, covers);
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg");
@@ -103,6 +103,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
.Setup(v => v.AlreadyExists(It.IsAny(), It.IsAny()))
.Returns(false);
+ Mocker.GetMock()
+ .Setup(v => v.GetAlbumsByArtist(It.IsAny()))
+ .Returns(new List { _album });
+
Mocker.GetMock()
.Setup(v => v.FileExists(It.IsAny()))
.Returns(true);
@@ -110,7 +114,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Subject.HandleAsync(new ArtistUpdatedEvent(_artist));
Mocker.GetMock()
- .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2));
+ .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3));
}
[Test]
@@ -120,6 +124,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
.Setup(v => v.AlreadyExists(It.IsAny(), It.IsAny()))
.Returns(true);
+ Mocker.GetMock()
+ .Setup(v => v.GetAlbumsByArtist(It.IsAny()))
+ .Returns(new List { _album });
+
Mocker.GetMock()
.Setup(v => v.FileExists(It.IsAny()))
.Returns(false);
@@ -127,7 +135,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Subject.HandleAsync(new ArtistUpdatedEvent(_artist));
Mocker.GetMock()
- .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2));
+ .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3));
}
[Test]
@@ -141,6 +149,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
.Setup(v => v.FileExists(It.IsAny()))
.Returns(true);
+ Mocker.GetMock()
+ .Setup(v => v.GetAlbumsByArtist(It.IsAny()))
+ .Returns(new List { _album });
+
Mocker.GetMock()
.Setup(v => v.GetFileSize(It.IsAny()))
.Returns(1000);
@@ -162,6 +174,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
.Setup(v => v.FileExists(It.IsAny()))
.Returns(true);
+ Mocker.GetMock()
+ .Setup(v => v.GetAlbumsByArtist(It.IsAny()))
+ .Returns(new List { _album });
+
Mocker.GetMock()
.Setup(v => v.GetFileSize(It.IsAny()))
.Returns(0);
@@ -169,7 +185,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Subject.HandleAsync(new ArtistUpdatedEvent(_artist));
Mocker.GetMock()
- .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2));
+ .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3));
}
[Test]
@@ -183,6 +199,10 @@ namespace NzbDrone.Core.Test.MediaCoverTests
.Setup(v => v.FileExists(It.IsAny()))
.Returns(false);
+ Mocker.GetMock()
+ .Setup(v => v.GetAlbumsByArtist(It.IsAny()))
+ .Returns(new List { _album });
+
Mocker.GetMock()
.Setup(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()))
.Throws();
@@ -190,7 +210,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
Subject.HandleAsync(new ArtistUpdatedEvent(_artist));
Mocker.GetMock()
- .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2));
+ .Verify(v => v.Resize(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3));
}
}
}
diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs
index 1cffae9d8..daf1368e0 100644
--- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs
+++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs
@@ -165,7 +165,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
return new List(); ;
}
- var source = _mediaCoverService.GetCoverPath(artist.Id, image.CoverType);
+ var source = _mediaCoverService.GetCoverPath(artist.Id, MediaCoverEntity.Artist, image.CoverType);
var destination = Path.GetFileName(artist.Path) + Path.GetExtension(source);
return new List{ new ImageFileResult(destination, source) };
diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
index ed91bc47c..c849b867e 100644
--- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
+++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
@@ -205,7 +205,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
{
foreach (var image in artist.Metadata.Value.Images)
{
- var source = _mediaCoverService.GetCoverPath(artist.Id, image.CoverType);
+ var source = _mediaCoverService.GetCoverPath(artist.Id, MediaCoverEntity.Artist, image.CoverType);
var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(image.Url);
if (image.CoverType == MediaCoverTypes.Poster)
{
diff --git a/src/NzbDrone.Core/MediaCover/MediaCover.cs b/src/NzbDrone.Core/MediaCover/MediaCover.cs
index ed832e003..3829cb450 100644
--- a/src/NzbDrone.Core/MediaCover/MediaCover.cs
+++ b/src/NzbDrone.Core/MediaCover/MediaCover.cs
@@ -16,6 +16,12 @@ namespace NzbDrone.Core.MediaCover
Logo = 8
}
+ public enum MediaCoverEntity
+ {
+ Artist = 0,
+ Album = 1
+ }
+
public class MediaCover : IEmbeddedDocument
{
public MediaCoverTypes CoverType { get; set; }
diff --git a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs
index e64505893..09aa0a8d2 100644
--- a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs
+++ b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Net;
using NLog;
using NzbDrone.Common.Disk;
@@ -16,8 +17,8 @@ namespace NzbDrone.Core.MediaCover
{
public interface IMapCoversToLocal
{
- void ConvertToLocalUrls(int artistId, IEnumerable covers, int? albumId = null);
- string GetCoverPath(int artistId, MediaCoverTypes mediaCoverTypes, int? height = null, int? albumId = null);
+ void ConvertToLocalUrls(int entityId, MediaCoverEntity coverEntity, IEnumerable covers);
+ string GetCoverPath(int entityId, MediaCoverEntity coverEntity, MediaCoverTypes mediaCoverTypes, int? height = null);
}
public class MediaCoverService :
@@ -58,31 +59,33 @@ namespace NzbDrone.Core.MediaCover
_coverRootFolder = appFolderInfo.GetMediaCoverPath();
}
- public string GetCoverPath(int artistId, MediaCoverTypes coverTypes, int? height = null, int? albumId = null)
+ public string GetCoverPath(int entityId, MediaCoverEntity coverEntity, MediaCoverTypes coverTypes, int? height = null)
{
var heightSuffix = height.HasValue ? "-" + height.ToString() : "";
- if (albumId.HasValue)
+ if (coverEntity == MediaCoverEntity.Album)
{
- return Path.Combine(GetAlbumCoverPath(artistId, albumId.Value), coverTypes.ToString().ToLower() + heightSuffix + ".jpg");
+ return Path.Combine(GetAlbumCoverPath(entityId), coverTypes.ToString().ToLower() + heightSuffix + ".jpg");
+ }
+ else
+ {
+ return Path.Combine(GetArtistCoverPath(entityId), coverTypes.ToString().ToLower() + heightSuffix + ".jpg");
}
-
- return Path.Combine(GetArtistCoverPath(artistId), coverTypes.ToString().ToLower() + heightSuffix + ".jpg");
}
- public void ConvertToLocalUrls(int artistId, IEnumerable covers, int? albumId = null)
+ public void ConvertToLocalUrls(int entityId, MediaCoverEntity coverEntity, IEnumerable covers)
{
foreach (var mediaCover in covers)
{
- var filePath = GetCoverPath(artistId, mediaCover.CoverType, null, albumId);
+ var filePath = GetCoverPath(entityId, coverEntity, mediaCover.CoverType, null);
- if (albumId.HasValue)
+ if (coverEntity == MediaCoverEntity.Album)
{
- mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + artistId + "/" + albumId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
+ mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/Albums/" + entityId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
}
else
{
- mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + artistId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
+ mediaCover.Url = _configFileProvider.UrlBase + @"/MediaCover/" + entityId + "/" + mediaCover.CoverType.ToString().ToLower() + ".jpg";
}
if (_diskProvider.FileExists(filePath))
@@ -98,16 +101,16 @@ namespace NzbDrone.Core.MediaCover
return Path.Combine(_coverRootFolder, artistId.ToString());
}
- private string GetAlbumCoverPath(int artistId, int albumId)
+ private string GetAlbumCoverPath(int albumId)
{
- return Path.Combine(_coverRootFolder, artistId.ToString(), albumId.ToString());
+ return Path.Combine(_coverRootFolder, "Albums", albumId.ToString());
}
- private void EnsureCovers(Artist artist)
+ private void EnsureArtistCovers(Artist artist)
{
foreach (var cover in artist.Metadata.Value.Images)
{
- var fileName = GetCoverPath(artist.Id, cover.CoverType);
+ var fileName = GetCoverPath(artist.Id, MediaCoverEntity.Artist, cover.CoverType);
var alreadyExists = false;
try
@@ -134,37 +137,37 @@ namespace NzbDrone.Core.MediaCover
}
}
- //TODO Decide if we want to cache album art local
- //private void EnsureAlbumCovers(Album album)
- //{
- // foreach (var cover in album.Images)
- // {
- // var fileName = GetCoverPath(album.ArtistId, cover.CoverType, null, album.Id);
- // var alreadyExists = false;
- // try
- // {
- // alreadyExists = _coverExistsSpecification.AlreadyExists(cover.Url, fileName);
- // if (!alreadyExists)
- // {
- // DownloadAlbumCover(album, cover);
- // }
- // }
- // catch (WebException e)
- // {
- // _logger.Warn("Couldn't download media cover for {0}. {1}", album, e.Message);
- // }
- // catch (Exception e)
- // {
- // _logger.Error(e, "Couldn't download media cover for {0}", album);
- // }
-
- // EnsureResizedCovers(album.Artist, cover, !alreadyExists, album);
- // }
- //}
+ private void EnsureAlbumCovers(Album album)
+ {
+ foreach (var cover in album.Images.Where(e => e.CoverType == MediaCoverTypes.Cover))
+ {
+ var fileName = GetCoverPath(album.Id, MediaCoverEntity.Album, cover.CoverType, null);
+ var alreadyExists = false;
+ try
+ {
+ var lastModifiedServer = GetCoverModifiedDate(cover.Url);
+ alreadyExists = _coverExistsSpecification.AlreadyExists(lastModifiedServer, fileName);
+ if (!alreadyExists)
+ {
+ DownloadAlbumCover(album, cover, lastModifiedServer);
+ }
+ }
+ catch (WebException e)
+ {
+ _logger.Warn("Couldn't download media cover for {0}. {1}", album, e.Message);
+ }
+ catch (Exception e)
+ {
+ _logger.Error(e, "Couldn't download media cover for {0}", album);
+ }
+
+ EnsureResizedAlbumCovers(album, cover, !alreadyExists);
+ }
+ }
private void DownloadCover(Artist artist, MediaCover cover, DateTime lastModified)
{
- var fileName = GetCoverPath(artist.Id, cover.CoverType);
+ var fileName = GetCoverPath(artist.Id, MediaCoverEntity.Artist, cover.CoverType);
_logger.Info("Downloading {0} for {1} {2}", cover.CoverType, artist, cover.Url);
_httpClient.DownloadFile(cover.Url, fileName);
@@ -179,124 +182,132 @@ namespace NzbDrone.Core.MediaCover
}
}
- //private void DownloadAlbumCover(Album album, MediaCover cover)
- //{
- // var fileName = GetCoverPath(album.ArtistId, cover.CoverType, null, album.Id);
+ private void DownloadAlbumCover(Album album, MediaCover cover, DateTime lastModified)
+ {
+ var fileName = GetCoverPath(album.Id, MediaCoverEntity.Album, cover.CoverType, null);
- // _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, album, cover.Url);
- // _httpClient.DownloadFile(cover.Url, fileName);
- //}
+ _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, album, cover.Url);
+ _httpClient.DownloadFile(cover.Url, fileName);
+
+ try
+ {
+ _diskProvider.FileSetLastWriteTime(fileName, lastModified);
+ }
+ catch (Exception ex)
+ {
+ _logger.Debug(ex, "Unable to set modified date for {0} image for album {1}", cover.CoverType, album);
+ }
+ }
private void EnsureResizedCovers(Artist artist, MediaCover cover, bool forceResize, Album album = null)
{
- int[] heights;
+ int[] heights = GetDefaultHeights(cover.CoverType);
- switch (cover.CoverType)
+ foreach (var height in heights)
{
- default:
- return;
-
- case MediaCoverTypes.Poster:
- case MediaCoverTypes.Cover:
- case MediaCoverTypes.Disc:
- case MediaCoverTypes.Logo:
- case MediaCoverTypes.Headshot:
- heights = new[] { 500, 250 };
- break;
-
- case MediaCoverTypes.Banner:
- heights = new[] { 70, 35 };
- break;
+ var mainFileName = GetCoverPath(artist.Id, MediaCoverEntity.Artist, cover.CoverType);
+ var resizeFileName = GetCoverPath(artist.Id, MediaCoverEntity.Artist, cover.CoverType, height);
- case MediaCoverTypes.Fanart:
- case MediaCoverTypes.Screenshot:
- heights = new[] { 360, 180 };
- break;
- }
-
-
- if (album == null)
- {
- foreach (var height in heights)
+ if (forceResize || !_diskProvider.FileExists(resizeFileName) || _diskProvider.GetFileSize(resizeFileName) == 0)
{
- var mainFileName = GetCoverPath(artist.Id, cover.CoverType);
- var resizeFileName = GetCoverPath(artist.Id, cover.CoverType, height);
+ _logger.Debug("Resizing {0}-{1} for {2}", cover.CoverType, height, artist);
- if (forceResize || !_diskProvider.FileExists(resizeFileName) || _diskProvider.GetFileSize(resizeFileName) == 0)
+ try
+ {
+ _resizer.Resize(mainFileName, resizeFileName, height);
+ }
+ catch
{
- _logger.Debug("Resizing {0}-{1} for {2}", cover.CoverType, height, artist);
-
- try
- {
- _resizer.Resize(mainFileName, resizeFileName, height);
- }
- catch
- {
- _logger.Debug("Couldn't resize media cover {0}-{1} for {2}, using full size image instead.", cover.CoverType, height, artist);
- }
+ _logger.Debug("Couldn't resize media cover {0}-{1} for artist {2}, using full size image instead.", cover.CoverType, height, artist);
}
}
}
- else
+ }
+
+ private void EnsureResizedAlbumCovers(Album album, MediaCover cover, bool forceResize)
+ {
+ int[] heights = GetDefaultHeights(cover.CoverType);
+
+ foreach (var height in heights)
{
- foreach (var height in heights)
- {
- var mainFileName = GetCoverPath(album.ArtistId, cover.CoverType, null, album.Id);
- var resizeFileName = GetCoverPath(album.ArtistId, cover.CoverType, height, album.Id);
+ var mainFileName = GetCoverPath(album.Id, MediaCoverEntity.Album, cover.CoverType, null);
+ var resizeFileName = GetCoverPath(album.Id, MediaCoverEntity.Album, cover.CoverType, height);
- if (forceResize || !_diskProvider.FileExists(resizeFileName) || _diskProvider.GetFileSize(resizeFileName) == 0)
+ if (forceResize || !_diskProvider.FileExists(resizeFileName) || _diskProvider.GetFileSize(resizeFileName) == 0)
+ {
+ _logger.Debug("Resizing {0}-{1} for {2}", cover.CoverType, height, album);
+
+ try
+ {
+ _resizer.Resize(mainFileName, resizeFileName, height);
+ }
+ catch
{
- _logger.Debug("Resizing {0}-{1} for {2}", cover.CoverType, height, artist);
-
- try
- {
- _resizer.Resize(mainFileName, resizeFileName, height);
- }
- catch
- {
- _logger.Debug("Couldn't resize media cover {0}-{1} for {2}, using full size image instead.", cover.CoverType, height, album);
- }
+ _logger.Debug("Couldn't resize media cover {0}-{1} for album {2}, using full size image instead.", cover.CoverType, height, album);
}
}
}
}
- public void HandleAsync(ArtistUpdatedEvent message)
+ private DateTime GetCoverModifiedDate(string url)
{
- EnsureCovers(message.Artist);
+ var lastModifiedServer = DateTime.Now;
- //Turn off for now, not using album images
+ var headers = _httpClient.Head(new HttpRequest(url)).Headers;
- //var albums = _albumService.GetAlbumsByArtist(message.Artist.Id);
- //foreach (Album album in albums)
- //{
- // EnsureAlbumCovers(album);
- //}
-
- _eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Artist));
+ if (headers.LastModified.HasValue)
+ {
+ lastModifiedServer = headers.LastModified.Value;
+ }
+
+ return lastModifiedServer;
}
- public void HandleAsync(ArtistDeletedEvent message)
+ private int[] GetDefaultHeights(MediaCoverTypes coverType)
{
- var path = GetArtistCoverPath(message.Artist.Id);
- if (_diskProvider.FolderExists(path))
+ switch (coverType)
{
- _diskProvider.DeleteFolder(path, true);
+ default:
+ return new int[] { };
+
+ case MediaCoverTypes.Poster:
+ case MediaCoverTypes.Disc:
+ case MediaCoverTypes.Logo:
+ case MediaCoverTypes.Headshot:
+ return new[] { 500, 250 };
+
+ case MediaCoverTypes.Banner:
+ return new[] { 70, 35 };
+
+ case MediaCoverTypes.Fanart:
+ case MediaCoverTypes.Screenshot:
+ return new[] { 360, 180 };
+ case MediaCoverTypes.Cover:
+ return new[] { 250 };
}
}
- private DateTime GetCoverModifiedDate(string url)
+ public void HandleAsync(ArtistUpdatedEvent message)
{
- var lastModifiedServer = DateTime.Now;
+ EnsureArtistCovers(message.Artist);
- var headers = _httpClient.Head(new HttpRequest(url)).Headers;
-
- if (headers.LastModified.HasValue)
+ var albums = _albumService.GetAlbumsByArtist(message.Artist.Id);
+ foreach (Album album in albums)
{
- lastModifiedServer = headers.LastModified.Value;
+ EnsureAlbumCovers(album);
}
- return lastModifiedServer;
+ _eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Artist));
}
+
+ public void HandleAsync(ArtistDeletedEvent message)
+ {
+ var path = GetArtistCoverPath(message.Artist.Id);
+ if (_diskProvider.FolderExists(path))
+ {
+ _diskProvider.DeleteFolder(path, true);
+ }
+ }
+
}
}