fixes #222 - Music providers not downloading art.

This commit is contained in:
Luke Pulverenti 2013-05-02 18:32:15 -04:00
parent 9105b065e7
commit 19a95edf58
13 changed files with 221 additions and 32 deletions

View File

@ -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);
}

View File

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

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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
{

View File

@ -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;

View File

@ -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";

View File

@ -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>

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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();