diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs
index 0c75e7edcf..75d318057e 100644
--- a/MediaBrowser.Controller/Library/IMetadataSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs
@@ -22,13 +22,6 @@ namespace MediaBrowser.Controller.Library
/// true if [is enabled for] [the specified item]; otherwise, false.
bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType);
- ///
- /// Gets the save path.
- ///
- /// The item.
- /// System.String.
- string GetSavePath(IHasMetadata item);
-
///
/// Saves the specified item.
///
@@ -37,4 +30,14 @@ namespace MediaBrowser.Controller.Library
/// Task.
void Save(IHasMetadata item, CancellationToken cancellationToken);
}
+
+ public interface IMetadataFileSaver : IMetadataSaver
+ {
+ ///
+ /// Gets the save path.
+ ///
+ /// The item.
+ /// System.String.
+ string GetSavePath(IHasMetadata item);
+ }
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index b4f228a1d9..1eb17d75d2 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -582,7 +583,15 @@ namespace MediaBrowser.Providers.Manager
list.Add(GetPluginSummary());
list.Add(GetPluginSummary());
list.Add(GetPluginSummary());
-
+
+ list.Add(GetPluginSummary());
+ list.Add(GetPluginSummary());
+
+ list.Add(GetPluginSummary());
+ list.Add(GetPluginSummary());
+ list.Add(GetPluginSummary());
+ list.Add(GetPluginSummary());
+
return list;
}
@@ -672,33 +681,49 @@ namespace MediaBrowser.Providers.Manager
/// Task.
public async Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType)
{
- var locationType = item.LocationType;
- if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
- {
- throw new ArgumentException("Only file-system based items can save metadata.");
- }
-
foreach (var saver in _savers.Where(i => i.IsEnabledFor(item, updateType)))
{
- var path = saver.GetSavePath(item);
+ var fileSaver = saver as IMetadataFileSaver;
- var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1));
+ if (fileSaver != null)
+ {
+ var locationType = item.LocationType;
+ if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
+ {
+ throw new ArgumentException("Only file-system based items can save metadata.");
+ }
- await semaphore.WaitAsync().ConfigureAwait(false);
+ var path = fileSaver.GetSavePath(item);
- try
- {
- _libraryMonitor.ReportFileSystemChangeBeginning(path);
- saver.Save(item, CancellationToken.None);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in metadata saver", ex);
+ var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1));
+
+ await semaphore.WaitAsync().ConfigureAwait(false);
+
+ try
+ {
+ _libraryMonitor.ReportFileSystemChangeBeginning(path);
+ saver.Save(item, CancellationToken.None);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in metadata saver", ex);
+ }
+ finally
+ {
+ _libraryMonitor.ReportFileSystemChangeComplete(path, false);
+ semaphore.Release();
+ }
}
- finally
+ else
{
- _libraryMonitor.ReportFileSystemChangeComplete(path, false);
- semaphore.Release();
+ try
+ {
+ saver.Save(item, CancellationToken.None);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in metadata saver", ex);
+ }
}
}
}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 1838b85566..9170e7268c 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -105,6 +105,7 @@
+
diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
index 2924180ffe..2ae329c452 100644
--- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
@@ -5,7 +5,6 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using System;
using System.Globalization;
@@ -15,11 +14,10 @@ using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using System.Xml;
namespace MediaBrowser.Providers.Music
{
- public class LastfmArtistProvider : IRemoteMetadataProvider
+ public class LastfmArtistProvider : IRemoteMetadataProvider, IHasOrder
{
private readonly IJsonSerializer _json;
private readonly IHttpClient _httpClient;
@@ -44,7 +42,7 @@ namespace MediaBrowser.Providers.Music
{
var result = new MetadataResult();
- var musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(id, cancellationToken).ConfigureAwait(false);
+ var musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz);
if (!String.IsNullOrWhiteSpace(musicBrainzId))
{
@@ -123,69 +121,6 @@ namespace MediaBrowser.Providers.Music
LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
}
-
- private async Task FindId(ItemId item, CancellationToken cancellationToken)
- {
- try
- {
- // If we don't get anything, go directly to music brainz
- return await FindIdFromMusicBrainz(item, cancellationToken).ConfigureAwait(false);
- }
- catch (HttpException e)
- {
- if (e.StatusCode.HasValue && e.StatusCode.Value == HttpStatusCode.BadRequest)
- {
- // They didn't like a character in the name. Handle the exception so that the provider doesn't keep retrying over and over
- return null;
- }
-
- throw;
- }
- }
-
- ///
- /// Finds the id from music brainz.
- ///
- /// The item.
- /// The cancellation token.
- /// Task{System.String}.
- private async Task FindIdFromMusicBrainz(ItemId item, CancellationToken cancellationToken)
- {
- // They seem to throw bad request failures on any term with a slash
- var nameToSearch = item.Name.Replace('/', ' ');
-
- var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
-
- var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-
- var ns = new XmlNamespaceManager(doc.NameTable);
- ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#");
- var node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns);
-
- if (node != null && node.Value != null)
- {
- return node.Value;
- }
-
- if (HasDiacritics(item.Name))
- {
- // Try again using the search with accent characters url
- url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
-
- doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-
- ns = new XmlNamespaceManager(doc.NameTable);
- ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#");
- node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns);
-
- if (node != null && node.Value != null)
- {
- return node.Value;
- }
- }
-
- return null;
- }
///
/// Determines whether the specified text has diacritics.
@@ -225,5 +160,10 @@ namespace MediaBrowser.Providers.Music
{
get { return "last.fm"; }
}
+
+ public int Order
+ {
+ get { return 1; }
+ }
}
}
diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
new file mode 100644
index 0000000000..4cc408a00f
--- /dev/null
+++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
@@ -0,0 +1,119 @@
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace MediaBrowser.Providers.Music
+{
+ public class MusicBrainzArtistProvider : IRemoteMetadataProvider
+ {
+ public async Task> GetMetadata(ItemId id, CancellationToken cancellationToken)
+ {
+ var result = new MetadataResult();
+
+ var musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(id, cancellationToken).ConfigureAwait(false);
+
+ if (!string.IsNullOrWhiteSpace(musicBrainzId))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ result.Item = new MusicArtist();
+ result.HasMetadata = true;
+
+ result.Item.SetProviderId(MetadataProviders.Musicbrainz, musicBrainzId);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Finds the id from music brainz.
+ ///
+ /// The item.
+ /// The cancellation token.
+ /// Task{System.String}.
+ private async Task FindId(ItemId item, CancellationToken cancellationToken)
+ {
+ // They seem to throw bad request failures on any term with a slash
+ var nameToSearch = item.Name.Replace('/', ' ');
+
+ var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
+
+ var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+
+ var ns = new XmlNamespaceManager(doc.NameTable);
+ ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#");
+ var node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns);
+
+ if (node != null && node.Value != null)
+ {
+ return node.Value;
+ }
+
+ if (HasDiacritics(item.Name))
+ {
+ // Try again using the search with accent characters url
+ url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
+
+ doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+
+ ns = new XmlNamespaceManager(doc.NameTable);
+ ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#");
+ node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns);
+
+ if (node != null && node.Value != null)
+ {
+ return node.Value;
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Determines whether the specified text has diacritics.
+ ///
+ /// The text.
+ /// true if the specified text has diacritics; otherwise, false.
+ private bool HasDiacritics(string text)
+ {
+ return !String.Equals(text, RemoveDiacritics(text), StringComparison.Ordinal);
+ }
+
+ ///
+ /// Removes the diacritics.
+ ///
+ /// The text.
+ /// System.String.
+ private string RemoveDiacritics(string text)
+ {
+ return String.Concat(
+ text.Normalize(NormalizationForm.FormD)
+ .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
+ UnicodeCategory.NonSpacingMark)
+ ).Normalize(NormalizationForm.FormC);
+ }
+
+ ///
+ /// Encodes an URL.
+ ///
+ /// The name.
+ /// System.String.
+ private string UrlEncode(string name)
+ {
+ return WebUtility.UrlEncode(name);
+ }
+
+ public string Name
+ {
+ get { return "MusicBrainz"; }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs
index 7eb56e40bc..34f91ba284 100644
--- a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs
@@ -9,7 +9,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- class AlbumXmlSaver : IMetadataSaver
+ class AlbumXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs
index efaa967512..5c40f3b388 100644
--- a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs
@@ -12,7 +12,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- class ArtistXmlSaver : IMetadataSaver
+ class ArtistXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs
index 078b1feba5..35c53115d0 100644
--- a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs
@@ -10,7 +10,7 @@ using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Providers.Savers
{
- public class BoxSetXmlSaver : IMetadataSaver
+ public class BoxSetXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs
index ed9a9bd6dd..3d8cbb4151 100644
--- a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Providers.Savers
///
/// Class PersonXmlSaver
///
- public class ChannelXmlSaver : IMetadataSaver
+ public class ChannelXmlSaver : IMetadataFileSaver
{
///
/// Determines whether [is enabled for] [the specified item].
diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs
index a0e3097185..c1f6bb7de4 100644
--- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs
@@ -12,7 +12,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- public class EpisodeXmlSaver : IMetadataSaver
+ public class EpisodeXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
private readonly IItemRepository _itemRepository;
diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs
index 6d384e410d..fe8eec3a59 100644
--- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs
@@ -12,7 +12,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- public class FolderXmlSaver : IMetadataSaver
+ public class FolderXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs
index d0d2ffcd0e..38af319236 100644
--- a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs
@@ -10,7 +10,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- public class GameSystemXmlSaver : IMetadataSaver
+ public class GameSystemXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.Providers/Savers/GameXmlSaver.cs
index 4e3f948a3c..b9abb37733 100644
--- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/GameXmlSaver.cs
@@ -15,7 +15,7 @@ namespace MediaBrowser.Providers.Savers
///
/// Saves game.xml for games
///
- public class GameXmlSaver : IMetadataSaver
+ public class GameXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
index f65c8f5df1..2c19cb628a 100644
--- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
@@ -17,7 +17,7 @@ namespace MediaBrowser.Providers.Savers
///
/// Saves movie.xml for movies, trailers and music videos
///
- public class MovieXmlSaver : IMetadataSaver
+ public class MovieXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
private readonly IItemRepository _itemRepository;
diff --git a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs
index 676f2dae05..12703aa3c5 100644
--- a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs
@@ -12,7 +12,7 @@ namespace MediaBrowser.Providers.Savers
///
/// Class PersonXmlSaver
///
- public class PersonXmlSaver : IMetadataSaver
+ public class PersonXmlSaver : IMetadataFileSaver
{
public string Name
{
diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs
index 52f310f0f7..6c4d3fb19a 100644
--- a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs
@@ -9,7 +9,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- public class SeasonXmlSaver : IMetadataSaver
+ public class SeasonXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;
diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs
index d472c2da25..21019fa0ed 100644
--- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs
@@ -11,7 +11,7 @@ using System.Threading;
namespace MediaBrowser.Providers.Savers
{
- public class SeriesXmlSaver : IMetadataSaver
+ public class SeriesXmlSaver : IMetadataFileSaver
{
private readonly IServerConfigurationManager _config;