diff options
| -rw-r--r-- | MediaBrowser.Api/ItemLookupService.cs | 27 | ||||
| -rw-r--r-- | MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 3 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs | 80 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs | 130 |
4 files changed, 199 insertions, 41 deletions
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index a32a1ad03..62596287e 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; @@ -67,6 +68,18 @@ namespace MediaBrowser.Api { } + [Route("/Items/RemoteSearch/MusicArtist", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/MusicAlbum", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>> + { + } + [Route("/Items/RemoteSearch/Person", "POST")] [Api(Description = "Gets external id infos for an item")] public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>> @@ -167,6 +180,20 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } + public object Post(GetMusicAlbumRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetMusicArtistRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + public object Get(GetRemoteSearchImage request) { var result = GetRemoteImage(request).Result; diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 75879b3da..a7ee05cf3 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -96,6 +96,9 @@ <Name>MediaBrowser.Model</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <Folder Include="Server\" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 43ee7bdbc..e36d8a320 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -7,6 +7,7 @@ using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Text; using System.Threading; @@ -31,9 +32,86 @@ namespace MediaBrowser.Providers.Music public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) { + var releaseId = searchInfo.GetReleaseId(); + + string url = null; + + if (!string.IsNullOrEmpty(releaseId)) + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=reid:{0}", releaseId); + } + else + { + var artistMusicBrainzId = searchInfo.GetMusicBrainzArtistId(); + + if (!string.IsNullOrWhiteSpace(artistMusicBrainzId)) + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", + WebUtility.UrlEncode(searchInfo.Name), + artistMusicBrainzId); + } + else + { + url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", + WebUtility.UrlEncode(searchInfo.Name), + WebUtility.UrlEncode(searchInfo.GetAlbumArtist())); + } + } + + if (!string.IsNullOrWhiteSpace(url)) + { + var doc = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + + return GetResultsFromResponse(doc); + } + return new List<RemoteSearchResult>(); } + private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc) + { + var ns = new XmlNamespaceManager(doc.NameTable); + ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + + var list = new List<RemoteSearchResult>(); + + var nodes = doc.SelectNodes("//mb:release-list/mb:release", ns); + + if (nodes != null) + { + foreach (var node in nodes.Cast<XmlNode>()) + { + if (node.Attributes != null) + { + string name = null; + + string mbzId = node.Attributes["id"].Value; + + var nameNode = node.SelectSingleNode("//mb:title", ns); + + if (nameNode != null) + { + name = nameNode.InnerText; + } + + if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name)) + { + var result = new RemoteSearchResult + { + Name = name + }; + + result.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbzId); + + list.Add(result); + } + } + } + } + + return list; + } + public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken) { var releaseId = id.GetReleaseId(); @@ -146,7 +224,7 @@ namespace MediaBrowser.Providers.Music { result.ReleaseGroupId = releaseGroupIdNode.Value; } - + return result; } diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 7c0233d3e..12a1bdd35 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -19,70 +19,120 @@ namespace MediaBrowser.Providers.Music { public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); - } - - public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) - { - var result = new MetadataResult<MusicArtist>(); - - var musicBrainzId = id.GetMusicBrainzArtistId() ?? await FindId(id, cancellationToken).ConfigureAwait(false); + var musicBrainzId = searchInfo.GetMusicBrainzArtistId(); if (!string.IsNullOrWhiteSpace(musicBrainzId)) { - cancellationToken.ThrowIfCancellationRequested(); + var url = string.Format("http://www.musicbrainz.org/ws/2/artist/?query=arid:{0}", musicBrainzId); - result.Item = new MusicArtist(); - result.HasMetadata = true; + var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken) + .ConfigureAwait(false); - result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId); + return GetResultsFromResponse(doc); } + else + { + // They seem to throw bad request failures on any term with a slash + var nameToSearch = searchInfo.Name.Replace('/', ' '); - return result; - } - - /// <summary> - /// Finds the id from music brainz. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{System.String}.</returns> - private async Task<string> FindId(ItemLookupInfo 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 results = GetResultsFromResponse(doc).ToList(); + + if (results.Count > 0) + { + return results; + } - var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); + if (HasDiacritics(searchInfo.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); + + return GetResultsFromResponse(doc); + } + } - var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + return new List<RemoteSearchResult>(); + } + private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc) + { 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) + var list = new List<RemoteSearchResult>(); + + var nodes = doc.SelectNodes("//mb:artist-list/mb:artist", ns); + + if (nodes != null) { - return node.Value; + foreach (var node in nodes.Cast<XmlNode>()) + { + if (node.Attributes != null) + { + string name = null; + + string mbzId = node.Attributes["id"].Value; + + var nameNode = node.SelectSingleNode("//mb:name", ns); + + if (nameNode != null) + { + name = nameNode.InnerText; + } + + if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name)) + { + var result = new RemoteSearchResult + { + Name = name + }; + + result.SetProviderId(MetadataProviders.MusicBrainzArtist, mbzId); + + list.Add(result); + } + } + } } - if (HasDiacritics(item.Name)) + return list; + } + + public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) + { + var result = new MetadataResult<MusicArtist> { - // Try again using the search with accent characters url - url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + Item = new MusicArtist() + }; - doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); + var musicBrainzId = id.GetMusicBrainzArtistId(); - 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 (string.IsNullOrWhiteSpace(musicBrainzId)) + { + var searchResults = await GetSearchResults(id, cancellationToken).ConfigureAwait(false); + + var singleResult = searchResults.FirstOrDefault(); - if (node != null && node.Value != null) + if (singleResult != null) { - return node.Value; + musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); + result.Item.Name = singleResult.Name; } } - return null; + if (!string.IsNullOrWhiteSpace(musicBrainzId)) + { + result.HasMetadata = true; + result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId); + } + + return result; } /// <summary> |
