diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index dbe7eba5b9..d44f003fed 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -110,7 +110,8 @@ - + + diff --git a/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs index 9f0dedf4db..011c2b611a 100644 --- a/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/FanArtArtistProvider.cs @@ -1,4 +1,5 @@ -using System.Collections.Specialized; +using System.Collections.Generic; +using System.Collections.Specialized; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -143,6 +144,7 @@ namespace MediaBrowser.Controller.Providers.Music Logger.Debug("FanArtProvider getting Backdrop for " + artist.Name); try { + artist.BackdropImagePaths = new List(); artist.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(artist, path, ("Backdrop"+(numBackdrops > 0 ? numBackdrops.ToString() : "")+".jpg"), FanArtResourcePool, cancellationToken).ConfigureAwait(false)); numBackdrops++; if (numBackdrops >= ConfigurationManager.Configuration.MaxBackdrops) break; diff --git a/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs index 0ac6d770d2..8aca8b9a04 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Text; @@ -16,12 +17,13 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Providers.Music { - public class LastfmArtistProvider : LastfmBaseArtistProvider + public class LastfmArtistProvider : LastfmBaseProvider { public LastfmArtistProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager) : base(jsonSerializer, httpClient, logManager, configurationManager) { + LocalMetaFileName = LastfmHelper.LocalArtistMetaFileName; } protected override async Task FindId(Entities.BaseItem item, System.Threading.CancellationToken cancellationToken) @@ -80,8 +82,24 @@ namespace MediaBrowser.Controller.Providers.Music if (result != null && result.artist != null) { - ProcessArtistData(item as MusicArtist, result.artist); + LastfmHelper.ProcessArtistData(item, result.artist); + //And save locally if indicated + if (ConfigurationManager.Configuration.SaveLocalMeta) + { + var ms = new MemoryStream(); + JsonSerializer.SerializeToStream(result.artist, ms); + + cancellationToken.ThrowIfCancellationRequested(); + + await Kernel.Instance.FileSystemManager.SaveToLibraryFilesystem(item, Path.Combine(item.MetaLocation, LocalMetaFileName), ms, cancellationToken).ConfigureAwait(false); + + } } } + + public override bool Supports(Entities.BaseItem item) + { + return item is MusicArtist; + } } } diff --git a/MediaBrowser.Controller/Providers/Music/LastfmBaseArtistProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmBaseArtistProvider.cs deleted file mode 100644 index 444c0fefd5..0000000000 --- a/MediaBrowser.Controller/Providers/Music/LastfmBaseArtistProvider.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Providers.Music -{ - public abstract class LastfmBaseArtistProvider : LastfmBaseProvider - { - protected LastfmBaseArtistProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager) - : base(jsonSerializer, httpClient, logManager, configurationManager) - { - LocalMetaFileName = "MBArtist.json"; - } - - public override bool Supports(Entities.BaseItem item) - { - return item is MusicArtist; - } - - protected void ProcessArtistData(MusicArtist artist, LastfmArtist data) - { - artist.Overview = data.bio.summary; - foreach (var tag in data.tags.tag) - { - artist.AddGenre(tag.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 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 formationlist { get; set; } - } - - public class LastfmArtist - { - 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 similar { get; set; } - public LastfmTags tags { get; set; } - public LastFmBio bio { get; set; } - } - - public class LastfmGetArtistResult - { - public LastfmArtist artist { get; set; } - } - - public class Artistmatches - { - public List artist { get; set; } - } - - public class LastfmArtistSearchResult - { - public Artistmatches artistmatches { get; set; } - } - - public class LastfmArtistSearchResults - { - public LastfmArtistSearchResult results { get; set; } - } - #endregion -} diff --git a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs index 2d4bb1f59a..f18a9cb653 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Collections.Generic; +using System.Net; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -66,6 +67,17 @@ namespace MediaBrowser.Controller.Providers.Music /// protected string LocalMetaFileName { get; set; } + /// + /// If we save locally, refresh if they delete something + /// + protected override bool RefreshOnFileSystemStampChange + { + get + { + return ConfigurationManager.Configuration.SaveLocalMeta; + } + } + /// /// Gets the priority. /// @@ -87,19 +99,58 @@ namespace MediaBrowser.Controller.Providers.Music } } + protected const string RootUrl = @"http://ws.audioscrobbler.com/2.0/?"; + protected static string ApiKey = "7b76553c3eb1d341d642755aecc40a33"; + /// - /// If we save locally, refresh if they delete something + /// Determines whether [has local meta] [the specified item]. /// - protected override bool RefreshOnFileSystemStampChange + /// The item. + /// true if [has local meta] [the specified item]; otherwise, false. + protected bool HasLocalMeta(BaseItem item) { - get + return item.ResolveArgs.ContainsMetaFileByName(LocalMetaFileName); + } + + /// + /// Fetches the items data. + /// + /// The item. + /// + /// Task. + protected virtual async Task FetchData(BaseItem item, CancellationToken cancellationToken) + { + var id = item.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(item, cancellationToken).ConfigureAwait(false); + if (id != null) { - return ConfigurationManager.Configuration.SaveLocalMeta; + Logger.Debug("LastfmProvider - getting info with id: " + id); + + cancellationToken.ThrowIfCancellationRequested(); + + item.SetProviderId(MetadataProviders.Musicbrainz, id); + + await FetchLastfmData(item, id, cancellationToken).ConfigureAwait(false); + } + else + { + Logger.Info("LastfmProvider could not find " + item.Name + ". Check name on Last.fm."); } + } - protected const string RootUrl = @"http://ws.audioscrobbler.com/2.0/?"; - protected static string ApiKey = "7b76553c3eb1d341d642755aecc40a33"; + protected abstract Task FindId(BaseItem item, CancellationToken cancellationToken); + + protected abstract Task FetchLastfmData(BaseItem item, string id, CancellationToken cancellationToken); + + /// + /// Encodes an URL. + /// + /// The name. + /// System.String. + protected static string UrlEncode(string name) + { + return WebUtility.UrlEncode(name); + } protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) { @@ -173,56 +224,76 @@ namespace MediaBrowser.Controller.Providers.Music SetLastRefreshed(item, DateTime.UtcNow); return true; } + } - /// - /// Determines whether [has local meta] [the specified item]. - /// - /// The item. - /// true if [has local meta] [the specified item]; otherwise, false. - private bool HasLocalMeta(BaseItem item) - { - return item.ResolveArgs.ContainsMetaFileByName(LocalMetaFileName); - } + #region Result Objects - /// - /// Fetches the items data. - /// - /// The item. - /// - /// Task. - protected async Task FetchData(BaseItem item, CancellationToken cancellationToken) - { - var id = item.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(item, cancellationToken).ConfigureAwait(false); - if (id != null) - { - Logger.Debug("LastfmProvider - getting info with id: " + id); + public class LastfmStats + { + public string listeners { get; set; } + public string playcount { get; set; } + } - cancellationToken.ThrowIfCancellationRequested(); + public class LastfmTag + { + public string name { get; set; } + public string url { get; set; } + } - item.SetProviderId(MetadataProviders.Musicbrainz, id); - await FetchLastfmData(item, id, cancellationToken).ConfigureAwait(false); - } - else - { - Logger.Info("LastfmProvider could not find " + item.Name + ". Check name on Last.fm."); - } - - } + public class LastfmTags + { + public List tag { get; set; } + } - protected abstract Task FindId(BaseItem item, CancellationToken cancellationToken); + public class LastfmFormationInfo + { + public string yearfrom { get; set; } + public string yearto { get; set; } + } - protected abstract Task FetchLastfmData(BaseItem item, string id, CancellationToken cancellationToken); + 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 formationlist { get; set; } + } - /// - /// Encodes an URL. - /// - /// The name. - /// System.String. - protected static string UrlEncode(string name) - { - return WebUtility.UrlEncode(name); - } + public class LastfmArtist + { + 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 similar { get; set; } + public LastfmTags tags { get; set; } + public LastFmBio bio { get; set; } + } + public class LastfmGetArtistResult + { + public LastfmArtist artist { get; set; } + } + + public class Artistmatches + { + public List artist { get; set; } } + + public class LastfmArtistSearchResult + { + public Artistmatches artistmatches { get; set; } + } + + public class LastfmArtistSearchResults + { + public LastfmArtistSearchResult results { get; set; } + } + + #endregion } diff --git a/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs new file mode 100644 index 0000000000..d4559b94a1 --- /dev/null +++ b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Providers.Music +{ + public static class LastfmHelper + { + public static string LocalArtistMetaFileName = "MBArtist.json"; + + public static void ProcessArtistData(BaseItem artist, LastfmArtist data) + { + artist.Overview = data.bio != null ? data.bio.content : null; + if (data.tags != null) + { + foreach (var tag in data.tags.tag) + { + artist.AddGenre(tag.name); + } + + } + } + + } +} diff --git a/MediaBrowser.Controller/Providers/Music/MusicArtistProviderFromJson.cs b/MediaBrowser.Controller/Providers/Music/MusicArtistProviderFromJson.cs new file mode 100644 index 0000000000..6008074895 --- /dev/null +++ b/MediaBrowser.Controller/Providers/Music/MusicArtistProviderFromJson.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; + +namespace MediaBrowser.Controller.Providers.Music +{ + public class MusicArtistProviderFromJson : BaseMetadataProvider + { + /// + /// Gets the json serializer. + /// + /// The json serializer. + protected IJsonSerializer JsonSerializer { get; private set; } + + public MusicArtistProviderFromJson(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager) + : base(logManager, configurationManager) + { + if (jsonSerializer == null) + { + throw new ArgumentNullException("jsonSerializer"); + } + JsonSerializer = jsonSerializer; + + } + + protected override Task FetchAsyncInternal(BaseItem item, bool force, CancellationToken cancellationToken) + { + return Task.Run(() => + { + cancellationToken.ThrowIfCancellationRequested(); + + var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName)); + if (entry.HasValue) + { + // read in our saved meta and pass to processing function + var data = JsonSerializer.DeserializeFromFile(entry.Value.Path); + + cancellationToken.ThrowIfCancellationRequested(); + + LastfmHelper.ProcessArtistData(item, data); + + SetLastRefreshed(item, DateTime.UtcNow); + return true; + } + return false; + }); + } + + public override MetadataProviderPriority Priority + { + get + { + return MetadataProviderPriority.First; + } + } + + public override bool Supports(BaseItem item) + { + return item is MusicArtist; + } + + public override bool RequiresInternet + { + get + { + return false; + } + } + + protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) + { + if (!item.ResolveArgs.ContainsMetaFileByName(LastfmHelper.LocalArtistMetaFileName)) + { + return false; // nothing to read + } + + // Need to re-override to jump over intermediate implementation + return CompareDate(item) > providerInfo.LastRefreshed; + } + + /// + /// Override this to return the date that should be compared to the last refresh date + /// to determine if this provider should be re-fetched. + /// + /// The item. + /// DateTime. + protected override DateTime CompareDate(BaseItem item) + { + var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName)); + return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue; + } + + } +}