Преглед изворни кода

fixes #222 - Music providers not downloading art.

Luke Pulverenti пре 12 година
родитељ
комит
19a95edf58

+ 0 - 1
MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -97,7 +97,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
                 };
 
                 client = new HttpClient(handler);
-                client.DefaultRequestHeaders.Add("Accept", "application/json,image/*");
                 client.Timeout = TimeSpan.FromSeconds(30);
                 _httpClients.TryAdd(host, client);
             }

+ 0 - 1
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -6,6 +6,5 @@ namespace MediaBrowser.Controller.Entities.Audio
     /// </summary>
     public class MusicArtist : Folder
     {
-
     }
 }

+ 5 - 9
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -35,6 +35,8 @@ namespace MediaBrowser.Controller.Entities
             ScreenshotImagePaths = new List<string>();
             BackdropImagePaths = new List<string>();
             ProductionLocations = new List<string>();
+            Images = new Dictionary<ImageType, string>();
+            ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         }
 
         /// <summary>
@@ -977,10 +979,10 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         public virtual void ClearMetaValues()
         {
-            Images = null;
+            Images.Clear();
             ForcedSortName = null;
             PremiereDate = null;
-            BackdropImagePaths = null;
+            BackdropImagePaths.Clear();
             OfficialRating = null;
             CustomRating = null;
             Overview = null;
@@ -992,7 +994,7 @@ namespace MediaBrowser.Controller.Entities
             RunTimeTicks = null;
             AspectRatio = null;
             ProductionYear = null;
-            ProviderIds = null;
+            ProviderIds.Clear();
             DisplayMediaType = GetType().Name;
             ResolveArgs = null;
         }
@@ -1465,12 +1467,6 @@ namespace MediaBrowser.Controller.Entities
             }
             else
             {
-                // Ensure it exists
-                if (Images == null)
-                {
-                    Images = new Dictionary<ImageType, string>();
-                }
-
                 Images[typeKey] = path;
             }
         }

+ 2 - 3
MediaBrowser.Controller/Providers/BaseProviderInfo.cs

@@ -28,10 +28,9 @@ namespace MediaBrowser.Controller.Providers
         /// <value>The provider version.</value>
         public string ProviderVersion { get; set; }
         /// <summary>
-        /// Gets or sets the custom data.
+        /// Contains a has of data that can be used to determine if the provider should refresh again
         /// </summary>
-        /// <value>The custom data.</value>
-        public string CustomData { get; set; }
+        public Guid Data { get; set; }
     }
 
     /// <summary>

+ 4 - 5
MediaBrowser.Controller/Providers/FanartBaseProvider.cs

@@ -1,9 +1,8 @@
-using System.Threading;
-using MediaBrowser.Controller.Configuration;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Entities;
-using System;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Threading;
 
 namespace MediaBrowser.Controller.Providers
 {

+ 4 - 3
MediaBrowser.Controller/Providers/ImagesByNameProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.Logging;
@@ -52,7 +53,7 @@ namespace MediaBrowser.Controller.Providers
         protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
         {
             // Force a refresh if the IBN path changed
-            if (!string.Equals(providerInfo.CustomData, ConfigurationManager.ApplicationPaths.ItemsByNamePath, StringComparison.OrdinalIgnoreCase))
+            if (providerInfo.Data != ConfigurationManager.ApplicationPaths.ItemsByNamePath.GetMD5())
             {
                 return true;
             }
@@ -120,7 +121,7 @@ namespace MediaBrowser.Controller.Providers
 
             if (item.ProviderData.TryGetValue(Id, out data))
             {
-                data.CustomData = ConfigurationManager.ApplicationPaths.ItemsByNamePath;
+                data.Data = ConfigurationManager.ApplicationPaths.ItemsByNamePath.GetMD5();
             }
 
             return result;

+ 1 - 1
MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs

@@ -253,7 +253,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
         };
 
-        public const string LOCAL_META_FILE_NAME = "mbmovie.js";
+        public const string LOCAL_META_FILE_NAME = "mbmovie.json";
         public const string ALT_META_FILE_NAME = "movie.xml";
         protected string ItemType = "movie";
 

+ 14 - 3
MediaBrowser.Controller/Providers/Movies/RottenTomatoesMovieProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
@@ -114,7 +115,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             }
 
             // Refresh if imdb id has changed
-            if (!string.Equals(item.GetProviderId(MetadataProviders.Imdb), providerInfo.CustomData))
+            if (providerInfo.Data != GetComparisonData(item.GetProviderId(MetadataProviders.Imdb)))
             {
                 return true;
             }
@@ -144,7 +145,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             if (item.ProviderData.TryGetValue(Id, out data))
             {
-                data.CustomData = item.GetProviderId(MetadataProviders.Imdb);
+                data.Data = GetComparisonData(item.GetProviderId(MetadataProviders.Imdb));
             }
 
             SetLastRefreshed(item, DateTime.UtcNow);
@@ -152,6 +153,16 @@ namespace MediaBrowser.Controller.Providers.Movies
             return Task.FromResult(true);
         }
 
+        /// <summary>
+        /// Gets the comparison data.
+        /// </summary>
+        /// <param name="imdbId">The imdb id.</param>
+        /// <returns>Guid.</returns>
+        private Guid GetComparisonData(string imdbId)
+        {
+            return string.IsNullOrEmpty(imdbId) ? Guid.Empty : imdbId.GetMD5();
+        }
+
         /// <summary>
         /// Gets the priority.
         /// </summary>

+ 1 - 1
MediaBrowser.Controller/Providers/Movies/TmdbPersonProvider.cs

@@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         /// <summary>
         /// The meta file name
         /// </summary>
-        protected const string MetaFileName = "mbperson.js";
+        protected const string MetaFileName = "mbperson.json";
 
         protected readonly IProviderManager ProviderManager;
         

+ 117 - 2
MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs

@@ -7,18 +7,41 @@ using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
 using System;
 using System.IO;
+using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Xml;
 
 namespace MediaBrowser.Controller.Providers.Music
 {
+    /// <summary>
+    /// Class FanArtAlbumProvider
+    /// </summary>
     public class FanArtAlbumProvider : FanartBaseProvider
     {
+        /// <summary>
+        /// The _provider manager
+        /// </summary>
         private readonly IProviderManager _providerManager;
 
+        /// <summary>
+        /// The _music brainz resource pool
+        /// </summary>
+        private readonly SemaphoreSlim _musicBrainzResourcePool = new SemaphoreSlim(1, 1);
+
+        /// <summary>
+        /// Gets the HTTP client.
+        /// </summary>
+        /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
 
+        /// <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)
             : base(logManager, configurationManager)
         {
@@ -26,11 +49,20 @@ namespace MediaBrowser.Controller.Providers.Music
             HttpClient = httpClient;
         }
 
+        /// <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;
         }
 
+        /// <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
         {
             get
@@ -39,11 +71,15 @@ namespace MediaBrowser.Controller.Providers.Music
             }
         }
 
+        /// <summary>
+        /// Gets the provider version.
+        /// </summary>
+        /// <value>The provider version.</value>
         protected override string ProviderVersion
         {
             get
             {
-                return "20130501.5";
+                return "11";
             }
         }
 
@@ -69,11 +105,27 @@ namespace MediaBrowser.Controller.Providers.Music
             return base.NeedsRefreshInternal(item, providerInfo);
         }
 
+        /// <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, CancellationToken cancellationToken)
         {
             cancellationToken.ThrowIfCancellationRequested();
 
-            var url = string.Format("http://api.fanart.tv/webservice/album/{0}/{1}/xml/all/1/1", APIKey, item.GetProviderId(MetadataProviders.Musicbrainz));
+            var releaseGroupId = await GetReleaseGroupId(item.GetProviderId(MetadataProviders.Musicbrainz), cancellationToken).ConfigureAwait(false);
+
+            if (string.IsNullOrEmpty(releaseGroupId))
+            {
+                SetLastRefreshed(item, DateTime.UtcNow);
+
+                return true;
+            }
+
+            var url = string.Format("http://api.fanart.tv/webservice/album/{0}/{1}/xml/all/1/1", APIKey, releaseGroupId);
 
             var doc = new XmlDocument();
 
@@ -143,5 +195,68 @@ namespace MediaBrowser.Controller.Providers.Music
 
             return true;
         }
+
+        /// <summary>
+        /// The _last music brainz request
+        /// </summary>
+        private DateTime _lastMusicBrainzRequest = DateTime.MinValue;
+
+        /// <summary>
+        /// Gets the release group id.
+        /// </summary>
+        /// <param name="releaseEntryId">The release entry id.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{System.String}.</returns>
+        private async Task<string> GetReleaseGroupId(string releaseEntryId, CancellationToken cancellationToken)
+        {
+            await _musicBrainzResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+            try
+            {
+                var diff = 1000 - (DateTime.Now - _lastMusicBrainzRequest).TotalMilliseconds;
+
+                // MusicBrainz is extremely adamant about limiting to one request per second
+
+                if (diff > 0)
+                {
+                    await Task.Delay(Convert.ToInt32(diff), cancellationToken).ConfigureAwait(false);
+                }
+
+                _lastMusicBrainzRequest = DateTime.Now;
+
+                return await GetReleaseGroupIdInternal(releaseEntryId, cancellationToken).ConfigureAwait(false);
+            }
+            finally
+            {
+                _musicBrainzResourcePool.Release();
+            }
+        }
+
+        /// <summary>
+        /// Gets the release group id internal.
+        /// </summary>
+        /// <param name="releaseEntryId">The release entry id.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{System.String}.</returns>
+        private async Task<string> GetReleaseGroupIdInternal(string releaseEntryId, CancellationToken cancellationToken)
+        {
+            var url = string.Format("http://www.musicbrainz.org/ws/2/release-group/?query=reid:{0}", releaseEntryId);
+
+            var doc = new XmlDocument();
+
+            using (var xml = await HttpClient.Get(url, cancellationToken).ConfigureAwait(false))
+            {
+                using (var oReader = new StreamReader(xml, Encoding.UTF8))
+                {
+                    doc.Load(oReader);
+                } 
+            }
+
+            var ns = new XmlNamespaceManager(doc.NameTable);
+            ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#");
+            var node = doc.SelectSingleNode("//mb:release-group-list/mb:release-group/@id", ns);
+
+            return node != null ? node.Value : null;
+        }
     }
 }

+ 16 - 0
MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs

@@ -58,6 +58,22 @@ namespace MediaBrowser.Controller.Providers.Music
             get { return ConfigurationManager.Configuration.SaveLocalMeta; }
         }
 
+        protected override bool RefreshOnVersionChange
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        protected override string ProviderVersion
+        {
+            get
+            {
+                return "1";
+            }
+        }
+
         /// <summary>
         /// Needses the refresh internal.
         /// </summary>

+ 52 - 1
MediaBrowser.Controller/Providers/Music/LastfmAlbumProvider.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MoreLinq;
@@ -32,6 +34,24 @@ namespace MediaBrowser.Controller.Providers.Music
             return BlankId;
         }
 
+        /// <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)
+        {
+            // If song metadata has changed and we don't have an mbid, refresh
+            if (string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz)) &&
+                GetComparisonData(item as MusicAlbum) != providerInfo.Data)
+            {
+                return true;
+            }
+
+            return base.NeedsRefreshInternal(item, providerInfo);
+        }
+
         protected override async Task FetchLastfmData(BaseItem item, string id, CancellationToken cancellationToken)
         {
             var result = await GetAlbumResult(item, cancellationToken).ConfigureAwait(false);
@@ -51,6 +71,13 @@ namespace MediaBrowser.Controller.Providers.Music
                     
                 }
             }
+
+            BaseProviderInfo data;
+
+            if (item.ProviderData.TryGetValue(Id, out data))
+            {
+                data.Data = GetComparisonData(item as MusicAlbum);
+            }
         }
 
         private async Task<LastfmGetAlbumResult> GetAlbumResult(BaseItem item, CancellationToken cancellationToken)
@@ -102,5 +129,29 @@ namespace MediaBrowser.Controller.Providers.Music
                 return true;
             }
         }
+
+        /// <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();
+
+            var albumArtists = songs.Select(i => i.AlbumArtist)
+                .Where(i => !string.IsNullOrEmpty(i))
+                .Distinct(StringComparer.OrdinalIgnoreCase)
+                .ToList();
+
+            var albumNames = songs.Select(i => i.AlbumArtist)
+                .Where(i => !string.IsNullOrEmpty(i))
+                .Distinct(StringComparer.OrdinalIgnoreCase)
+                .ToList();
+
+            albumArtists.AddRange(albumNames);
+
+            return string.Join(string.Empty, albumArtists.OrderBy(i => i).ToArray()).GetMD5();
+        }
     }
 }

+ 5 - 2
MediaBrowser.Server.Implementations/Providers/ProviderManager.cs

@@ -129,10 +129,13 @@ namespace MediaBrowser.Server.Implementations.Providers
             var providersChanged = false;
 
             item.ProviderData.TryGetValue(_supportedProvidersKey, out supportedProvidersInfo);
+
+            var supportedProvidersHash = supportedProvidersValue.GetMD5();
+
             if (supportedProvidersInfo != null)
             {
                 // Force refresh if the supported providers have changed
-                providersChanged = force = force || !string.Equals(supportedProvidersInfo.CustomData, supportedProvidersValue);
+                providersChanged = force = force || supportedProvidersHash != supportedProvidersInfo.Data;
 
                 // If providers have changed, clear provider info and update the supported providers hash
                 if (providersChanged)
@@ -144,7 +147,7 @@ namespace MediaBrowser.Server.Implementations.Providers
 
             if (providersChanged)
             {
-                supportedProvidersInfo.CustomData = supportedProvidersValue;
+                supportedProvidersInfo.Data = supportedProvidersHash;
             }
 
             if (force) item.ClearMetaValues();