2
0
Эх сурвалжийг харах

update music brainz providers

Luke Pulverenti 8 жил өмнө
parent
commit
2de485eb9f

+ 201 - 115
MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs

@@ -74,36 +74,50 @@ namespace MediaBrowser.Providers.Music
 
             if (!string.IsNullOrWhiteSpace(url))
             {
-                using (var reader = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false))
+                using (var stream = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false))
                 {
-                    return GetResultsFromResponse(reader);
+                    return GetResultsFromResponse(stream);
                 }
             }
 
             return new List<RemoteSearchResult>();
         }
 
-        private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlReader reader)
+        private List<RemoteSearchResult> GetResultsFromResponse(Stream stream)
         {
-            return ReleaseResult.Parse(reader).Select(i =>
+            using (var oReader = new StreamReader(stream, Encoding.UTF8))
             {
-                var result = new RemoteSearchResult
-                {
-                    Name = i.Title,
-                    ProductionYear = i.Year
-                };
+                var settings = _xmlSettings.Create(false);
 
-                if (!string.IsNullOrWhiteSpace(i.ReleaseId))
-                {
-                    result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseId);
-                }
-                if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId))
+                settings.CheckCharacters = false;
+                settings.IgnoreProcessingInstructions = true;
+                settings.IgnoreComments = true;
+
+                using (var reader = XmlReader.Create(oReader, settings))
                 {
-                    result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId);
-                }
+                    var results = ReleaseResult.Parse(reader);
 
-                return result;
-            });
+                    return results.Select(i =>
+                    {
+                        var result = new RemoteSearchResult
+                        {
+                            Name = i.Title,
+                            ProductionYear = i.Year
+                        };
+
+                        if (!string.IsNullOrWhiteSpace(i.ReleaseId))
+                        {
+                            result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseId);
+                        }
+                        if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId))
+                        {
+                            result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId);
+                        }
+
+                        return result;
+                    }).ToList();
+                }
+            }
         }
 
         public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
@@ -195,9 +209,21 @@ namespace MediaBrowser.Providers.Music
                 WebUtility.UrlEncode(albumName),
                 artistId);
 
-            using (var reader = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+            using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
             {
-                return ReleaseResult.Parse(reader, 1).FirstOrDefault();
+                using (var oReader = new StreamReader(stream, Encoding.UTF8))
+                {
+                    var settings = _xmlSettings.Create(false);
+
+                    settings.CheckCharacters = false;
+                    settings.IgnoreProcessingInstructions = true;
+                    settings.IgnoreComments = true;
+
+                    using (var reader = XmlReader.Create(oReader, settings))
+                    {
+                        return ReleaseResult.Parse(reader).FirstOrDefault();
+                    }
+                }
             }
         }
 
@@ -207,9 +233,21 @@ namespace MediaBrowser.Providers.Music
                 WebUtility.UrlEncode(albumName),
                 WebUtility.UrlEncode(artistName));
 
-            using (var reader = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+            using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
             {
-                return ReleaseResult.Parse(reader, 1).FirstOrDefault();
+                using (var oReader = new StreamReader(stream, Encoding.UTF8))
+                {
+                    var settings = _xmlSettings.Create(false);
+
+                    settings.CheckCharacters = false;
+                    settings.IgnoreProcessingInstructions = true;
+                    settings.IgnoreComments = true;
+
+                    using (var reader = XmlReader.Create(oReader, settings))
+                    {
+                        return ReleaseResult.Parse(reader).FirstOrDefault();
+                    }
+                }
             }
         }
 
@@ -221,31 +259,37 @@ namespace MediaBrowser.Providers.Music
             public string Overview;
             public int? Year;
 
-            public static List<ReleaseResult> Parse(XmlReader reader, int? limit = null)
+            public static List<ReleaseResult> Parse(XmlReader reader)
             {
+                var list = new List<ReleaseResult>();
+
                 reader.MoveToContent();
 
                 // Loop through each element
                 while (reader.Read())
                 {
-                    switch (reader.Name)
+                    if (reader.NodeType == XmlNodeType.Element)
                     {
-                        case "release-list":
-                            {
-                                using (var subReader = reader.ReadSubtree())
+                        switch (reader.Name)
+                        {
+                            case "release-list":
                                 {
-                                    return ParseReleaseList(subReader);
+                                    using (var subReader = reader.ReadSubtree())
+                                    {
+                                        list.AddRange(ParseReleaseList(subReader));
+                                    }
+                                    break;
                                 }
-                            }
-                        default:
-                            {
-                                reader.Skip();
-                                break;
-                            }
+                            default:
+                                {
+                                    reader.Skip();
+                                    break;
+                                }
+                        }
                     }
                 }
 
-                return new List<ReleaseResult>();
+                return list;
             }
 
             private static List<ReleaseResult> ParseReleaseList(XmlReader reader)
@@ -257,24 +301,31 @@ namespace MediaBrowser.Providers.Music
                 // Loop through each element
                 while (reader.Read())
                 {
-                    switch (reader.Name)
+                    if (reader.NodeType == XmlNodeType.Element)
                     {
-                        case "release":
-                            {
-                                var releaseId = reader.GetAttribute("id");
-
-                                using (var subReader = reader.ReadSubtree())
+                        switch (reader.Name)
+                        {
+                            case "release":
                                 {
-                                    var artist = ParseRelease(subReader, releaseId);
-                                    list.Add(artist);
+                                    //var releaseId = reader.GetAttribute("id");
+                                    string releaseId = null;
+
+                                    using (var subReader = reader.ReadSubtree())
+                                    {
+                                        var release = ParseRelease(subReader, releaseId);
+                                        if (release != null)
+                                        {
+                                            list.Add(release);
+                                        }
+                                    }
+                                    break;
                                 }
-                                break;
-                            }
-                        default:
-                            {
-                                reader.Skip();
-                                break;
-                            }
+                            default:
+                                {
+                                    reader.Skip();
+                                    break;
+                                }
+                        }
                     }
                 }
 
@@ -290,41 +341,70 @@ namespace MediaBrowser.Providers.Music
 
                 reader.MoveToContent();
 
+                reader.Read();
+
+                // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
                 // Loop through each element
-                while (reader.Read())
+                while (!reader.EOF)
                 {
-                    switch (reader.Name)
+                    if (reader.NodeType == XmlNodeType.Element)
                     {
-                        case "title":
-                            {
-                                result.Title = reader.ReadElementContentAsString();
-                                break;
-                            }
-                        case "date":
-                            {
-                                var val = reader.ReadElementContentAsString();
-                                DateTime date;
-                                if (DateTime.TryParse(val, out date))
+                        switch (reader.Name)
+                        {
+                            case "title":
                                 {
-                                    result.Year = date.Year;
+                                    result.Title = reader.ReadElementContentAsString();
+                                    break;
                                 }
-                                break;
-                            }
-                        case "annotation":
-                            {
-                                result.Overview = reader.ReadElementContentAsString();
-                                break;
-                            }
-                        case "release-group":
-                            {
-                                result.ReleaseGroupId = reader.GetAttribute("id");
-                                break;
-                            }
-                        default:
+                            case "date":
+                                {
+                                    var val = reader.ReadElementContentAsString();
+                                    DateTime date;
+                                    if (DateTime.TryParse(val, out date))
+                                    {
+                                        result.Year = date.Year;
+                                    }
+                                    break;
+                                }
+                            case "annotation":
+                                {
+                                    result.Overview = reader.ReadElementContentAsString();
+                                    break;
+                                }
+                            case "release-group":
+                                {
+                                    result.ReleaseGroupId = reader.GetAttribute("id");
+                                    //explicitly consume these to avoid grabbing data from child nodes
+                                    //reader.Skip();
+                                    using (var subtree = reader.ReadSubtree())
+                                    {
+                                    }
+                                    break;
+                                }
+                            //explicitly consume these to avoid grabbing data from child nodes
+                            //case "text-representation":
+                            //case "artist-credit":
+                            //case "medium-list":
+                            //case "tag-list":
+                            //case "label-info-list":
+                            //case "release-event-list":
+                            //    {
+                            //        using (var subtree = reader.ReadSubtree())
+                            //        {
+                            //        }
+                            //        break;
+                            //    }
+                            default:
                             {
                                 reader.Skip();
                                 break;
                             }
+                        }
+                    }
+                    else
+                    {
+                        reader.Read();
                     }
                 }
 
@@ -342,30 +422,45 @@ namespace MediaBrowser.Providers.Music
         {
             var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
 
-            using (var reader = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
+            using (var stream = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
             {
-                reader.MoveToContent();
-
-                // Loop through each element
-                while (reader.Read())
+                using (var oReader = new StreamReader(stream, Encoding.UTF8))
                 {
-                    switch (reader.Name)
+                    var settings = _xmlSettings.Create(false);
+
+                    settings.CheckCharacters = false;
+                    settings.IgnoreProcessingInstructions = true;
+                    settings.IgnoreComments = true;
+
+                    using (var reader = XmlReader.Create(oReader, settings))
                     {
-                        case "release-group-list":
+                        reader.MoveToContent();
+
+                        // Loop through each element
+                        while (reader.Read())
+                        {
+                            if (reader.NodeType == XmlNodeType.Element)
                             {
-                                using (var subReader = reader.ReadSubtree())
+                                switch (reader.Name)
                                 {
-                                    return GetFirstReleaseGroupId(subReader);
+                                    case "release-group-list":
+                                        {
+                                            using (var subReader = reader.ReadSubtree())
+                                            {
+                                                return GetFirstReleaseGroupId(subReader);
+                                            }
+                                        }
+                                    default:
+                                        {
+                                            reader.Skip();
+                                            break;
+                                        }
                                 }
                             }
-                        default:
-                            {
-                                reader.Skip();
-                                break;
-                            }
+                        }
+                        return null;
                     }
                 }
-                return null;
             }
         }
 
@@ -376,17 +471,20 @@ namespace MediaBrowser.Providers.Music
             // Loop through each element
             while (reader.Read())
             {
-                switch (reader.Name)
+                if (reader.NodeType == XmlNodeType.Element)
                 {
-                    case "release-group":
-                        {
-                            return reader.GetAttribute("id");
-                        }
-                    default:
-                        {
-                            reader.Skip();
-                            break;
-                        }
+                    switch (reader.Name)
+                    {
+                        case "release-group":
+                            {
+                                return reader.GetAttribute("id");
+                            }
+                        default:
+                            {
+                                reader.Skip();
+                                break;
+                            }
+                    }
                 }
             }
 
@@ -465,7 +563,7 @@ namespace MediaBrowser.Providers.Music
         /// <param name="isSearch">if set to <c>true</c> [is search].</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{XmlDocument}.</returns>
-        internal async Task<XmlReader> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
+        internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
         {
             var urlInfo = await GetMbzUrl().ConfigureAwait(false);
 
@@ -485,19 +583,7 @@ namespace MediaBrowser.Providers.Music
                 ResourcePool = _musicBrainzResourcePool
             };
 
-            using (var xml = await _httpClient.Get(options).ConfigureAwait(false))
-            {
-                using (var oReader = new StreamReader(xml, Encoding.UTF8))
-                {
-                    var settings = _xmlSettings.Create(false);
-
-                    settings.CheckCharacters = false;
-                    settings.IgnoreProcessingInstructions = true;
-                    settings.IgnoreComments = true;
-
-                    return XmlReader.Create(oReader, settings);
-                }
-            }
+            return await _httpClient.Get(options).ConfigureAwait(false);
         }
 
         public int Order

+ 95 - 62
MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs

@@ -6,6 +6,7 @@ using MediaBrowser.Model.Providers;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
+using System.IO;
 using System.Linq;
 using System.Net;
 using System.Text;
@@ -13,11 +14,19 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Xml;
 using MediaBrowser.Controller.Extensions;
+using MediaBrowser.Model.Xml;
 
 namespace MediaBrowser.Providers.Music
 {
     public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>
     {
+        private readonly IXmlReaderSettingsFactory _xmlSettings;
+
+        public MusicBrainzArtistProvider(IXmlReaderSettingsFactory xmlSettings)
+        {
+            _xmlSettings = xmlSettings;
+        }
+
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
         {
             var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
@@ -26,10 +35,10 @@ namespace MediaBrowser.Providers.Music
             {
                 var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
 
-                using (var reader = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
+                using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
                             .ConfigureAwait(false))
                 {
-                    return GetResultsFromResponse(reader);
+                    return GetResultsFromResponse(stream);
                 }
             }
             else
@@ -39,9 +48,9 @@ namespace MediaBrowser.Providers.Music
 
                 var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
 
-                using (var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+                using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
                 {
-                    var results = GetResultsFromResponse(doc).ToList();
+                    var results = GetResultsFromResponse(stream).ToList();
 
                     if (results.Count > 0)
                     {
@@ -54,9 +63,9 @@ namespace MediaBrowser.Providers.Music
                     // Try again using the search with accent characters url
                     url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
 
-                    using (var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+                    using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
                     {
-                        return GetResultsFromResponse(doc);
+                        return GetResultsFromResponse(stream);
                     }
                 }
             }
@@ -64,31 +73,46 @@ namespace MediaBrowser.Providers.Music
             return new List<RemoteSearchResult>();
         }
 
-        private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlReader reader)
+        private IEnumerable<RemoteSearchResult> GetResultsFromResponse(Stream stream)
         {
-            reader.MoveToContent();
-
-            // Loop through each element
-            while (reader.Read())
+            using (var oReader = new StreamReader(stream, Encoding.UTF8))
             {
-                switch (reader.Name)
+                var settings = _xmlSettings.Create(false);
+
+                settings.CheckCharacters = false;
+                settings.IgnoreProcessingInstructions = true;
+                settings.IgnoreComments = true;
+
+                using (var reader = XmlReader.Create(oReader, settings))
                 {
-                    case "artist-list":
+                    reader.MoveToContent();
+
+                    // Loop through each element
+                    while (reader.Read())
+                    {
+                        if (reader.NodeType == XmlNodeType.Element)
                         {
-                            using (var subReader = reader.ReadSubtree())
+                            switch (reader.Name)
                             {
-                                return ParseArtistList(subReader);
+                                case "artist-list":
+                                    {
+                                        using (var subReader = reader.ReadSubtree())
+                                        {
+                                            return ParseArtistList(subReader);
+                                        }
+                                    }
+                                default:
+                                    {
+                                        reader.Skip();
+                                        break;
+                                    }
                             }
                         }
-                    default:
-                        {
-                            reader.Skip();
-                            break;
-                        }
+                    }
+
+                    return new List<RemoteSearchResult>();
                 }
             }
-
-            return new List<RemoteSearchResult>();
         }
 
         private IEnumerable<RemoteSearchResult> ParseArtistList(XmlReader reader)
@@ -100,24 +124,30 @@ namespace MediaBrowser.Providers.Music
             // Loop through each element
             while (reader.Read())
             {
-                switch (reader.Name)
+                if (reader.NodeType == XmlNodeType.Element)
                 {
-                    case "artist":
-                        {
-                            var mbzId = reader.GetAttribute("id");
-
-                            using (var subReader = reader.ReadSubtree())
+                    switch (reader.Name)
+                    {
+                        case "artist":
                             {
-                                var artist = ParseArtist(subReader, mbzId);
-                                list.Add(artist);
+                                var mbzId = reader.GetAttribute("id");
+
+                                using (var subReader = reader.ReadSubtree())
+                                {
+                                    var artist = ParseArtist(subReader, mbzId);
+                                    if (artist != null)
+                                    {
+                                        list.Add(artist);
+                                    }
+                                }
+                                break;
                             }
-                            break;
-                        }
-                    default:
-                        {
-                            reader.Skip();
-                            break;
-                        }
+                        default:
+                            {
+                                reader.Skip();
+                                break;
+                            }
+                    }
                 }
             }
 
@@ -129,35 +159,38 @@ namespace MediaBrowser.Providers.Music
             var result = new RemoteSearchResult();
 
             reader.MoveToContent();
+            reader.Read();
+
+            // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
 
             // Loop through each element
-            while (reader.Read())
+            while (!reader.EOF)
             {
-                switch (reader.Name)
+                if (reader.NodeType == XmlNodeType.Element)
                 {
-                    case "name":
-                        {
-                            result.Name = reader.ReadElementContentAsString();
-                            break;
-                        }
-                    //case "sort-name":
-                    //    {
-                    //        break;
-                    //    }
-                    //case "tag-list":
-                    //    {
-                    //        break;
-                    //    }
-                    case "annotation":
-                        {
-                            result.Overview = reader.ReadElementContentAsString();
-                            break;
-                        }
-                    default:
-                        {
-                            reader.Skip();
-                            break;
-                        }
+                    switch (reader.Name)
+                    {
+                        case "name":
+                            {
+                                result.Name = reader.ReadElementContentAsString();
+                                break;
+                            }
+                        case "annotation":
+                            {
+                                result.Overview = reader.ReadElementContentAsString();
+                                break;
+                            }
+                        default:
+                            {
+                                // there is sort-name if ever needed
+                                reader.Skip();
+                                break;
+                            }
+                    }
+                }
+                else
+                {
+                    reader.Read();
                 }
             }