aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs3
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj2
-rw-r--r--MediaBrowser.Controller/Providers/IImageProvider.cs6
-rw-r--r--MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs27
-rw-r--r--MediaBrowser.Controller/Providers/IMetadataProvider.cs33
-rw-r--r--MediaBrowser.Controller/Providers/IMetadataService.cs3
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs4
-rw-r--r--MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs21
-rw-r--r--MediaBrowser.Controller/Providers/ItemId.cs14
-rw-r--r--MediaBrowser.Providers/All/LocalImageProvider.cs4
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Genres/GenreMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Manager/ConcreteMetadataService.cs5
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs37
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs79
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs105
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj19
-rw-r--r--MediaBrowser.Providers/Movies/FanArtMovieProvider.cs8
-rw-r--r--MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs10
-rw-r--r--MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs8
-rw-r--r--MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs154
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs188
-rw-r--r--MediaBrowser.Providers/Music/AlbumProviderFromXml.cs92
-rw-r--r--MediaBrowser.Providers/Music/AlbumXmlProvider.cs59
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/Music/FanArtAlbumProvider.cs413
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs4
-rw-r--r--MediaBrowser.Providers/Music/LastFmImageProvider.cs188
-rw-r--r--MediaBrowser.Providers/Music/LastfmAlbumProvider.cs309
-rw-r--r--MediaBrowser.Providers/Music/LastfmArtistProvider.cs28
-rw-r--r--MediaBrowser.Providers/Music/LastfmBaseProvider.cs194
-rw-r--r--MediaBrowser.Providers/Music/LastfmHelper.cs50
-rw-r--r--MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs354
-rw-r--r--MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs150
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs65
-rw-r--r--MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/People/PersonMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/People/TvdbPersonImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Studios/StudioMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs2
-rw-r--r--MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Users/UserMetadataService.cs2
52 files changed, 1145 insertions, 1535 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 203e6dc43..b3bf0d2b6 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -21,9 +21,6 @@ namespace MediaBrowser.Controller.Entities.Audio
Tags = new List<string>();
}
- public string LastFmImageUrl { get; set; }
- public string LastFmImageSize { get; set; }
-
/// <summary>
/// Gets or sets the tags.
/// </summary>
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index ee8bb2761..b05f14a13 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -146,11 +146,13 @@
<Compile Include="Providers\IDynamicInfoProvider.cs" />
<Compile Include="Providers\IHasMetadata.cs" />
<Compile Include="Providers\IImageProvider.cs" />
+ <Compile Include="Providers\ILocalMetadataProvider.cs" />
<Compile Include="Providers\IProviderRepository.cs" />
<Compile Include="Providers\IRemoteImageProvider.cs" />
<Compile Include="Providers\ILocalImageProvider.cs" />
<Compile Include="Providers\IMetadataProvider.cs" />
<Compile Include="Providers\IMetadataService.cs" />
+ <Compile Include="Providers\IRemoteMetadataProvider.cs" />
<Compile Include="Providers\ItemId.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" />
diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs
index 61f5579f4..1e5bdfeaf 100644
--- a/MediaBrowser.Controller/Providers/IImageProvider.cs
+++ b/MediaBrowser.Controller/Providers/IImageProvider.cs
@@ -19,11 +19,5 @@ namespace MediaBrowser.Controller.Providers
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
bool Supports(IHasImages item);
-
- /// <summary>
- /// Gets the order.
- /// </summary>
- /// <value>The order.</value>
- int Order { get; }
}
}
diff --git a/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs b/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs
new file mode 100644
index 000000000..62b208b59
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs
@@ -0,0 +1,27 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public interface ILocalMetadataProvider : IMetadataProvider
+ {
+ /// <summary>
+ /// Determines whether [has local metadata] [the specified item].
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns><c>true</c> if [has local metadata] [the specified item]; otherwise, <c>false</c>.</returns>
+ bool HasLocalMetadata(IHasMetadata item);
+ }
+
+ public interface ILocalMetadataProvider<TItemType> : IMetadataProvider<TItemType>, ILocalMetadataProvider
+ where TItemType : IHasMetadata
+ {
+ /// <summary>
+ /// Gets the metadata.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{MetadataResult{`0}}.</returns>
+ Task<MetadataResult<TItemType>> GetMetadata(string path, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
index 843ba263b..123e806ed 100644
--- a/MediaBrowser.Controller/Providers/IMetadataProvider.cs
+++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
@@ -1,6 +1,4 @@
using System;
-using System.Threading;
-using System.Threading.Tasks;
namespace MediaBrowser.Controller.Providers
{
@@ -20,32 +18,6 @@ namespace MediaBrowser.Controller.Providers
where TItemType : IHasMetadata
{
}
-
- public interface ILocalMetadataProvider : IMetadataProvider
- {
- /// <summary>
- /// Determines whether [has local metadata] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns><c>true</c> if [has local metadata] [the specified item]; otherwise, <c>false</c>.</returns>
- bool HasLocalMetadata(IHasMetadata item);
- }
-
- public interface IRemoteMetadataProvider : IMetadataProvider
- {
- }
-
- public interface IRemoteMetadataProvider<TItemType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
- where TItemType : IHasMetadata
- {
- Task<MetadataResult<TItemType>> GetMetadata(ItemId id, CancellationToken cancellationToken);
- }
-
- public interface ILocalMetadataProvider<TItemType> : IMetadataProvider<TItemType>, ILocalMetadataProvider
- where TItemType : IHasMetadata
- {
- Task<MetadataResult<TItemType>> GetMetadata(string path, CancellationToken cancellationToken);
- }
public interface IHasChangeMonitor
{
@@ -58,6 +30,11 @@ namespace MediaBrowser.Controller.Providers
bool HasChanged(IHasMetadata item, DateTime date);
}
+ public interface IHasOrder
+ {
+ int Order { get; }
+ }
+
public class MetadataResult<T>
where T : IHasMetadata
{
diff --git a/MediaBrowser.Controller/Providers/IMetadataService.cs b/MediaBrowser.Controller/Providers/IMetadataService.cs
index c6cc2b716..e9ce320ab 100644
--- a/MediaBrowser.Controller/Providers/IMetadataService.cs
+++ b/MediaBrowser.Controller/Providers/IMetadataService.cs
@@ -10,8 +10,7 @@ namespace MediaBrowser.Controller.Providers
/// Adds the parts.
/// </summary>
/// <param name="providers">The providers.</param>
- /// <param name="imageProviders">The image providers.</param>
- void AddParts(IEnumerable<IMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders);
+ void AddParts(IEnumerable<IMetadataProvider> providers);
/// <summary>
/// Determines whether this instance can refresh the specified item.
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index dc57552c4..0159f778f 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -74,13 +74,13 @@ namespace MediaBrowser.Controller.Providers
/// <param name="providerName">Name of the provider.</param>
/// <param name="type">The type.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, CancellationToken cancellationToken, string providerName = null, ImageType? type = null);
+ Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasImages item, CancellationToken cancellationToken, string providerName = null, ImageType? type = null);
/// <summary>
/// Gets the image providers.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>IEnumerable{ImageProviderInfo}.</returns>
- IEnumerable<ImageProviderInfo> GetImageProviderInfo(BaseItem item);
+ IEnumerable<ImageProviderInfo> GetImageProviderInfo(IHasImages item);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs
new file mode 100644
index 000000000..6007a5af6
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs
@@ -0,0 +1,21 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public interface IRemoteMetadataProvider : IMetadataProvider
+ {
+ }
+
+ public interface IRemoteMetadataProvider<TItemType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
+ where TItemType : IHasMetadata
+ {
+ /// <summary>
+ /// Gets the metadata.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{MetadataResult{`0}}.</returns>
+ Task<MetadataResult<TItemType>> GetMetadata(ItemId id, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/ItemId.cs b/MediaBrowser.Controller/Providers/ItemId.cs
index b3fe5bee5..3abb64bfb 100644
--- a/MediaBrowser.Controller/Providers/ItemId.cs
+++ b/MediaBrowser.Controller/Providers/ItemId.cs
@@ -37,4 +37,18 @@ namespace MediaBrowser.Controller.Providers
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
+
+ public class AlbumId : ItemId
+ {
+ /// <summary>
+ /// Gets or sets the album artist.
+ /// </summary>
+ /// <value>The album artist.</value>
+ public string AlbumArtist { get; set; }
+ /// <summary>
+ /// Gets or sets the artist music brainz identifier.
+ /// </summary>
+ /// <value>The artist music brainz identifier.</value>
+ public string ArtistMusicBrainzId { get; set; }
+ }
}
diff --git a/MediaBrowser.Providers/All/LocalImageProvider.cs b/MediaBrowser.Providers/All/LocalImageProvider.cs
index 88a68bc15..089cfe549 100644
--- a/MediaBrowser.Providers/All/LocalImageProvider.cs
+++ b/MediaBrowser.Providers/All/LocalImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
@@ -38,13 +39,14 @@ namespace MediaBrowser.Providers.All
if (locationType == LocationType.FileSystem)
{
// Episode has it's own provider
- if (item is Episode)
+ if (item is Episode || item is Audio)
{
return false;
}
return true;
}
+
if (locationType == LocationType.Virtual)
{
var season = item as Season;
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index b9b4e40d7..53ab3614d 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.BoxSets
{
- public class BoxSetMetadataService : ConcreteMetadataService<BoxSet>
+ public class BoxSetMetadataService : ConcreteMetadataService<BoxSet, ItemId>
{
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _iLocalizationManager;
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
index 2e75a66cb..b7672a6a7 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.BoxSets
{
- class MovieDbBoxSetImageProvider : IRemoteImageProvider
+ class MovieDbBoxSetImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IHttpClient _httpClient;
diff --git a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
index 94209c309..1eefb0798 100644
--- a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
+++ b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.GameGenres
{
- public class GameGenreMetadataService : ConcreteMetadataService<GameGenre>
+ public class GameGenreMetadataService : ConcreteMetadataService<GameGenre, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/Genres/GenreMetadataService.cs b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
index 21addc390..fa4a4c955 100644
--- a/MediaBrowser.Providers/Genres/GenreMetadataService.cs
+++ b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Genres
{
- public class GenreMetadataService : ConcreteMetadataService<Genre>
+ public class GenreMetadataService : ConcreteMetadataService<Genre, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
index 067894337..5c476c89d 100644
--- a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.LiveTv
{
- public class ChannelMetadataService : ConcreteMetadataService<LiveTvChannel>
+ public class ChannelMetadataService : ConcreteMetadataService<LiveTvChannel, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
index 6f08b199a..0a22daf2f 100644
--- a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.LiveTv
{
- public class ProgramMetadataService : ConcreteMetadataService<LiveTvProgram>
+ public class ProgramMetadataService : ConcreteMetadataService<LiveTvProgram, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs b/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs
index 3a4bc06ca..f3644581e 100644
--- a/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs
+++ b/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs
@@ -4,8 +4,9 @@ using MediaBrowser.Model.Logging;
namespace MediaBrowser.Providers.Manager
{
- public abstract class ConcreteMetadataService<TItemType> : MetadataService<TItemType>
- where TItemType : IHasMetadata, new()
+ public abstract class ConcreteMetadataService<TItemType, TIdType> : MetadataService<TItemType, TIdType>
+ where TItemType : IHasMetadata, new()
+ where TIdType : ItemId, new()
{
protected ConcreteMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo)
: base(serverConfigurationManager, logger, providerManager, providerRepo)
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index e8bae1d2f..7f0dc8b89 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Common.Extensions;
+using System.IO;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -21,6 +23,7 @@ namespace MediaBrowser.Providers.Manager
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
public ItemImageProvider(ILogger logger, IProviderManager providerManager, IServerConfigurationManager config)
{
@@ -97,9 +100,21 @@ namespace MediaBrowser.Providers.Manager
if (response.HasImage)
{
- var mimeType = "image/" + response.Format.ToString().ToLower();
+ if (!string.IsNullOrEmpty(response.Path))
+ {
+ var mimeType = "image/" + Path.GetExtension(response.Path).TrimStart('.').ToLower();
- await _providerManager.SaveImage((BaseItem)item, response.Stream, mimeType, imageType, null, Guid.NewGuid().ToString(), cancellationToken).ConfigureAwait(false);
+ var stream = _fileSystem.GetFileStream(response.Path, FileMode.Open, FileAccess.Read,
+ FileShare.Read, true);
+
+ await _providerManager.SaveImage((BaseItem)item, stream, mimeType, imageType, null, Guid.NewGuid().ToString(), cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ var mimeType = "image/" + response.Format.ToString().ToLower();
+
+ await _providerManager.SaveImage((BaseItem)item, response.Stream, mimeType, imageType, null, Guid.NewGuid().ToString(), cancellationToken).ConfigureAwait(false);
+ }
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
}
@@ -227,26 +242,14 @@ namespace MediaBrowser.Providers.Manager
/// <returns>IEnumerable{IImageProvider}.</returns>
private IEnumerable<IImageProvider> GetImageProviders(IHasImages item, IEnumerable<IImageProvider> imageProviders)
{
- var providers = imageProviders.Where(i =>
- {
- try
- {
- return i.Supports(item);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in ImageProvider.Supports", ex, i.Name);
-
- return false;
- }
- });
+ var providers = imageProviders;
if (!_config.Configuration.EnableInternetProviders)
{
providers = providers.Where(i => !(i is IRemoteImageProvider));
}
- return providers.OrderBy(i => i.Order);
+ return providers;
}
private bool MergeImages(IHasImages item, List<LocalImageInfo> images)
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index d8d9ee0ca..19f155a07 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -13,8 +12,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Manager
{
- public abstract class MetadataService<TItemType> : IMetadataService
+ public abstract class MetadataService<TItemType, TIdType> : IMetadataService
where TItemType : IHasMetadata
+ where TIdType : ItemId, new()
{
protected readonly IServerConfigurationManager ServerConfigurationManager;
protected readonly ILogger Logger;
@@ -23,8 +23,6 @@ namespace MediaBrowser.Providers.Manager
private IMetadataProvider<TItemType>[] _providers = { };
- private IImageProvider[] _imageProviders = { };
-
protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo)
{
ServerConfigurationManager = serverConfigurationManager;
@@ -37,13 +35,10 @@ namespace MediaBrowser.Providers.Manager
/// Adds the parts.
/// </summary>
/// <param name="providers">The providers.</param>
- /// <param name="imageProviders">The image providers.</param>
- public void AddParts(IEnumerable<IMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders)
+ public void AddParts(IEnumerable<IMetadataProvider> providers)
{
_providers = providers.OfType<IMetadataProvider<TItemType>>()
.ToArray();
-
- _imageProviders = imageProviders.OrderBy(i => i.Order).ToArray();
}
/// <summary>
@@ -79,11 +74,13 @@ namespace MediaBrowser.Providers.Manager
var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager);
var localImagesFailed = false;
+ var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item).ToList();
+
// Start by validating images
try
{
// Always validate images and check for new locally stored ones.
- if (itemImageProvider.ValidateImages(item, GetLocalImageProviders(item)))
+ if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>()))
{
updateType = updateType | ItemUpdateType.ImageUpdate;
}
@@ -114,7 +111,7 @@ namespace MediaBrowser.Providers.Manager
// Next run remote image providers, but only if local image providers didn't throw an exception
if (!localImagesFailed && options.ImageRefreshMode != ImageRefreshMode.ValidationOnly)
{
- var providers = GetNonLocalImageProviders(item, lastResult.DateLastImagesRefresh.HasValue, options).ToList();
+ var providers = GetNonLocalImageProviders(item, allImageProviders, lastResult.DateLastImagesRefresh.HasValue, options).ToList();
if (providers.Count > 0)
{
@@ -135,7 +132,7 @@ namespace MediaBrowser.Providers.Manager
{
if (string.IsNullOrEmpty(item.Name))
{
- throw new InvalidOperationException("Item has no name");
+ throw new InvalidOperationException(item.GetType().Name + " has no name: " + item.Path);
}
// Save to database
@@ -167,7 +164,7 @@ namespace MediaBrowser.Providers.Manager
protected virtual IEnumerable<IMetadataProvider> GetProviders(IHasMetadata item, bool hasRefreshedMetadata, MetadataRefreshOptions options)
{
// Get providers to refresh
- var providers = _providers.Where(i => CanRefresh(i, item)).ToList();
+ var providers = ((ProviderManager) ProviderManager).GetMetadataProviders<TItemType>(item).ToList();
// Run all if either of these flags are true
var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || !hasRefreshedMetadata;
@@ -193,22 +190,10 @@ namespace MediaBrowser.Providers.Manager
return providers;
}
- protected virtual IEnumerable<IImageProvider> GetNonLocalImageProviders(IHasMetadata item, bool hasRefreshedImages, ImageRefreshOptions options)
+ protected virtual IEnumerable<IImageProvider> GetNonLocalImageProviders(IHasMetadata item, IEnumerable<IImageProvider> allImageProviders, bool hasRefreshedImages, ImageRefreshOptions options)
{
// Get providers to refresh
- var providers = _imageProviders.Where(i =>
- {
- try
- {
- return !(i is ILocalImageProvider) && i.Supports(item);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error in ImageProvider.Supports", ex, i.Name);
-
- return false;
- }
- }).ToList();
+ var providers = allImageProviders.Where(i => !(i is ILocalImageProvider)).ToList();
// Run all if either of these flags are true
var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || !hasRefreshedImages;
@@ -226,33 +211,12 @@ namespace MediaBrowser.Providers.Manager
return providers;
}
-
- /// <summary>
- /// Determines whether this instance can refresh the specified provider.
- /// </summary>
- /// <param name="provider">The provider.</param>
- /// <param name="item">The item.</param>
- /// <returns><c>true</c> if this instance can refresh the specified provider; otherwise, <c>false</c>.</returns>
- protected bool CanRefresh(IMetadataProvider provider, IHasMetadata item)
- {
- if (!ServerConfigurationManager.Configuration.EnableInternetProviders && provider is IRemoteMetadataProvider)
- {
- return false;
- }
-
- if (item.LocationType != LocationType.FileSystem && provider is ILocalMetadataProvider)
- {
- return false;
- }
-
- return true;
- }
protected abstract Task SaveItem(TItemType item, ItemUpdateType reason, CancellationToken cancellationToken);
- protected virtual ItemId GetId(IHasMetadata item)
+ protected virtual TIdType GetId(TItemType item)
{
- return new ItemId
+ return new TIdType
{
MetadataCountryCode = item.GetPreferredMetadataCountryCode(),
MetadataLanguage = item.GetPreferredMetadataLanguage(),
@@ -371,23 +335,6 @@ namespace MediaBrowser.Providers.Manager
return 0;
}
}
-
- private IEnumerable<ILocalImageProvider> GetLocalImageProviders(IHasImages item)
- {
- return _imageProviders.OfType<ILocalImageProvider>().Where(i =>
- {
- try
- {
- return i.Supports(item);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error in ImageProvider.Supports", ex, i.Name);
-
- return false;
- }
- });
- }
}
public class RefreshResult
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 3696bd02f..77a9298ee 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -50,7 +50,6 @@ namespace MediaBrowser.Providers.Manager
/// <value>The metadata providers enumerable.</value>
private BaseMetadataProvider[] MetadataProviders { get; set; }
- private IRemoteImageProvider[] RemoteImageProviders { get; set; }
private IImageProvider[] ImageProviders { get; set; }
private readonly IFileSystem _fileSystem;
@@ -58,6 +57,7 @@ namespace MediaBrowser.Providers.Manager
private readonly IProviderRepository _providerRepo;
private IMetadataService[] _metadataServices = { };
+ private IMetadataProvider[] _metadataProviders = { };
/// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
@@ -89,16 +89,10 @@ namespace MediaBrowser.Providers.Manager
{
MetadataProviders = providers.OrderBy(e => e.Priority).ToArray();
- ImageProviders = imageProviders.OrderBy(i => i.Order).ToArray();
- RemoteImageProviders = ImageProviders.OfType<IRemoteImageProvider>().ToArray();
+ ImageProviders = imageProviders.ToArray();
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
-
- var providerList = metadataProviders.ToList();
- foreach (var service in _metadataServices)
- {
- service.AddParts(providerList, ImageProviders);
- }
+ _metadataProviders = metadataProviders.ToArray();
}
public Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken)
@@ -391,7 +385,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="providerName">Name of the provider.</param>
/// <param name="type">The type.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, CancellationToken cancellationToken, string providerName = null, ImageType? type = null)
+ public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasImages item, CancellationToken cancellationToken, string providerName = null, ImageType? type = null)
{
var providers = GetRemoteImageProviders(item);
@@ -418,7 +412,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="preferredLanguage">The preferred language.</param>
/// <param name="type">The type.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
- private async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken, IRemoteImageProvider i, string preferredLanguage, ImageType? type = null)
+ private async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken, IRemoteImageProvider i, string preferredLanguage, ImageType? type = null)
{
try
{
@@ -452,9 +446,23 @@ namespace MediaBrowser.Providers.Manager
return images;
}
- private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(BaseItem item)
+ /// <summary>
+ /// Gets the supported image providers.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>IEnumerable{IImageProvider}.</returns>
+ public IEnumerable<ImageProviderInfo> GetImageProviderInfo(IHasImages item)
+ {
+ return GetRemoteImageProviders(item).Select(i => new ImageProviderInfo
+ {
+ Name = i.Name,
+ Order = GetOrder(item, i)
+ });
+ }
+
+ public IEnumerable<IImageProvider> GetImageProviders(IHasImages item)
{
- return RemoteImageProviders.Where(i =>
+ return ImageProviders.Where(i =>
{
try
{
@@ -466,22 +474,77 @@ namespace MediaBrowser.Providers.Manager
return false;
}
- });
+ }).OrderBy(i => GetOrder(item, i));
+ }
+
+ public IEnumerable<IMetadataProvider<T>> GetMetadataProviders<T>(IHasMetadata item)
+ where T : IHasMetadata
+ {
+ return _metadataProviders.OfType<IMetadataProvider<T>>()
+ .Where(i => CanRefresh(i, item))
+ .OrderBy(i => GetOrder(item, i));
+ }
+
+ private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item)
+ {
+ return GetImageProviders(item).OfType<IRemoteImageProvider>();
}
/// <summary>
- /// Gets the supported image providers.
+ /// Determines whether this instance can refresh the specified provider.
/// </summary>
+ /// <param name="provider">The provider.</param>
/// <param name="item">The item.</param>
- /// <returns>IEnumerable{IImageProvider}.</returns>
- public IEnumerable<ImageProviderInfo> GetImageProviderInfo(BaseItem item)
+ /// <returns><c>true</c> if this instance can refresh the specified provider; otherwise, <c>false</c>.</returns>
+ protected bool CanRefresh(IMetadataProvider provider, IHasMetadata item)
{
- return GetRemoteImageProviders(item).Select(i => new ImageProviderInfo
+ if (!ConfigurationManager.Configuration.EnableInternetProviders && provider is IRemoteMetadataProvider)
{
- Name = i.Name,
- Order = i.Order
+ return false;
+ }
- });
+ if (item.LocationType != LocationType.FileSystem && provider is ILocalMetadataProvider)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Gets the order.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="provider">The provider.</param>
+ /// <returns>System.Int32.</returns>
+ private int GetOrder(IHasImages item, IImageProvider provider)
+ {
+ var hasOrder = provider as IHasOrder;
+
+ if (hasOrder == null)
+ {
+ return 0;
+ }
+
+ return hasOrder.Order;
+ }
+
+ /// <summary>
+ /// Gets the order.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="provider">The provider.</param>
+ /// <returns>System.Int32.</returns>
+ private int GetOrder(IHasMetadata item, IMetadataProvider provider)
+ {
+ var hasOrder = provider as IHasOrder;
+
+ if (hasOrder == null)
+ {
+ return 0;
+ }
+
+ return hasOrder.Order;
}
}
}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 83c628e23..512b11051 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -100,29 +100,26 @@
<Compile Include="Movies\ManualMovieDbImageProvider.cs" />
<Compile Include="Movies\ManualFanartMovieImageProvider.cs" />
<Compile Include="MusicGenres\MusicGenreMetadataService.cs" />
+ <Compile Include="Music\AlbumMetadataService.cs" />
<Compile Include="Music\ArtistMetadataService.cs" />
- <Compile Include="Music\LastFmArtistProvider.cs" />
+ <Compile Include="Music\LastfmArtistProvider.cs" />
<Compile Include="People\MovieDbPersonImageProvider.cs" />
<Compile Include="Movies\MovieUpdatesPrescanTask.cs" />
<Compile Include="Movies\MovieXmlParser.cs" />
- <Compile Include="Movies\FanArtMovieProvider.cs" />
- <Compile Include="Movies\FanArtMovieUpdatesPrescanTask.cs" />
+ <Compile Include="Movies\FanartMovieProvider.cs" />
+ <Compile Include="Movies\FanartMovieUpdatesPrescanTask.cs" />
<Compile Include="Movies\MovieDbImagesProvider.cs" />
<Compile Include="Movies\MovieDbProvider.cs" />
<Compile Include="Movies\MovieProviderFromXml.cs" />
<Compile Include="Movies\OpenMovieDatabaseProvider.cs" />
- <Compile Include="Music\AlbumInfoFromSongProvider.cs" />
- <Compile Include="Music\AlbumProviderFromXml.cs" />
+ <Compile Include="Music\AlbumXmlProvider.cs" />
<Compile Include="Music\ArtistXmlProvider.cs" />
- <Compile Include="Music\FanArtAlbumProvider.cs" />
- <Compile Include="Music\FanArtUpdatesPrescanTask.cs" />
+ <Compile Include="Music\FanartUpdatesPrescanTask.cs" />
<Compile Include="Music\LastfmAlbumProvider.cs" />
- <Compile Include="Music\LastFmImageProvider.cs" />
- <Compile Include="Music\LastfmBaseProvider.cs" />
<Compile Include="Music\LastfmHelper.cs" />
- <Compile Include="Music\ManualFanartAlbumProvider.cs" />
+ <Compile Include="Music\FanartAlbumProvider.cs" />
<Compile Include="Music\FanartArtistProvider.cs" />
- <Compile Include="Music\ManualLastFmImageProvider.cs" />
+ <Compile Include="Music\LastfmImageProvider.cs" />
<Compile Include="Music\MusicBrainzAlbumProvider.cs" />
<Compile Include="Music\MusicVideoXmlParser.cs" />
<Compile Include="Music\SoundtrackPostScanTask.cs" />
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
index 2cf403b09..f2cd2718a 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
@@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.Movies
/// <summary>
/// Class FanArtMovieProvider
/// </summary>
- class FanArtMovieProvider : BaseMetadataProvider
+ class FanartMovieProvider : BaseMetadataProvider
{
/// <summary>
/// Gets the HTTP client.
@@ -37,18 +37,18 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
private readonly IProviderManager _providerManager;
- internal static FanArtMovieProvider Current { get; private set; }
+ internal static FanartMovieProvider Current { get; private set; }
private readonly IFileSystem _fileSystem;
/// <summary>
- /// Initializes a new instance of the <see cref="FanArtMovieProvider" /> class.
+ /// Initializes a new instance of the <see cref="FanartMovieProvider" /> class.
/// </summary>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="providerManager">The provider manager.</param>
/// <exception cref="System.ArgumentNullException">httpClient</exception>
- public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
+ public FanartMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
index 88f478d1c..47948455b 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
@@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Movies
{
- class FanArtMovieUpdatesPrescanTask : ILibraryPostScanTask
+ class FanartMovieUpdatesPrescanTask : ILibraryPostScanTask
{
private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/";
@@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Movies
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public FanArtMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
+ public FanartMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
@@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.Movies
return;
}
- var path = FanArtMovieProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
+ var path = FanartMovieProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
Directory.CreateDirectory(path);
@@ -118,7 +118,7 @@ namespace MediaBrowser.Providers.Movies
return new List<string>();
}
- var updates = _jsonSerializer.DeserializeFromString<List<FanArtUpdatesPrescanTask.FanArtUpdate>>(json);
+ var updates = _jsonSerializer.DeserializeFromString<List<FanartUpdatesPrescanTask.FanArtUpdate>>(json);
var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
@@ -136,7 +136,7 @@ namespace MediaBrowser.Providers.Movies
{
_logger.Info("Updating movie " + id);
- await FanArtMovieProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false);
+ await FanartMovieProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
diff --git a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs
index c94339a7e..70aaec526 100644
--- a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs
@@ -20,7 +20,7 @@ using MediaBrowser.Providers.Music;
namespace MediaBrowser.Providers.Movies
{
- public class ManualFanartMovieImageProvider : IRemoteImageProvider, IHasChangeMonitor
+ public class ManualFanartMovieImageProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
@@ -86,9 +86,9 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(movieId))
{
- await FanArtMovieProvider.Current.EnsureMovieXml(movieId, cancellationToken).ConfigureAwait(false);
+ await FanartMovieProvider.Current.EnsureMovieXml(movieId, cancellationToken).ConfigureAwait(false);
- var xmlPath = FanArtMovieProvider.Current.GetFanartXmlPath(movieId);
+ var xmlPath = FanartMovieProvider.Current.GetFanartXmlPath(movieId);
try
{
@@ -344,7 +344,7 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(id))
{
// Process images
- var xmlPath = FanArtMovieProvider.Current.GetFanartXmlPath(id);
+ var xmlPath = FanartMovieProvider.Current.GetFanartXmlPath(id);
var fileInfo = new FileInfo(xmlPath);
diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
index 8c6e2d92e..bc4652e2c 100644
--- a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
@@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Movies
{
- class ManualMovieDbImageProvider : IRemoteImageProvider
+ class ManualMovieDbImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
diff --git a/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs b/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs
deleted file mode 100644
index 47799b8f3..000000000
--- a/MediaBrowser.Providers/Music/AlbumInfoFromSongProvider.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class AlbumInfoFromSongProvider : BaseMetadataProvider
- {
- public AlbumInfoFromSongProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
- : base(logManager, configurationManager)
- {
- }
-
- public override bool Supports(BaseItem item)
- {
- return item is MusicAlbum;
- }
-
- protected override bool RefreshOnVersionChange
- {
- get
- {
- return true;
- }
- }
-
- protected override string ProviderVersion
- {
- get
- {
- return "2";
- }
- }
-
- protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
- {
- // If song metadata has changed
- if (GetComparisonData((MusicAlbum)item) != providerInfo.FileStamp)
- {
- return true;
- }
-
- return base.NeedsRefreshInternal(item, providerInfo);
- }
- /// <summary>
- /// Gets the data.
- /// </summary>
- /// <param name="album">The album.</param>
- /// <returns>Guid.</returns>
- private Guid GetComparisonData(MusicAlbum album)
- {
- var songs = album.RecursiveChildren.OfType<Audio>().ToList();
-
- return GetComparisonData(songs);
- }
-
- private Guid GetComparisonData(List<Audio> songs)
- {
- var albumArtistNames = songs.Select(i => i.AlbumArtist)
- .Where(i => !string.IsNullOrEmpty(i))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- var studios = songs.SelectMany(i => i.Studios)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- var genres = songs.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- albumArtistNames.AddRange(studios);
- albumArtistNames.AddRange(genres);
-
- return string.Join(string.Empty, albumArtistNames.OrderBy(i => i).ToArray()).GetMD5();
- }
-
- public override Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
- {
- var album = (MusicAlbum)item;
-
- var songs = album.RecursiveChildren.OfType<Audio>().ToList();
-
- if (!item.LockedFields.Contains(MetadataFields.Name))
- {
- var name = songs.Select(i => i.Album).FirstOrDefault(i => !string.IsNullOrEmpty(i));
-
- if (!string.IsNullOrEmpty(name))
- {
- album.Name = name;
- }
- }
-
- if (!item.LockedFields.Contains(MetadataFields.Studios))
- {
- album.Studios = songs.SelectMany(i => i.Studios)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
-
- if (!item.LockedFields.Contains(MetadataFields.Genres))
- {
- album.Genres = songs.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
-
- album.AlbumArtist = songs
- .Select(i => i.AlbumArtist)
- .FirstOrDefault(i => !string.IsNullOrEmpty(i));
-
- album.Artists = songs.SelectMany(i => i.Artists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- var date = songs.Select(i => i.PremiereDate)
- .FirstOrDefault(i => i.HasValue);
-
- if (date.HasValue)
- {
- album.PremiereDate = date.Value;
- album.ProductionYear = date.Value.Year;
- }
- else
- {
- var year = songs.Select(i => i.ProductionYear ?? 1800).FirstOrDefault(i => i != 1800);
-
- if (year != 1800)
- {
- album.ProductionYear = year;
- }
- }
-
- providerInfo.FileStamp = GetComparisonData(songs);
-
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
- return TrueTaskResult;
- }
-
- public override MetadataProviderPriority Priority
- {
- get { return MetadataProviderPriority.Second; }
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
new file mode 100644
index 000000000..511fa0547
--- /dev/null
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -0,0 +1,188 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Providers.Manager;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class AlbumMetadataService : ConcreteMetadataService<MusicAlbum, AlbumId>
+ {
+ private readonly ILibraryManager _libraryManager;
+
+ public AlbumMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager)
+ : base(serverConfigurationManager, logger, providerManager, providerRepo)
+ {
+ _libraryManager = libraryManager;
+ }
+
+ /// <summary>
+ /// Merges the specified source.
+ /// </summary>
+ /// <param name="source">The source.</param>
+ /// <param name="target">The target.</param>
+ /// <param name="lockedFields">The locked fields.</param>
+ /// <param name="replaceData">if set to <c>true</c> [replace data].</param>
+ /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param>
+ protected override void MergeData(MusicAlbum source, MusicAlbum target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
+ {
+ ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ }
+
+ protected override Task SaveItem(MusicAlbum item, ItemUpdateType reason, CancellationToken cancellationToken)
+ {
+ return _libraryManager.UpdateItem(item, reason, cancellationToken);
+ }
+
+ protected override ItemUpdateType AfterMetadataRefresh(MusicAlbum item)
+ {
+ var updateType = base.AfterMetadataRefresh(item);
+
+ var songs = item.RecursiveChildren.OfType<Audio>().ToList();
+
+ if (!item.LockedFields.Contains(MetadataFields.Genres))
+ {
+ var currentList = item.Genres.ToList();
+
+ item.Genres = songs.SelectMany(i => i.Genres)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
+ {
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+ }
+
+ if (!item.LockedFields.Contains(MetadataFields.Studios))
+ {
+ var currentList = item.Studios.ToList();
+
+ item.Studios = songs.SelectMany(i => i.Studios)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ if (currentList.Count != item.Studios.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Studios.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
+ {
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+ }
+
+ if (!item.LockedFields.Contains(MetadataFields.Name))
+ {
+ var name = songs.Select(i => i.Album).FirstOrDefault(i => !string.IsNullOrEmpty(i));
+
+ if (!string.IsNullOrEmpty(name))
+ {
+ if (!string.Equals(item.Name, name, StringComparison.Ordinal))
+ {
+ item.Name = name;
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+ }
+ }
+
+ updateType = updateType | SetAlbumArtistFromSongs(item, songs);
+ updateType = updateType | SetArtistsFromSongs(item, songs);
+ updateType = updateType | SetDateFromSongs(item, songs);
+
+ return updateType;
+ }
+
+ protected override AlbumId GetId(MusicAlbum item)
+ {
+ var id = base.GetId(item);
+
+ id.AlbumArtist = item.AlbumArtist;
+
+ var artist = item.Parents.OfType<MusicArtist>().FirstOrDefault();
+
+ if (artist != null)
+ {
+ id.ArtistMusicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
+ id.AlbumArtist = id.AlbumArtist ?? artist.Name;
+ }
+
+ return id;
+ }
+
+ private ItemUpdateType SetAlbumArtistFromSongs(MusicAlbum item, IEnumerable<Audio> songs)
+ {
+ var updateType = ItemUpdateType.Unspecified;
+
+ var albumArtist = songs
+ .Select(i => i.AlbumArtist)
+ .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+
+ if (!string.IsNullOrEmpty(albumArtist))
+ {
+ if (!string.Equals(item.AlbumArtist, albumArtist, StringComparison.Ordinal))
+ {
+ item.AlbumArtist = albumArtist;
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+ }
+
+ return updateType;
+ }
+
+ private ItemUpdateType SetArtistsFromSongs(MusicAlbum item, IEnumerable<Audio> songs)
+ {
+ var updateType = ItemUpdateType.Unspecified;
+
+ var currentList = item.Artists.ToList();
+
+ item.Artists = songs.SelectMany(i => i.Artists)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ if (currentList.Count != item.Artists.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Artists.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
+ {
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+
+ return updateType;
+ }
+
+ private ItemUpdateType SetDateFromSongs(MusicAlbum item, List<Audio> songs)
+ {
+ var updateType = ItemUpdateType.Unspecified;
+
+ var date = songs.Select(i => i.PremiereDate)
+ .FirstOrDefault(i => i.HasValue);
+
+ var originalPremiereDate = item.PremiereDate;
+ var originalProductionYear = item.ProductionYear;
+
+ if (date.HasValue)
+ {
+ item.PremiereDate = date.Value;
+ item.ProductionYear = date.Value.Year;
+ }
+ else
+ {
+ var year = songs.Select(i => i.ProductionYear ?? 1800).FirstOrDefault(i => i != 1800);
+
+ if (year != 1800)
+ {
+ item.ProductionYear = year;
+ }
+ }
+
+ if ((originalPremiereDate ?? DateTime.MinValue) != (item.PremiereDate ?? DateTime.MinValue) ||
+ (originalProductionYear ?? -1) != (item.ProductionYear ?? -1))
+ {
+ updateType = updateType | ItemUpdateType.MetadataDownload;
+ }
+
+ return updateType;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs b/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs
deleted file mode 100644
index 32d45d1ae..000000000
--- a/MediaBrowser.Providers/Music/AlbumProviderFromXml.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- class AlbumProviderFromXml : BaseMetadataProvider
- {
- private readonly IFileSystem _fileSystem;
-
- public AlbumProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
- : base(logManager, configurationManager)
- {
- _fileSystem = fileSystem;
- }
-
- /// <summary>
- /// Supportses the specified item.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- public override bool Supports(BaseItem item)
- {
- return item is MusicAlbum && item.LocationType == LocationType.FileSystem;
- }
-
- /// <summary>
- /// Gets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public override MetadataProviderPriority Priority
- {
- get { return MetadataProviderPriority.First; }
- }
-
- private const string XmlFileName = "album.xml";
- protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo)
- {
- var xml = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName));
-
- if (xml == null)
- {
- return false;
- }
-
- return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved;
- }
-
- /// <summary>
- /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="force">if set to <c>true</c> [force].</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName));
-
- if (metadataFile != null)
- {
- var path = metadataFile.FullName;
-
- await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- new BaseItemXmlParser<MusicAlbum>(Logger).Fetch((MusicAlbum)item, path, cancellationToken);
- }
- finally
- {
- XmlParsingResourcePool.Release();
- }
-
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
- return true;
- }
-
- return false;
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/AlbumXmlProvider.cs b/MediaBrowser.Providers/Music/AlbumXmlProvider.cs
new file mode 100644
index 000000000..66095fb7f
--- /dev/null
+++ b/MediaBrowser.Providers/Music/AlbumXmlProvider.cs
@@ -0,0 +1,59 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.Music
+{
+ class AlbumXmlProvider : BaseXmlProvider, ILocalMetadataProvider<MusicAlbum>
+ {
+ private readonly ILogger _logger;
+
+ public AlbumXmlProvider(IFileSystem fileSystem, ILogger logger)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ }
+
+ public async Task<MetadataResult<MusicAlbum>> GetMetadata(string path, CancellationToken cancellationToken)
+ {
+ path = GetXmlPath(path);
+
+ var result = new MetadataResult<MusicAlbum>();
+
+ await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ try
+ {
+ var item = new MusicAlbum();
+
+ new BaseItemXmlParser<MusicAlbum>(_logger).Fetch(item, path, cancellationToken);
+ result.HasMetadata = true;
+ result.Item = item;
+ }
+ catch (FileNotFoundException)
+ {
+ result.HasMetadata = false;
+ }
+ finally
+ {
+ XmlParsingResourcePool.Release();
+ }
+
+ return result;
+ }
+
+ public string Name
+ {
+ get { return "Media Browser Xml"; }
+ }
+
+ protected override string GetXmlPath(string path)
+ {
+ return Path.Combine(path, "album.xml");
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index 31202feb2..1b598e596 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
- public class ArtistMetadataService : ConcreteMetadataService<MusicArtist>
+ public class ArtistMetadataService : ConcreteMetadataService<MusicArtist, ItemId>
{
private readonly ILibraryManager _libraryManager;
@@ -49,13 +49,13 @@ namespace MediaBrowser.Providers.Music
{
var songs = item.RecursiveChildren.OfType<Audio>().ToList();
- var currentGenres = item.Genres.ToList();
+ var currentList = item.Genres.ToList();
item.Genres = songs.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
- if (currentGenres.Count != item.Genres.Count || !currentGenres.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
+ if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
{
updateType = updateType | ItemUpdateType.MetadataDownload;
}
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index e2dde6c4f..cd87d213b 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -3,210 +3,373 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Net;
-using System.Net;
+using System.Xml;
namespace MediaBrowser.Providers.Music
{
- /// <summary>
- /// Class FanArtAlbumProvider
- /// </summary>
- public class FanArtAlbumProvider : BaseMetadataProvider
+ public class FanartAlbumProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder
{
- /// <summary>
- /// The _provider manager
- /// </summary>
- private readonly IProviderManager _providerManager;
-
- /// <summary>
- /// Gets the HTTP client.
- /// </summary>
- /// <value>The HTTP client.</value>
- protected IHttpClient HttpClient { get; private set; }
-
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ private readonly IServerConfigurationManager _config;
+ private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
- /// <summary>
- /// Initializes a new instance of the <see cref="FanArtAlbumProvider"/> class.
- /// </summary>
- /// <param name="httpClient">The HTTP client.</param>
- /// <param name="logManager">The log manager.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <param name="providerManager">The provider manager.</param>
- public FanArtAlbumProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
- : base(logManager, configurationManager)
+ public FanartAlbumProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
{
- _providerManager = providerManager;
+ _config = config;
+ _httpClient = httpClient;
_fileSystem = fileSystem;
- HttpClient = httpClient;
}
- /// <summary>
- /// Gets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public override MetadataProviderPriority Priority
+ public string Name
{
- get { return MetadataProviderPriority.Fifth; }
+ get { return ProviderName; }
}
- /// <summary>
- /// Supportses the specified item.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- public override bool Supports(BaseItem item)
+ public static string ProviderName
+ {
+ get { return "FanArt"; }
+ }
+
+ public bool Supports(IHasImages item)
{
return item is MusicAlbum;
}
- public override ItemUpdateType ItemUpdateType
+ public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
- get
+ return new List<ImageType>
{
- return ItemUpdateType.ImageUpdate;
- }
+ ImageType.Primary,
+ ImageType.Disc
+ };
}
-
- /// <summary>
- /// Gets a value indicating whether [refresh on version change].
- /// </summary>
- /// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value>
- protected override bool RefreshOnVersionChange
+
+ public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
{
- get
+ var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
+
+ return images.Where(i => i.Type == imageType);
+ }
+
+ public async Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
+ {
+ var album = (MusicAlbum)item;
+
+ var list = new List<RemoteImageInfo>();
+
+ var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
+
+ if (!string.IsNullOrEmpty(artistMusicBrainzId))
{
- return true;
+ await FanartArtistProvider.Current.EnsureMovieXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false);
+
+ var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
+
+ var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz);
+
+ try
+ {
+ AddImages(list, artistXmlPath, musicBrainzId, musicBrainzReleaseGroupId, cancellationToken);
+ }
+ catch (FileNotFoundException)
+ {
+
+ }
}
+
+ var language = item.GetPreferredMetadataLanguage();
+
+ var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
+
+ // Sort first by width to prioritize HD versions
+ return list.OrderByDescending(i => i.Width ?? 0)
+ .ThenByDescending(i =>
+ {
+ if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
+ {
+ return 3;
+ }
+ if (!isLanguageEn)
+ {
+ if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
+ {
+ return 2;
+ }
+ }
+ if (string.IsNullOrEmpty(i.Language))
+ {
+ return isLanguageEn ? 3 : 2;
+ }
+ return 0;
+ })
+ .ThenByDescending(i => i.CommunityRating ?? 0)
+ .ThenByDescending(i => i.VoteCount ?? 0);
}
/// <summary>
- /// Gets the provider version.
+ /// Adds the images.
/// </summary>
- /// <value>The provider version.</value>
- protected override string ProviderVersion
+ /// <param name="list">The list.</param>
+ /// <param name="xmlPath">The XML path.</param>
+ /// <param name="releaseId">The release identifier.</param>
+ /// <param name="releaseGroupId">The release group identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ private void AddImages(List<RemoteImageInfo> list, string xmlPath, string releaseId, string releaseGroupId, CancellationToken cancellationToken)
{
- get
+ using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
{
- return "18";
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
+ {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ }))
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "music":
+ {
+ using (var subReader = reader.ReadSubtree())
+ {
+ AddImagesFromMusicNode(list, releaseId, releaseGroupId, subReader, cancellationToken);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
}
}
/// <summary>
- /// Needses the refresh internal.
+ /// Adds the images from music node.
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="providerInfo">The provider info.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
+ /// <param name="list">The list.</param>
+ /// <param name="releaseId">The release identifier.</param>
+ /// <param name="releaseGroupId">The release group identifier.</param>
+ /// <param name="reader">The reader.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ private void AddImagesFromMusicNode(List<RemoteImageInfo> list, string releaseId, string releaseGroupId, XmlReader reader, CancellationToken cancellationToken)
{
- if (!ConfigurationManager.Configuration.DownloadMusicAlbumImages.Disc &&
- !ConfigurationManager.Configuration.DownloadMusicAlbumImages.Primary)
- {
- return false;
- }
+ reader.MoveToContent();
- if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Disc))
+ while (reader.Read())
{
- return false;
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "albums":
+ {
+ using (var subReader = reader.ReadSubtree())
+ {
+ AddImagesFromAlbumsNode(list, releaseId, releaseGroupId, subReader, cancellationToken);
+ }
+ break;
+ }
+ default:
+ {
+ using (reader.ReadSubtree())
+ {
+ }
+ break;
+ }
+ }
+ }
}
-
- return base.NeedsRefreshInternal(item, providerInfo);
}
- protected override DateTime CompareDate(BaseItem item)
+ /// <summary>
+ /// Adds the images from albums node.
+ /// </summary>
+ /// <param name="list">The list.</param>
+ /// <param name="releaseId">The release identifier.</param>
+ /// <param name="releaseGroupId">The release group identifier.</param>
+ /// <param name="reader">The reader.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ private void AddImagesFromAlbumsNode(List<RemoteImageInfo> list, string releaseId, string releaseGroupId, XmlReader reader, CancellationToken cancellationToken)
{
- var artistMusicBrainzId = item.Parent.GetProviderId(MetadataProviders.Musicbrainz);
+ reader.MoveToContent();
- if (!string.IsNullOrEmpty(artistMusicBrainzId))
+ while (reader.Read())
{
- var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(ConfigurationManager.CommonApplicationPaths, artistMusicBrainzId);
-
- var file = new FileInfo(artistXmlPath);
-
- if (file.Exists)
+ if (reader.NodeType == XmlNodeType.Element)
{
- return _fileSystem.GetLastWriteTimeUtc(file);
+ switch (reader.Name)
+ {
+ case "album":
+ {
+ var id = reader.GetAttribute("id");
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ if (string.Equals(id, releaseId, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(id, releaseGroupId, StringComparison.OrdinalIgnoreCase))
+ {
+ AddImages(list, subReader, cancellationToken);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ using (reader.ReadSubtree())
+ {
+ }
+ break;
+ }
+ }
}
- }
-
- return base.CompareDate(item);
+ }
}
/// <summary>
- /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
+ /// Adds the images.
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="force">if set to <c>true</c> [force].</param>
+ /// <param name="list">The list.</param>
+ /// <param name="reader">The reader.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
+ private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken)
{
- if (!item.LockedFields.Contains(MetadataFields.Images))
+ reader.MoveToContent();
+
+ while (reader.Read())
{
- var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualFanartAlbumProvider.ProviderName).ConfigureAwait(false);
- await FetchFromXml(item, images.ToList(), cancellationToken).ConfigureAwait(false);
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "cdart":
+ {
+ AddImage(list, reader, ImageType.Disc, 1000, 1000);
+ break;
+ }
+ case "albumcover":
+ {
+ AddImage(list, reader, ImageType.Primary, 1000, 1000);
+ break;
+ }
+ default:
+ {
+ using (reader.ReadSubtree())
+ {
+ }
+ break;
+ }
+ }
+ }
}
-
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
-
- return true;
}
/// <summary>
- /// Fetches from XML.
+ /// Adds the image.
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="images">The images.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- private async Task FetchFromXml(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken)
+ /// <param name="list">The list.</param>
+ /// <param name="reader">The reader.</param>
+ /// <param name="type">The type.</param>
+ /// <param name="width">The width.</param>
+ /// <param name="height">The height.</param>
+ private void AddImage(List<RemoteImageInfo> list, XmlReader reader, ImageType type, int width, int height)
{
- cancellationToken.ThrowIfCancellationRequested();
+ var url = reader.GetAttribute("url");
+
+ var size = reader.GetAttribute("size");
- if (ConfigurationManager.Configuration.DownloadMusicAlbumImages.Primary && !item.HasImage(ImageType.Primary))
+ if (!string.IsNullOrEmpty(size))
{
- await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false);
+ int sizeNum;
+ if (int.TryParse(size, NumberStyles.Any, _usCulture, out sizeNum))
+ {
+ width = sizeNum;
+ height = sizeNum;
+ }
}
- cancellationToken.ThrowIfCancellationRequested();
+ var likesString = reader.GetAttribute("likes");
+ int likes;
- if (ConfigurationManager.Configuration.DownloadMusicAlbumImages.Disc && !item.HasImage(ImageType.Disc))
+ var info = new RemoteImageInfo
{
- await SaveImage(item, images, ImageType.Disc, cancellationToken).ConfigureAwait(false);
+ RatingType = RatingType.Likes,
+ Type = type,
+ Width = width,
+ Height = height,
+ ProviderName = Name,
+ Url = url,
+ Language = reader.GetAttribute("lang")
+ };
+
+ if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
+ {
+ info.CommunityRating = likes;
}
+
+ list.Add(info);
}
- private async Task SaveImage(BaseItem item, List<RemoteImageInfo> images, ImageType type, CancellationToken cancellationToken)
+ public int Order
{
- foreach (var image in images.Where(i => i.Type == type))
+ get { return 0; }
+ }
+
+ public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClient.GetResponse(new HttpRequestOptions
{
- try
- {
- await _providerManager.SaveImage(item, image.Url, FanartArtistProvider.FanArtResourcePool, type, null, cancellationToken).ConfigureAwait(false);
- break;
- }
- catch (HttpException ex)
- {
- // Sometimes fanart has bad url's in their xml
- if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
- {
- continue;
- }
- break;
- }
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = FanartArtistProvider.FanArtResourcePool
+ });
+ }
+
+ public bool HasChanged(IHasMetadata item, DateTime date)
+ {
+ var album = (MusicAlbum)item;
+
+ var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
+
+ if (!String.IsNullOrEmpty(artistMusicBrainzId))
+ {
+ // Process images
+ var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
+
+ var fileInfo = new FileInfo(artistXmlPath);
+
+ return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
}
+
+ return false;
}
}
}
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index 35d27036d..2b4a814c5 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -20,7 +20,7 @@ using System.Xml;
namespace MediaBrowser.Providers.Music
{
- public class FanartArtistProvider : IRemoteImageProvider, IHasChangeMonitor
+ public class FanartArtistProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder
{
internal static readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(3, 3);
internal const string ApiKey = "5c6b04c68e904cfed1e6cbc9a9e683d4";
diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
index c3a879f8c..d002c02f2 100644
--- a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
@@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
- class FanArtUpdatesPrescanTask : ILibraryPostScanTask
+ class FanartUpdatesPrescanTask : ILibraryPostScanTask
{
private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmusic/{0}/{1}/";
@@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Music
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public FanArtUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
+ public FanartUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
diff --git a/MediaBrowser.Providers/Music/LastFmImageProvider.cs b/MediaBrowser.Providers/Music/LastFmImageProvider.cs
index 71278ce5c..659ae5bef 100644
--- a/MediaBrowser.Providers/Music/LastFmImageProvider.cs
+++ b/MediaBrowser.Providers/Music/LastFmImageProvider.cs
@@ -1,113 +1,165 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
- /// <summary>
- /// Class LastFmArtistImageProvider
- /// </summary>
- public class LastFmImageProvider : BaseMetadataProvider
+ public class LastfmImageProvider : IRemoteImageProvider, IHasOrder
{
- /// <summary>
- /// The _provider manager
- /// </summary>
- private readonly IProviderManager _providerManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LastFmImageProvider"/> class.
- /// </summary>
- /// <param name="logManager">The log manager.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <param name="providerManager">The provider manager.</param>
- public LastFmImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager) :
- base(logManager, configurationManager)
+ private readonly IHttpClient _httpClient;
+ private readonly IServerConfigurationManager _config;
+
+ public LastfmImageProvider(IHttpClient httpClient, IServerConfigurationManager config)
+ {
+ _httpClient = httpClient;
+ _config = config;
+ }
+
+ public string Name
+ {
+ get { return ProviderName; }
+ }
+
+ public static string ProviderName
{
- _providerManager = providerManager;
+ get { return "last.fm"; }
}
- /// <summary>
- /// Supportses the specified item.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- public override bool Supports(BaseItem item)
+ public bool Supports(IHasImages item)
{
- return item is MusicAlbum;
+ return item is MusicAlbum || item is MusicArtist;
}
- /// <summary>
- /// Needses the refresh internal.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="providerInfo">The provider info.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
+ public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
- if (item.HasImage(ImageType.Primary))
+ return new List<ImageType>
{
- return false;
- }
+ ImageType.Primary
+ };
+ }
+
+ public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
+ {
+ var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
- return base.NeedsRefreshInternal(item, providerInfo);
+ return images.Where(i => i.Type == imageType);
}
- /// <summary>
- /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="force">if set to <c>true</c> [force].</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
+ public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{
- if (!item.HasImage(ImageType.Primary))
+ var list = new List<RemoteImageInfo>();
+
+ RemoteImageInfo info = null;
+
+ var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz);
+
+ if (!string.IsNullOrEmpty(musicBrainzId))
{
- var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualLastFmImageProvider.ProviderName).ConfigureAwait(false);
+ var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
+
+ try
+ {
+ var parts = File.ReadAllText(cachePath).Split('|');
- await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false);
+ info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault());
+ }
+ catch (DirectoryNotFoundException)
+ {
+ }
+ catch (FileNotFoundException)
+ {
+ }
}
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
+ if (info == null)
+ {
+ var musicBrainzReleaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ if (!string.IsNullOrEmpty(musicBrainzReleaseGroupId))
+ {
+ var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzReleaseGroupId, "image.txt");
+
+ try
+ {
+ var parts = File.ReadAllText(cachePath).Split('|');
- return true;
+ info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault());
+ }
+ catch (DirectoryNotFoundException)
+ {
+ }
+ catch (FileNotFoundException)
+ {
+ }
+ }
+ }
+
+ if (info != null)
+ {
+ list.Add(info);
+ }
+
+ // The only info we have is size
+ return Task.FromResult<IEnumerable<RemoteImageInfo>>(list.OrderByDescending(i => i.Width ?? 0));
}
- private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken)
+ private RemoteImageInfo GetInfo(string url, string size)
{
- cancellationToken.ThrowIfCancellationRequested();
+ if (string.IsNullOrEmpty(url))
+ {
+ return null;
+ }
- var configSetting = item is MusicAlbum
- ? ConfigurationManager.Configuration.DownloadMusicAlbumImages
- : ConfigurationManager.Configuration.DownloadMusicArtistImages;
+ var info = new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Url = url,
+ Type = ImageType.Primary
+ };
- if (configSetting.Primary && !item.HasImage(ImageType.Primary) && !item.LockedFields.Contains(MetadataFields.Images))
+ if (string.Equals(size, "mega", StringComparison.OrdinalIgnoreCase))
+ {
+
+ }
+ else if (string.Equals(size, "extralarge", StringComparison.OrdinalIgnoreCase))
+ {
+
+ }
+ else if (string.Equals(size, "large", StringComparison.OrdinalIgnoreCase))
+ {
+
+ }
+ else if (string.Equals(size, "medium", StringComparison.OrdinalIgnoreCase))
{
- var image = images.FirstOrDefault(i => i.Type == ImageType.Primary);
- if (image != null)
- {
- await _providerManager.SaveImage(item, image.Url, LastFmArtistProvider.LastfmResourcePool, ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
- }
}
+
+ return info;
+ }
+
+ public int Order
+ {
+ get { return 1; }
}
- /// <summary>
- /// Gets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public override MetadataProviderPriority Priority
+ public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
- get { return MetadataProviderPriority.Fifth; }
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = LastfmArtistProvider.LastfmResourcePool
+ });
}
}
}
diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
index 5cfcf054d..f9d7d3018 100644
--- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
@@ -1,106 +1,51 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
-using MoreLinq;
using System;
+using System.Collections.Generic;
using System.IO;
-using System.Linq;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
- public class LastfmAlbumProvider : LastfmBaseProvider
+ public class LastfmAlbumProvider : IRemoteMetadataProvider<MusicAlbum>, IHasOrder
{
- internal static LastfmAlbumProvider Current;
+ private readonly IJsonSerializer _json;
+ private readonly IHttpClient _httpClient;
- public LastfmAlbumProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
- : base(jsonSerializer, httpClient, logManager, configurationManager)
- {
- Current = this;
- }
+ private readonly IServerConfigurationManager _config;
+ private readonly ILogger _logger;
- /// <summary>
- /// Gets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public override MetadataProviderPriority Priority
+ public LastfmAlbumProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger)
{
- get { return MetadataProviderPriority.Fourth; }
+ _httpClient = httpClient;
+ _json = json;
+ _config = config;
+ _logger = logger;
}
- protected override string ProviderVersion
+ public async Task<MetadataResult<MusicAlbum>> GetMetadata(ItemId id, CancellationToken cancellationToken)
{
- get
- {
- return "9";
- }
- }
+ var result = new MetadataResult<MusicAlbum>();
- private bool HasAltMeta(BaseItem item)
- {
- return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName("album.xml");
- }
-
- /// <summary>
- /// Needses the refresh internal.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="providerInfo">The provider info.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
- {
- var hasId = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz)) &&
- !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup));
+ var lastFmData = await GetAlbumResult((AlbumId)id, cancellationToken).ConfigureAwait(false);
- if (hasId && HasAltMeta(item))
+ if (lastFmData != null && lastFmData.album != null)
{
- return false;
+ result.HasMetadata = true;
+ ProcessAlbumData(result.Item, lastFmData.album);
}
- // If song metadata has changed and we don't have an mbid, refresh
- if (!hasId && GetComparisonData(item as MusicAlbum) != providerInfo.FileStamp)
- {
- return true;
- }
-
- return base.NeedsRefreshInternal(item, providerInfo);
+ return result;
}
- /// <summary>
- /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="force">if set to <c>true</c> [force].</param>
- /// <param name="cancellationToken">The cancellation token</param>
- /// <returns>Task{System.Boolean}.</returns>
- public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var album = (MusicAlbum)item;
-
- var result = await GetAlbumResult(album, cancellationToken).ConfigureAwait(false);
-
- if (result != null && result.album != null)
- {
- LastfmHelper.ProcessAlbumData(item, result.album);
- }
-
- providerInfo.FileStamp = GetComparisonData(album);
-
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
- return true;
- }
-
-
- private async Task<LastfmGetAlbumResult> GetAlbumResult(MusicAlbum item, CancellationToken cancellationToken)
+ private async Task<LastfmGetAlbumResult> GetAlbumResult(AlbumId item, CancellationToken cancellationToken)
{
// Try album release Id
if (!string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz)))
@@ -123,33 +68,37 @@ namespace MediaBrowser.Providers.Music
return result;
}
}
-
- // Get each song, distinct by the combination of AlbumArtist and Album
- var songs = item.RecursiveChildren.OfType<Audio>().DistinctBy(i => (i.AlbumArtist ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
- foreach (var song in songs.Where(song => !string.IsNullOrEmpty(song.Album) && !string.IsNullOrEmpty(song.AlbumArtist)))
- {
- var result = await GetAlbumResult(song.AlbumArtist, song.Album, cancellationToken).ConfigureAwait(false);
+ //// Get each song, distinct by the combination of AlbumArtist and Album
+ //var songs = item.RecursiveChildren.OfType<Audio>().DistinctBy(i => (i.AlbumArtist ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
- if (result != null && result.album != null)
- {
- return result;
- }
+ //foreach (var song in songs.Where(song => !string.IsNullOrEmpty(song.Album) && !string.IsNullOrEmpty(song.AlbumArtist)))
+ //{
+ // var result = await GetAlbumResult(song.AlbumArtist, song.Album, cancellationToken).ConfigureAwait(false);
+
+ // if (result != null && result.album != null)
+ // {
+ // return result;
+ // }
+ //}
+
+ if (string.IsNullOrEmpty(item.AlbumArtist))
+ {
+ return null;
}
- // Try the folder name
- return await GetAlbumResult(item.Parent.Name, item.Name, cancellationToken);
+ return await GetAlbumResult(item.AlbumArtist, item.Name, cancellationToken);
}
private async Task<LastfmGetAlbumResult> GetAlbumResult(string artist, string album, CancellationToken cancellationToken)
{
// Get albu info using artist and album name
- var url = LastFmArtistProvider.RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(artist), UrlEncode(album), LastFmArtistProvider.ApiKey);
+ var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(artist), UrlEncode(album), LastfmArtistProvider.ApiKey);
- using (var json = await HttpClient.Get(new HttpRequestOptions
+ using (var json = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = LastFmArtistProvider.LastfmResourcePool,
+ ResourcePool = LastfmArtistProvider.LastfmResourcePool,
CancellationToken = cancellationToken,
EnableHttpCompression = false
@@ -162,7 +111,7 @@ namespace MediaBrowser.Providers.Music
// Fix their bad json
jsonText = jsonText.Replace("\"#text\"", "\"url\"");
- return JsonSerializer.DeserializeFromString<LastfmGetAlbumResult>(jsonText);
+ return _json.DeserializeFromString<LastfmGetAlbumResult>(jsonText);
}
}
}
@@ -170,48 +119,180 @@ namespace MediaBrowser.Providers.Music
private async Task<LastfmGetAlbumResult> GetAlbumResult(string musicbraizId, CancellationToken cancellationToken)
{
// Get albu info using artist and album name
- var url = LastFmArtistProvider.RootUrl + string.Format("method=album.getInfo&mbid={0}&api_key={1}&format=json", musicbraizId, LastFmArtistProvider.ApiKey);
+ var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&mbid={0}&api_key={1}&format=json", musicbraizId, LastfmArtistProvider.ApiKey);
- using (var json = await HttpClient.Get(new HttpRequestOptions
+ using (var json = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = LastFmArtistProvider.LastfmResourcePool,
+ ResourcePool = LastfmArtistProvider.LastfmResourcePool,
CancellationToken = cancellationToken,
EnableHttpCompression = false
}).ConfigureAwait(false))
{
- return JsonSerializer.DeserializeFromStream<LastfmGetAlbumResult>(json);
+ return _json.DeserializeFromStream<LastfmGetAlbumResult>(json);
}
}
- public override bool Supports(BaseItem item)
+ private void ProcessAlbumData(MusicAlbum item, LastfmAlbum data)
{
- return item is MusicAlbum;
+ var overview = data.wiki != null ? data.wiki.content : null;
+
+ if (!item.LockedFields.Contains(MetadataFields.Overview))
+ {
+ item.Overview = overview;
+ }
+
+ // Only grab the date here if the album doesn't already have one, since id3 tags are preferred
+ DateTime release;
+
+ if (DateTime.TryParse(data.releasedate, out release))
+ {
+ // Lastfm sends back null as sometimes 1901, other times 0
+ if (release.Year > 1901)
+ {
+ if (!item.PremiereDate.HasValue)
+ {
+ item.PremiereDate = release;
+ }
+
+ if (!item.ProductionYear.HasValue)
+ {
+ item.ProductionYear = release.Year;
+ }
+ }
+ }
+
+ string imageSize;
+ var url = LastfmHelper.GetImageUrl(data, out imageSize);
+
+ var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz) ??
+ item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
}
/// <summary>
- /// Gets the data.
+ /// Encodes an URL.
/// </summary>
- /// <param name="album">The album.</param>
- /// <returns>Guid.</returns>
- private Guid GetComparisonData(MusicAlbum album)
+ /// <param name="name">The name.</param>
+ /// <returns>System.String.</returns>
+ private string UrlEncode(string name)
+ {
+ return WebUtility.UrlEncode(name);
+ }
+
+ public string Name
{
- var songs = album.RecursiveChildren.OfType<Audio>().ToList();
+ get { return "last.fm"; }
+ }
- var albumArtists = songs.Select(i => i.AlbumArtist)
- .Where(i => !string.IsNullOrEmpty(i))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
+ public int Order
+ {
+ get { return 1; }
+ }
+ }
- var albumNames = songs.Select(i => i.AlbumArtist)
- .Where(i => !string.IsNullOrEmpty(i))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
+ #region Result Objects
- albumArtists.AddRange(albumNames);
+ public class LastfmStats
+ {
+ public string listeners { get; set; }
+ public string playcount { get; set; }
+ }
- return string.Join(string.Empty, albumArtists.OrderBy(i => i).ToArray()).GetMD5();
- }
+ public class LastfmTag
+ {
+ public string name { get; set; }
+ public string url { get; set; }
}
+
+
+ public class LastfmTags
+ {
+ public List<LastfmTag> tag { get; set; }
+ }
+
+ public class LastfmFormationInfo
+ {
+ public string yearfrom { get; set; }
+ public string yearto { get; set; }
+ }
+
+ public class LastFmBio
+ {
+ public string published { get; set; }
+ public string summary { get; set; }
+ public string content { get; set; }
+ public string placeformed { get; set; }
+ public string yearformed { get; set; }
+ public List<LastfmFormationInfo> formationlist { get; set; }
+ }
+
+ public class LastFmImage
+ {
+ public string url { get; set; }
+ public string size { get; set; }
+ }
+
+ public class LastfmArtist : IHasLastFmImages
+ {
+ public string name { get; set; }
+ public string mbid { get; set; }
+ public string url { get; set; }
+ public string streamable { get; set; }
+ public string ontour { get; set; }
+ public LastfmStats stats { get; set; }
+ public List<LastfmArtist> similar { get; set; }
+ public LastfmTags tags { get; set; }
+ public LastFmBio bio { get; set; }
+ public List<LastFmImage> image { get; set; }
+ }
+
+
+ public class LastfmAlbum : IHasLastFmImages
+ {
+ public string name { get; set; }
+ public string artist { get; set; }
+ public string id { get; set; }
+ public string mbid { get; set; }
+ public string releasedate { get; set; }
+ public int listeners { get; set; }
+ public int playcount { get; set; }
+ public LastfmTags toptags { get; set; }
+ public LastFmBio wiki { get; set; }
+ public List<LastFmImage> image { get; set; }
+ }
+
+ public interface IHasLastFmImages
+ {
+ List<LastFmImage> image { get; set; }
+ }
+
+ public class LastfmGetAlbumResult
+ {
+ public LastfmAlbum album { get; set; }
+ }
+
+ public class LastfmGetArtistResult
+ {
+ public LastfmArtist artist { get; set; }
+ }
+
+ public class Artistmatches
+ {
+ public List<LastfmArtist> artist { get; set; }
+ }
+
+ public class LastfmArtistSearchResult
+ {
+ public Artistmatches artistmatches { get; set; }
+ }
+
+ public class LastfmArtistSearchResults
+ {
+ public LastfmArtistSearchResult results { get; set; }
+ }
+
+ #endregion
}
diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
index 488340cf6..2924180ff 100644
--- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
@@ -19,7 +19,7 @@ using System.Xml;
namespace MediaBrowser.Providers.Music
{
- public class LastFmArtistProvider : IRemoteMetadataProvider<MusicArtist>
+ public class LastfmArtistProvider : IRemoteMetadataProvider<MusicArtist>
{
private readonly IJsonSerializer _json;
private readonly IHttpClient _httpClient;
@@ -30,12 +30,14 @@ namespace MediaBrowser.Providers.Music
internal static string ApiKey = "7b76553c3eb1d341d642755aecc40a33";
private readonly IServerConfigurationManager _config;
- private ILogger _logger;
+ private readonly ILogger _logger;
- public LastFmArtistProvider(IHttpClient httpClient, IJsonSerializer json)
+ public LastfmArtistProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger)
{
_httpClient = httpClient;
_json = json;
+ _config = config;
+ _logger = logger;
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ItemId id, CancellationToken cancellationToken)
@@ -119,25 +121,7 @@ namespace MediaBrowser.Providers.Music
string imageSize;
var url = LastfmHelper.GetImageUrl(data, out imageSize);
- var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
-
- try
- {
- if (string.IsNullOrEmpty(url))
- {
- File.Delete(cachePath);
- }
- else
- {
- Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
- File.WriteAllText(cachePath, url + "|" + imageSize);
- }
- }
- catch (IOException ex)
- {
- // Don't fail if this is unable to write
- _logger.ErrorException("Error saving to {0}", ex, cachePath);
- }
+ LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
}
private async Task<string> FindId(ItemId item, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Music/LastfmBaseProvider.cs b/MediaBrowser.Providers/Music/LastfmBaseProvider.cs
deleted file mode 100644
index 7ff7bf407..000000000
--- a/MediaBrowser.Providers/Music/LastfmBaseProvider.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Threading;
-
-namespace MediaBrowser.Providers.Music
-{
- /// <summary>
- /// Class MovieDbProvider
- /// </summary>
- public abstract class LastfmBaseProvider : BaseMetadataProvider
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="LastfmBaseProvider" /> class.
- /// </summary>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="httpClient">The HTTP client.</param>
- /// <param name="logManager">The log manager.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
- protected LastfmBaseProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
- : base(logManager, configurationManager)
- {
- if (jsonSerializer == null)
- {
- throw new ArgumentNullException("jsonSerializer");
- }
- if (httpClient == null)
- {
- throw new ArgumentNullException("httpClient");
- }
- JsonSerializer = jsonSerializer;
- HttpClient = httpClient;
- }
-
- protected override string ProviderVersion
- {
- get
- {
- return "8";
- }
- }
-
- protected override bool RefreshOnVersionChange
- {
- get
- {
- return true;
- }
- }
-
- /// <summary>
- /// Gets the json serializer.
- /// </summary>
- /// <value>The json serializer.</value>
- protected IJsonSerializer JsonSerializer { get; private set; }
-
- /// <summary>
- /// Gets the HTTP client.
- /// </summary>
- /// <value>The HTTP client.</value>
- protected IHttpClient HttpClient { get; private set; }
-
- /// <summary>
- /// Gets a value indicating whether [requires internet].
- /// </summary>
- /// <value><c>true</c> if [requires internet]; otherwise, <c>false</c>.</value>
- public override bool RequiresInternet
- {
- get
- {
- return true;
- }
- }
-
- /// <summary>
- /// Encodes an URL.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <returns>System.String.</returns>
- protected static string UrlEncode(string name)
- {
- return WebUtility.UrlEncode(name);
- }
- }
-
- #region Result Objects
-
- public class LastfmStats
- {
- public string listeners { get; set; }
- public string playcount { get; set; }
- }
-
- public class LastfmTag
- {
- public string name { get; set; }
- public string url { get; set; }
- }
-
-
- public class LastfmTags
- {
- public List<LastfmTag> tag { get; set; }
- }
-
- public class LastfmFormationInfo
- {
- public string yearfrom { get; set; }
- public string yearto { get; set; }
- }
-
- public class LastFmBio
- {
- public string published { get; set; }
- public string summary { get; set; }
- public string content { get; set; }
- public string placeformed { get; set; }
- public string yearformed { get; set; }
- public List<LastfmFormationInfo> formationlist { get; set; }
- }
-
- public class LastFmImage
- {
- public string url { get; set; }
- public string size { get; set; }
- }
-
- public class LastfmArtist : IHasLastFmImages
- {
- public string name { get; set; }
- public string mbid { get; set; }
- public string url { get; set; }
- public string streamable { get; set; }
- public string ontour { get; set; }
- public LastfmStats stats { get; set; }
- public List<LastfmArtist> similar { get; set; }
- public LastfmTags tags { get; set; }
- public LastFmBio bio { get; set; }
- public List<LastFmImage> image { get; set; }
- }
-
-
- public class LastfmAlbum : IHasLastFmImages
- {
- public string name { get; set; }
- public string artist { get; set; }
- public string id { get; set; }
- public string mbid { get; set; }
- public string releasedate { get; set; }
- public int listeners { get; set; }
- public int playcount { get; set; }
- public LastfmTags toptags { get; set; }
- public LastFmBio wiki { get; set; }
- public List<LastFmImage> image { get; set; }
- }
-
- public interface IHasLastFmImages
- {
- List<LastFmImage> image { get; set; }
- }
-
- public class LastfmGetAlbumResult
- {
- public LastfmAlbum album { get; set; }
- }
-
- public class LastfmGetArtistResult
- {
- public LastfmArtist artist { get; set; }
- }
-
- public class Artistmatches
- {
- public List<LastfmArtist> artist { get; set; }
- }
-
- public class LastfmArtistSearchResult
- {
- public Artistmatches artistmatches { get; set; }
- }
-
- public class LastfmArtistSearchResults
- {
- public LastfmArtistSearchResult results { get; set; }
- }
-
- #endregion
-}
diff --git a/MediaBrowser.Providers/Music/LastfmHelper.cs b/MediaBrowser.Providers/Music/LastfmHelper.cs
index 0895d245c..0c67e7ea7 100644
--- a/MediaBrowser.Providers/Music/LastfmHelper.cs
+++ b/MediaBrowser.Providers/Music/LastfmHelper.cs
@@ -1,7 +1,7 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Logging;
using System;
+using System.IO;
using System.Linq;
namespace MediaBrowser.Providers.Music
@@ -37,41 +37,27 @@ namespace MediaBrowser.Providers.Music
return null;
}
- public static void ProcessAlbumData(BaseItem item, LastfmAlbum data)
+ public static void SaveImageInfo(IApplicationPaths appPaths, ILogger logger, string musicBrainzId, string url, string size)
{
- var overview = data.wiki != null ? data.wiki.content : null;
+ var cachePath = Path.Combine(appPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
- if (!item.LockedFields.Contains(MetadataFields.Overview))
+ try
{
- item.Overview = overview;
- }
-
- // Only grab the date here if the album doesn't already have one, since id3 tags are preferred
- DateTime release;
-
- if (DateTime.TryParse(data.releasedate, out release))
- {
- // Lastfm sends back null as sometimes 1901, other times 0
- if (release.Year > 1901)
+ if (string.IsNullOrEmpty(url))
{
- if (!item.PremiereDate.HasValue)
- {
- item.PremiereDate = release;
- }
-
- if (!item.ProductionYear.HasValue)
- {
- item.ProductionYear = release.Year;
- }
+ File.Delete(cachePath);
+ }
+ else
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
+ File.WriteAllText(cachePath, url + "|" + size);
}
}
-
- var album = (MusicAlbum)item;
-
- string imageSize;
-
- album.LastFmImageUrl = GetImageUrl(data, out imageSize);
- album.LastFmImageSize = imageSize;
+ catch (IOException ex)
+ {
+ // Don't fail if this is unable to write
+ logger.ErrorException("Error saving to {0}", ex, cachePath);
+ }
}
}
}
diff --git a/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs b/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs
deleted file mode 100644
index f1dda948f..000000000
--- a/MediaBrowser.Providers/Music/ManualFanartAlbumProvider.cs
+++ /dev/null
@@ -1,354 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml;
-
-namespace MediaBrowser.Providers.Music
-{
- public class ManualFanartAlbumProvider : IRemoteImageProvider
- {
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private readonly IServerConfigurationManager _config;
- private readonly IHttpClient _httpClient;
-
- public ManualFanartAlbumProvider(IServerConfigurationManager config, IHttpClient httpClient)
- {
- _config = config;
- _httpClient = httpClient;
- }
-
- public string Name
- {
- get { return ProviderName; }
- }
-
- public static string ProviderName
- {
- get { return "FanArt"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is MusicAlbum;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary,
- ImageType.Disc
- };
- }
-
- public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
- {
- var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
-
- return images.Where(i => i.Type == imageType);
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
- {
- var album = (MusicAlbum)item;
-
- var list = new List<RemoteImageInfo>();
-
- var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
-
- if (!string.IsNullOrEmpty(artistMusicBrainzId))
- {
- var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
-
- var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
-
- var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz);
-
- try
- {
- AddImages(list, artistXmlPath, musicBrainzId, musicBrainzReleaseGroupId, cancellationToken);
- }
- catch (FileNotFoundException)
- {
-
- }
- }
-
- var language = item.GetPreferredMetadataLanguage();
-
- var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
-
- // Sort first by width to prioritize HD versions
- list = list.OrderByDescending(i => i.Width ?? 0)
- .ThenByDescending(i =>
- {
- if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
- if (!isLanguageEn)
- {
- if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
- {
- return 2;
- }
- }
- if (string.IsNullOrEmpty(i.Language))
- {
- return isLanguageEn ? 3 : 2;
- }
- return 0;
- })
- .ThenByDescending(i => i.CommunityRating ?? 0)
- .ThenByDescending(i => i.VoteCount ?? 0)
- .ToList();
-
- return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
- }
-
- /// <summary>
- /// Adds the images.
- /// </summary>
- /// <param name="list">The list.</param>
- /// <param name="xmlPath">The XML path.</param>
- /// <param name="releaseId">The release identifier.</param>
- /// <param name="releaseGroupId">The release group identifier.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- private void AddImages(List<RemoteImageInfo> list, string xmlPath, string releaseId, string releaseGroupId, CancellationToken cancellationToken)
- {
- using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "music":
- {
- using (var subReader = reader.ReadSubtree())
- {
- AddImagesFromMusicNode(list, releaseId, releaseGroupId, subReader, cancellationToken);
- }
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Adds the images from music node.
- /// </summary>
- /// <param name="list">The list.</param>
- /// <param name="releaseId">The release identifier.</param>
- /// <param name="releaseGroupId">The release group identifier.</param>
- /// <param name="reader">The reader.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- private void AddImagesFromMusicNode(List<RemoteImageInfo> list, string releaseId, string releaseGroupId, XmlReader reader, CancellationToken cancellationToken)
- {
- reader.MoveToContent();
-
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "albums":
- {
- using (var subReader = reader.ReadSubtree())
- {
- AddImagesFromAlbumsNode(list, releaseId, releaseGroupId, subReader, cancellationToken);
- }
- break;
- }
- default:
- {
- using (reader.ReadSubtree())
- {
- }
- break;
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Adds the images from albums node.
- /// </summary>
- /// <param name="list">The list.</param>
- /// <param name="releaseId">The release identifier.</param>
- /// <param name="releaseGroupId">The release group identifier.</param>
- /// <param name="reader">The reader.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- private void AddImagesFromAlbumsNode(List<RemoteImageInfo> list, string releaseId, string releaseGroupId, XmlReader reader, CancellationToken cancellationToken)
- {
- reader.MoveToContent();
-
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "album":
- {
- var id = reader.GetAttribute("id");
-
- using (var subReader = reader.ReadSubtree())
- {
- if (string.Equals(id, releaseId, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(id, releaseGroupId, StringComparison.OrdinalIgnoreCase))
- {
- AddImages(list, subReader, cancellationToken);
- }
- }
- break;
- }
- default:
- {
- using (reader.ReadSubtree())
- {
- }
- break;
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Adds the images.
- /// </summary>
- /// <param name="list">The list.</param>
- /// <param name="reader">The reader.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken)
- {
- reader.MoveToContent();
-
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "cdart":
- {
- AddImage(list, reader, ImageType.Disc, 1000, 1000);
- break;
- }
- case "albumcover":
- {
- AddImage(list, reader, ImageType.Primary, 1000, 1000);
- break;
- }
- default:
- {
- using (reader.ReadSubtree())
- {
- }
- break;
- }
- }
- }
- }
- }
-
- /// <summary>
- /// Adds the image.
- /// </summary>
- /// <param name="list">The list.</param>
- /// <param name="reader">The reader.</param>
- /// <param name="type">The type.</param>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- private void AddImage(List<RemoteImageInfo> list, XmlReader reader, ImageType type, int width, int height)
- {
- var url = reader.GetAttribute("url");
-
- var size = reader.GetAttribute("size");
-
- if (!string.IsNullOrEmpty(size))
- {
- int sizeNum;
- if (int.TryParse(size, NumberStyles.Any, _usCulture, out sizeNum))
- {
- width = sizeNum;
- height = sizeNum;
- }
- }
-
- var likesString = reader.GetAttribute("likes");
- int likes;
-
- var info = new RemoteImageInfo
- {
- RatingType = RatingType.Likes,
- Type = type,
- Width = width,
- Height = height,
- ProviderName = Name,
- Url = url,
- Language = reader.GetAttribute("lang")
- };
-
- if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
- {
- info.CommunityRating = likes;
- }
-
- list.Add(info);
- }
-
- public int Order
- {
- get { return 0; }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanartArtistProvider.FanArtResourcePool
- });
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs b/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs
deleted file mode 100644
index b1e9fa9b3..000000000
--- a/MediaBrowser.Providers/Music/ManualLastFmImageProvider.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class ManualLastFmImageProvider : IRemoteImageProvider
- {
- private readonly IHttpClient _httpClient;
- private readonly IServerConfigurationManager _config;
-
- public ManualLastFmImageProvider(IHttpClient httpClient, IServerConfigurationManager config)
- {
- _httpClient = httpClient;
- _config = config;
- }
-
- public string Name
- {
- get { return ProviderName; }
- }
-
- public static string ProviderName
- {
- get { return "last.fm"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is MusicAlbum || item is MusicArtist;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary
- };
- }
-
- public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
- {
- var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
-
- return images.Where(i => i.Type == imageType);
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
- {
- var list = new List<RemoteImageInfo>();
-
- RemoteImageInfo info = null;
-
- var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz);
-
- var album = item as MusicAlbum;
- if (album != null)
- {
- info = GetInfo(album.LastFmImageUrl, album.LastFmImageSize);
- }
-
- var musicArtist = item as MusicArtist;
- if (musicArtist != null && !string.IsNullOrEmpty(musicBrainzId))
- {
- var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
-
- try
- {
- var parts = File.ReadAllText(cachePath).Split('|');
-
- info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault());
- }
- catch (DirectoryNotFoundException ex)
- {
- }
- catch (FileNotFoundException ex)
- {
- }
-
- }
-
- if (info != null)
- {
- list.Add(info);
- }
-
- // The only info we have is size
- return Task.FromResult<IEnumerable<RemoteImageInfo>>(list.OrderByDescending(i => i.Width ?? 0));
- }
-
- private RemoteImageInfo GetInfo(string url, string size)
- {
- if (string.IsNullOrEmpty(url))
- {
- return null;
- }
-
- var info = new RemoteImageInfo
- {
- ProviderName = Name,
- Url = url,
- Type = ImageType.Primary
- };
-
- if (string.Equals(size, "mega", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "extralarge", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "large", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "medium", StringComparison.OrdinalIgnoreCase))
- {
-
- }
-
- return info;
- }
-
- public int Order
- {
- get { return 1; }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = LastFmArtistProvider.LastfmResourcePool
- });
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
index 29edac6b0..3f7c0ce96 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
@@ -1,11 +1,8 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Net;
@@ -16,46 +13,46 @@ using System.Xml;
namespace MediaBrowser.Providers.Music
{
- public class MusicBrainzAlbumProvider : BaseMetadataProvider
+ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum>, IHasOrder
{
internal static MusicBrainzAlbumProvider Current;
private readonly IHttpClient _httpClient;
private readonly IApplicationHost _appHost;
- public MusicBrainzAlbumProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IHttpClient httpClient, IApplicationHost appHost)
- : base(logManager, configurationManager)
+ public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost)
{
_httpClient = httpClient;
_appHost = appHost;
-
Current = this;
}
- public override bool Supports(BaseItem item)
+ public async Task<MetadataResult<MusicAlbum>> GetMetadata(ItemId id, CancellationToken cancellationToken)
{
- return item is MusicAlbum;
- }
+ var albumId = (AlbumId)id;
+ var releaseId = albumId.GetProviderId(MetadataProviders.Musicbrainz);
+ var releaseGroupId = albumId.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
- public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken)
- {
- var releaseId = item.GetProviderId(MetadataProviders.Musicbrainz);
- var releaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+ var result = new MetadataResult<MusicAlbum>();
if (string.IsNullOrEmpty(releaseId))
{
- var result = await GetReleaseResult((MusicAlbum)item, cancellationToken).ConfigureAwait(false);
+ var releaseResult = await GetReleaseResult(albumId.ArtistMusicBrainzId, albumId.AlbumArtist, albumId.Name, cancellationToken).ConfigureAwait(false);
- if (!string.IsNullOrEmpty(result.ReleaseId))
+ result.Item = new MusicAlbum();
+
+ if (!string.IsNullOrEmpty(releaseResult.ReleaseId))
{
- releaseId = result.ReleaseId;
- item.SetProviderId(MetadataProviders.Musicbrainz, releaseId);
+ releaseId = releaseResult.ReleaseId;
+ result.HasMetadata = true;
+ result.Item.SetProviderId(MetadataProviders.Musicbrainz, releaseId);
}
- if (!string.IsNullOrEmpty(result.ReleaseGroupId))
+ if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId))
{
- releaseGroupId = result.ReleaseGroupId;
- item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
+ releaseGroupId = releaseResult.ReleaseGroupId;
+ result.HasMetadata = true;
+ result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
}
}
@@ -63,25 +60,26 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrEmpty(releaseId) && string.IsNullOrEmpty(releaseGroupId))
{
releaseGroupId = await GetReleaseGroupId(releaseId, cancellationToken).ConfigureAwait(false);
-
- item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
+ result.HasMetadata = true;
+ result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
}
- SetLastRefreshed(item, DateTime.UtcNow, providerInfo);
- return true;
+ return result;
}
- private Task<ReleaseResult> GetReleaseResult(MusicAlbum album, CancellationToken cancellationToken)
+ public string Name
{
- var artist = album.Parent;
- var artistId = artist.GetProviderId(MetadataProviders.Musicbrainz);
+ get { return "MusicBrainz"; }
+ }
- if (!string.IsNullOrEmpty(artistId))
+ private Task<ReleaseResult> GetReleaseResult(string artistMusicBrainId, string artistName, string albumName, CancellationToken cancellationToken)
+ {
+ if (!string.IsNullOrEmpty(artistMusicBrainId))
{
- return GetReleaseResult(album.Name, artistId, cancellationToken);
+ return GetReleaseResult(albumName, artistMusicBrainId, cancellationToken);
}
- return GetReleaseResultByArtistName(album.Name, artist.Name, cancellationToken);
+ return GetReleaseResultByArtistName(albumName, artistName, cancellationToken);
}
private async Task<ReleaseResult> GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken)
@@ -218,10 +216,9 @@ namespace MediaBrowser.Providers.Music
}
}
-
- public override MetadataProviderPriority Priority
+ public int Order
{
- get { return MetadataProviderPriority.Third; }
+ get { return 0; }
}
}
}
diff --git a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
index aba60e7ba..b252970cb 100644
--- a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
+++ b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.MusicGenres
{
- public class MusicGenreMetadataService : ConcreteMetadataService<MusicGenre>
+ public class MusicGenreMetadataService : ConcreteMetadataService<MusicGenre, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
index 2b4e43f3c..3f8278bda 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.People
{
- public class MovieDbPersonImageProvider : IRemoteImageProvider
+ public class MovieDbPersonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
diff --git a/MediaBrowser.Providers/People/PersonMetadataService.cs b/MediaBrowser.Providers/People/PersonMetadataService.cs
index fe17f67b1..f39ae68bd 100644
--- a/MediaBrowser.Providers/People/PersonMetadataService.cs
+++ b/MediaBrowser.Providers/People/PersonMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.People
{
- public class PersonMetadataService : ConcreteMetadataService<Person>
+ public class PersonMetadataService : ConcreteMetadataService<Person, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
index aa4b9e0d8..769f07788 100644
--- a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
@@ -18,7 +18,7 @@ using System.Xml;
namespace MediaBrowser.Providers.People
{
- public class TvdbPersonImageProvider : IRemoteImageProvider
+ public class TvdbPersonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _library;
diff --git a/MediaBrowser.Providers/Studios/StudioMetadataService.cs b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
index f27a5c3b0..78ef1b51c 100644
--- a/MediaBrowser.Providers/Studios/StudioMetadataService.cs
+++ b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Studios
{
- public class StudioMetadataService : ConcreteMetadataService<Studio>
+ public class StudioMetadataService : ConcreteMetadataService<Studio, ItemId>
{
private readonly ILibraryManager _libraryManager;
diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
index 0c5b3fabc..6b005c9dc 100644
--- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
@@ -127,7 +127,7 @@ namespace MediaBrowser.Providers.TV
var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
- var updates = _jsonSerializer.DeserializeFromString<List<FanArtUpdatesPrescanTask.FanArtUpdate>>(json);
+ var updates = _jsonSerializer.DeserializeFromString<List<FanartUpdatesPrescanTask.FanArtUpdate>>(json);
return updates.Select(i => i.id).Where(existingDictionary.ContainsKey);
}
diff --git a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs
index 6fdd7d094..c7b2f595b 100644
--- a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs
@@ -19,7 +19,7 @@ using MediaBrowser.Providers.Music;
namespace MediaBrowser.Providers.TV
{
- public class ManualFanartSeasonImageProvider : IRemoteImageProvider
+ public class ManualFanartSeasonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs
index f7e19a6c1..9e492d8ea 100644
--- a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs
@@ -19,7 +19,7 @@ using MediaBrowser.Providers.Music;
namespace MediaBrowser.Providers.TV
{
- public class ManualFanartSeriesImageProvider : IRemoteImageProvider
+ public class ManualFanartSeriesImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs
index f672942db..458482bf6 100644
--- a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs
@@ -19,7 +19,7 @@ using System.Xml;
namespace MediaBrowser.Providers.TV
{
- public class ManualTvdbSeasonImageProvider : IRemoteImageProvider
+ public class ManualTvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs
index a1c7114fc..0cc2d8899 100644
--- a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs
@@ -19,7 +19,7 @@ using System.Xml;
namespace MediaBrowser.Providers.TV
{
- public class ManualTvdbSeriesImageProvider : IRemoteImageProvider
+ public class ManualTvdbSeriesImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
diff --git a/MediaBrowser.Providers/Users/UserMetadataService.cs b/MediaBrowser.Providers/Users/UserMetadataService.cs
index f2b2da087..3a7abd79b 100644
--- a/MediaBrowser.Providers/Users/UserMetadataService.cs
+++ b/MediaBrowser.Providers/Users/UserMetadataService.cs
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Users
{
- public class UserMetadataService : ConcreteMetadataService<User>
+ public class UserMetadataService : ConcreteMetadataService<User, ItemId>
{
private readonly IUserManager _userManager;