add audio db for artists

pull/702/head
Luke Pulverenti 11 years ago
parent 41b9ce56ef
commit aac392f4cd

@ -320,6 +320,10 @@ namespace MediaBrowser.Api.Images
return ToStaticFileResult(contentPath);
}
}
catch (DirectoryNotFoundException)
{
// Means the file isn't cached yet
}
catch (FileNotFoundException)
{
// Means the file isn't cached yet
@ -356,7 +360,6 @@ namespace MediaBrowser.Api.Images
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
@ -365,6 +368,7 @@ namespace MediaBrowser.Api.Images
}
}
Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
using (var writer = new StreamWriter(pointerCachePath))
{
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);

@ -111,13 +111,15 @@ namespace MediaBrowser.Api
.OfType<MusicArtist>()
.ToList();
var musicArtistRefreshTasks = musicArtists.Select(i => i.ValidateChildren(new Progress<double>(), cancellationToken, true, request.Forced));
var options = GetRefreshOptions(request);
var musicArtistRefreshTasks = musicArtists.Select(i => i.ValidateChildren(new Progress<double>(), cancellationToken, options, true));
await Task.WhenAll(musicArtistRefreshTasks).ConfigureAwait(false);
try
{
await item.RefreshMetadata(GetRefreshOptions(request), CancellationToken.None).ConfigureAwait(false);
await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@ -250,9 +252,11 @@ namespace MediaBrowser.Api
{
var item = _dtoService.GetItemByDtoId(request.Id);
var options = GetRefreshOptions(request);
try
{
await item.RefreshMetadata(GetRefreshOptions(request), CancellationToken.None).ConfigureAwait(false);
await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false);
if (item.IsFolder)
{
@ -267,7 +271,7 @@ namespace MediaBrowser.Api
{
var folder = (Folder)item;
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, options, request.Recursive).ConfigureAwait(false);
}
}
}
@ -295,7 +299,7 @@ namespace MediaBrowser.Api
{
var folder = (Folder)child;
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, options, request.Recursive).ConfigureAwait(false);
}
}
}

@ -299,26 +299,24 @@ namespace MediaBrowser.Controller.Entities
/// <value>The current validation cancellation token source.</value>
private CancellationTokenSource CurrentValidationCancellationTokenSource { get; set; }
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken)
{
return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions());
}
/// <summary>
/// Validates that the children of the folder still exist
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="metadataRefreshOptions">The metadata refresh options.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="forceRefreshMetadata">if set to <c>true</c> [force refresh metadata].</param>
/// <returns>Task.</returns>
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true)
{
var directoryService = new DirectoryService(Logger);
return ValidateChildrenWithCancellationSupport(progress, cancellationToken, recursive ?? true, true,
metadataRefreshOptions.DirectoryService = metadataRefreshOptions.DirectoryService ?? new DirectoryService(Logger);
new MetadataRefreshOptions
{
ReplaceAllMetadata = forceRefreshMetadata,
DirectoryService = directoryService
}, directoryService);
return ValidateChildrenWithCancellationSupport(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService);
}
private async Task ValidateChildrenWithCancellationSupport(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, DirectoryService directoryService)
@ -531,7 +529,7 @@ namespace MediaBrowser.Controller.Entities
cancellationToken.ThrowIfCancellationRequested();
var innerProgress = new ActionableProgress<double>();
// Avoid implicitly captured closure
var currentChild = child;
innerProgress.RegisterAction(p =>

@ -38,6 +38,9 @@ namespace MediaBrowser.Model.Entities
Zap2It,
NesBox,
NesBoxRom,
TvRageSeries
TvRage,
Freebase,
FreebaseMachine,
AudioDbArtist
}
}

@ -119,6 +119,8 @@
<Compile Include="Music\AlbumImageFromSongProvider.cs" />
<Compile Include="Music\AlbumMetadataService.cs" />
<Compile Include="Music\ArtistMetadataService.cs" />
<Compile Include="Music\AudioDbArtistImageProvider.cs" />
<Compile Include="Music\AudioDbArtistProvider.cs" />
<Compile Include="Music\AudioMetadataService.cs" />
<Compile Include="Music\Extensions.cs" />
<Compile Include="Music\LastfmArtistProvider.cs" />

@ -0,0 +1,164 @@
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 MediaBrowser.Model.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
public class AudioDbArtistImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _json;
public AudioDbArtistImageProvider(IServerConfigurationManager config, IJsonSerializer json, IHttpClient httpClient)
{
_config = config;
_json = json;
_httpClient = httpClient;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType>
{
ImageType.Primary,
ImageType.Logo,
ImageType.Banner,
ImageType.Backdrop
};
}
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 async Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
{
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
if (!string.IsNullOrWhiteSpace(id))
{
await AudioDbArtistProvider.Current.EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
var path = AudioDbArtistProvider.GetArtistInfoPath(_config.ApplicationPaths, id);
var obj = _json.DeserializeFromFile<AudioDbArtistProvider.RootObject>(path);
if (obj != null && obj.artists != null && obj.artists.Count > 0)
{
return GetImages(obj.artists[0]);
}
}
return new List<RemoteImageInfo>();
}
private IEnumerable<RemoteImageInfo> GetImages(AudioDbArtistProvider.Artist item)
{
var list = new List<RemoteImageInfo>();
if (!string.IsNullOrWhiteSpace(item.strArtistThumb))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistThumb,
Type = ImageType.Primary
});
}
if (!string.IsNullOrWhiteSpace(item.strArtistLogo))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistLogo,
Type = ImageType.Logo
});
}
if (!string.IsNullOrWhiteSpace(item.strArtistBanner))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistBanner,
Type = ImageType.Banner
});
}
if (!string.IsNullOrWhiteSpace(item.strArtistFanart))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistFanart,
Type = ImageType.Backdrop
});
}
if (!string.IsNullOrWhiteSpace(item.strArtistFanart2))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistFanart2,
Type = ImageType.Backdrop
});
}
if (!string.IsNullOrWhiteSpace(item.strArtistFanart3))
{
list.Add(new RemoteImageInfo
{
ProviderName = Name,
Url = item.strArtistFanart3,
Type = ImageType.Backdrop
});
}
return list;
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool
});
}
public string Name
{
get { return "TheAudioDB"; }
}
public bool Supports(IHasImages item)
{
return item is MusicArtist;
}
public int Order
{
get
{
// After fanart
return 1;
}
}
}
}

@ -0,0 +1,212 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
public class AudioDbArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _json;
public static AudioDbArtistProvider Current;
public SemaphoreSlim AudioDbResourcePool = new SemaphoreSlim(2, 2);
private const string ApiKey = "49jhsf8248yfahka89724011";
public const string BaseUrl = "http://www.theaudiodb.com/api/v1/json/" + ApiKey;
public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClient httpClient, IJsonSerializer json)
{
_config = config;
_fileSystem = fileSystem;
_httpClient = httpClient;
_json = json;
Current = this;
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicArtist>();
var id = info.GetMusicBrainzArtistId();
if (!string.IsNullOrWhiteSpace(id))
{
await EnsureArtistInfo(id, cancellationToken).ConfigureAwait(false);
var path = GetArtistInfoPath(_config.ApplicationPaths, id);
var obj = _json.DeserializeFromFile<RootObject>(path);
if (obj != null && obj.artists != null && obj.artists.Count > 0)
{
result.Item = new MusicArtist();
result.HasMetadata = true;
ProcessResult(result.Item, obj.artists[0]);
}
}
return result;
}
private void ProcessResult(MusicArtist item, Artist result)
{
item.HomePageUrl = result.strWebsite;
item.Overview = result.strBiographyEN;
item.SetProviderId(MetadataProviders.AudioDbArtist, result.idArtist);
item.SetProviderId(MetadataProviders.MusicBrainzArtist, result.strMusicBrainzID);
}
public string Name
{
get { return "TheAudioDB"; }
}
private readonly Task _cachedTask = Task.FromResult(true);
internal Task EnsureArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
{
var xmlPath = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
if (fileInfo.Exists)
{
if (_config.Configuration.EnableFanArtUpdates || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
{
return _cachedTask;
}
}
return DownloadArtistInfo(musicBrainzId, cancellationToken);
}
internal async Task DownloadArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var url = BaseUrl + "/artist-mb.php?i=" + musicBrainzId;
var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
ResourcePool = AudioDbResourcePool,
CancellationToken = cancellationToken
}).ConfigureAwait(false))
{
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
}
}
/// <summary>
/// Gets the artist data path.
/// </summary>
/// <param name="appPaths">The application paths.</param>
/// <param name="musicBrainzArtistId">The music brainz artist identifier.</param>
/// <returns>System.String.</returns>
private static string GetArtistDataPath(IApplicationPaths appPaths, string musicBrainzArtistId)
{
var dataPath = Path.Combine(GetArtistDataPath(appPaths), musicBrainzArtistId);
return dataPath;
}
/// <summary>
/// Gets the artist data path.
/// </summary>
/// <param name="appPaths">The application paths.</param>
/// <returns>System.String.</returns>
internal static string GetArtistDataPath(IApplicationPaths appPaths)
{
var dataPath = Path.Combine(appPaths.DataPath, "audiodb");
return dataPath;
}
internal static string GetArtistInfoPath(IApplicationPaths appPaths, string musicBrainzArtistId)
{
var dataPath = GetArtistDataPath(appPaths, musicBrainzArtistId);
return Path.Combine(dataPath, "artist.json");
}
public class Artist
{
public string idArtist { get; set; }
public string strArtist { get; set; }
public string strArtistAlternate { get; set; }
public object idLabel { get; set; }
public string intFormedYear { get; set; }
public string intBornYear { get; set; }
public object intDiedYear { get; set; }
public object strDisbanded { get; set; }
public string strGenre { get; set; }
public string strSubGenre { get; set; }
public string strWebsite { get; set; }
public string strFacebook { get; set; }
public string strTwitter { get; set; }
public string strBiographyEN { get; set; }
public string strBiographyDE { get; set; }
public string strBiographyFR { get; set; }
public object strBiographyCN { get; set; }
public string strBiographyIT { get; set; }
public object strBiographyJP { get; set; }
public object strBiographyRU { get; set; }
public object strBiographyES { get; set; }
public object strBiographyPT { get; set; }
public object strBiographySE { get; set; }
public object strBiographyNL { get; set; }
public object strBiographyHU { get; set; }
public object strBiographyNO { get; set; }
public object strBiographyIL { get; set; }
public object strBiographyPL { get; set; }
public string strGender { get; set; }
public string intMembers { get; set; }
public string strCountry { get; set; }
public string strCountryCode { get; set; }
public string strArtistThumb { get; set; }
public string strArtistLogo { get; set; }
public string strArtistFanart { get; set; }
public string strArtistFanart2 { get; set; }
public string strArtistFanart3 { get; set; }
public string strArtistBanner { get; set; }
public string strMusicBrainzID { get; set; }
public object strLastFMChart { get; set; }
public string strLocked { get; set; }
}
public class RootObject
{
public List<Artist> artists { get; set; }
}
public int Order
{
get
{
// After musicbrainz
return 1;
}
}
}
}

@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.Music
return id;
}
public static string GetArtistId(this AlbumInfo info)
public static string GetMusicBrainzArtistId(this AlbumInfo info)
{
string id;
info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzAlbumArtist.ToString(), out id);
@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.Music
return id;
}
public static string GetArtistId(this ArtistInfo info)
public static string GetMusicBrainzArtistId(this ArtistInfo info)
{
string id;
info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzArtist.ToString(), out id);

@ -151,7 +151,11 @@ namespace MediaBrowser.Providers.Music
public int Order
{
get { return 1; }
get
{
// After all others
return 3;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)

@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music
{
var result = new MetadataResult<MusicArtist>();
var musicBrainzId = id.GetArtistId();
var musicBrainzId = id.GetMusicBrainzArtistId();
if (!String.IsNullOrWhiteSpace(musicBrainzId))
{
@ -161,7 +161,11 @@ namespace MediaBrowser.Providers.Music
public int Order
{
get { return 1; }
get
{
// After fanart & audiodb
return 2;
}
}
}
}

@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.Music
if (string.IsNullOrEmpty(releaseId))
{
var artistMusicBrainzId = id.GetArtistId();
var artistMusicBrainzId = id.GetMusicBrainzArtistId();
var releaseResult = await GetReleaseResult(artistMusicBrainzId, id.GetAlbumArtist(), id.Name, cancellationToken).ConfigureAwait(false);

@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music
{
var result = new MetadataResult<MusicArtist>();
var musicBrainzId = id.GetArtistId() ?? await FindId(id, cancellationToken).ConfigureAwait(false);
var musicBrainzId = id.GetMusicBrainzArtistId() ?? await FindId(id, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(musicBrainzId))
{

@ -169,12 +169,20 @@ namespace MediaBrowser.Providers.TV
}
if (ids.tvrage_id > 0)
{
series.SetProviderId(MetadataProviders.TvRageSeries, ids.tvrage_id.ToString(_usCulture));
series.SetProviderId(MetadataProviders.TvRage, ids.tvrage_id.ToString(_usCulture));
}
if (ids.tvdb_id > 0)
{
series.SetProviderId(MetadataProviders.Tvdb, ids.tvdb_id.ToString(_usCulture));
}
if (!string.IsNullOrWhiteSpace(ids.freebase_id))
{
series.SetProviderId(MetadataProviders.Freebase, ids.freebase_id);
}
if (!string.IsNullOrWhiteSpace(ids.freebase_mid))
{
series.SetProviderId(MetadataProviders.FreebaseMachine, ids.freebase_mid);
}
}
}

@ -13,7 +13,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
public class SeriesMetadataService : MetadataService<Series, ItemLookupInfo>
public class SeriesMetadataService : MetadataService<Series, SeriesInfo>
{
private readonly ILibraryManager _libraryManager;

@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.TV
{
}, cancellationToken).ConfigureAwait(false);
await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
await series.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(), true)
.ConfigureAwait(false);
}
}

@ -158,33 +158,24 @@ namespace MediaBrowser.Providers.TV
var automaticUpdatesEnabled = _config.Configuration.EnableTvDbUpdates;
var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
if (seriesFile == null || !seriesFile.Exists)
// No need to check age if automatic updates are enabled
if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > 7))
{
// No need to check age if automatic updates are enabled
if (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > 7)
{
download = true;
}
download = true;
}
var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
if (actorsXml == null || !actorsXml.Exists)
// No need to check age if automatic updates are enabled
if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > 7))
{
// No need to check age if automatic updates are enabled
if (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > 7)
{
download = true;
}
download = true;
}
var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
if (bannersXml == null || !bannersXml.Exists)
// No need to check age if automatic updates are enabled
if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > 7))
{
// No need to check age if automatic updates are enabled
if (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > 7)
{
download = true;
}
download = true;
}
// Only download if not already there

@ -955,7 +955,7 @@ namespace MediaBrowser.Server.Implementations.Library
progress.Report(.5);
// Start by just validating the children of the root, but go no further
await RootFolder.ValidateChildren(new Progress<double>(), cancellationToken, recursive: false);
await RootFolder.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(), recursive: false);
progress.Report(1);
@ -980,7 +980,7 @@ namespace MediaBrowser.Server.Implementations.Library
innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6));
// Now validate the entire media library
await RootFolder.ValidateChildren(innerProgress, cancellationToken, recursive: true).ConfigureAwait(false);
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(), recursive: true).ConfigureAwait(false);
progress.Report(75);
@ -1109,7 +1109,7 @@ namespace MediaBrowser.Server.Implementations.Library
cancellationToken.ThrowIfCancellationRequested();
await userRootFolder.ValidateChildren(new Progress<double>(), cancellationToken, recursive: false).ConfigureAwait(false);
await userRootFolder.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(), recursive: false).ConfigureAwait(false);
}
/// <summary>

Loading…
Cancel
Save