Ver código fonte

fixes #520 - Support multiple artists per audio track

Luke Pulverenti 11 anos atrás
pai
commit
44b12c0f9f

+ 25 - 4
MediaBrowser.Api/AlbumsService.cs

@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using ServiceStack.ServiceHost;
 using System;
+using System.Collections.Generic;
 using System.Linq;
 
 namespace MediaBrowser.Api
@@ -76,15 +77,35 @@ namespace MediaBrowser.Api
 
             var artists1 = album1.RecursiveChildren
                 .OfType<Audio>()
-                .SelectMany(i => new[] { i.AlbumArtist, i.Artist })
-                .Where(i => !string.IsNullOrEmpty(i))
+                .SelectMany(i =>
+                {
+                    var list = new List<string>();
+
+                    if (!string.IsNullOrEmpty(i.AlbumArtist))
+                    {
+                        list.Add(i.AlbumArtist);
+                    }
+                    list.AddRange(i.Artists);
+
+                    return list;
+                })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToList();
 
             var artists2 = album2.RecursiveChildren
                 .OfType<Audio>()
-                .SelectMany(i => new[] { i.AlbumArtist, i.Artist })
-                .Where(i => !string.IsNullOrEmpty(i))
+                .SelectMany(i =>
+                {
+                    var list = new List<string>();
+
+                    if (!string.IsNullOrEmpty(i.AlbumArtist))
+                    {
+                        list.Add(i.AlbumArtist);
+                    }
+                    list.AddRange(i.Artists);
+
+                    return list;
+                })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
 

+ 12 - 2
MediaBrowser.Api/BaseApiService.cs

@@ -140,8 +140,18 @@ namespace MediaBrowser.Api
             
             return libraryManager.RootFolder.RecursiveChildren
                 .OfType<Audio>()
-                .SelectMany(i => new[] { i.Artist, i.AlbumArtist })
-                .Where(i => !string.IsNullOrEmpty(i))
+                .SelectMany(i =>
+                {
+                    var list = new List<string>();
+
+                    if (!string.IsNullOrEmpty(i.AlbumArtist))
+                    {
+                        list.Add(i.AlbumArtist);
+                    }
+                    list.AddRange(i.Artists);
+
+                    return list;
+                })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .FirstOrDefault(i =>
                 {

+ 13 - 1
MediaBrowser.Api/ItemRefreshService.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using ServiceStack.ServiceHost;
 using System;
@@ -111,14 +112,25 @@ namespace MediaBrowser.Api
         {
             var item = await GetArtist(request.Name, _libraryManager).ConfigureAwait(false);
 
+            var cancellationToken = CancellationToken.None;
+
             try
             {
-                await item.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
+                await item.RefreshMetadata(cancellationToken, forceRefresh: request.Forced).ConfigureAwait(false);
             }
             catch (Exception ex)
             {
                 Logger.ErrorException("Error refreshing library", ex);
             }
+
+            // Refresh albums
+            var refreshTasks = _libraryManager.RootFolder
+                                              .RecursiveChildren
+                                              .OfType<MusicAlbum>()
+                                              .Where(i => i.HasArtist(item.Name))
+                                              .Select(i => i.ValidateChildren(new Progress<double>(), cancellationToken, true, request.Forced));
+
+            await Task.WhenAll(refreshTasks).ConfigureAwait(false);
         }
 
         public void Post(RefreshGenre request)

+ 1 - 1
MediaBrowser.Api/ItemUpdateService.cs

@@ -275,7 +275,7 @@ namespace MediaBrowser.Api
             {
                 song.Album = request.Album;
                 song.AlbumArtist = request.AlbumArtist;
-                song.Artist = request.Artists[0];
+                song.Artists = request.Artists.ToList();
             }
 
             var musicVideo = item as MusicVideo;

+ 2 - 3
MediaBrowser.Api/SearchService.cs

@@ -196,8 +196,7 @@ namespace MediaBrowser.Api
                 result.SongCount = songs.Count;
                 
                 result.Artists = songs
-                    .Select(i => i.Artist)
-                    .Where(i => !string.IsNullOrEmpty(i))
+                    .SelectMany(i => i.Artists)
                     .Distinct(StringComparer.OrdinalIgnoreCase)
                     .ToArray();
 
@@ -210,7 +209,7 @@ namespace MediaBrowser.Api
             {
                 result.Album = song.Album;
                 result.AlbumArtist = song.AlbumArtist;
-                result.Artists = !string.IsNullOrEmpty(song.Artist) ? new[] { song.Artist } : new string[] { };
+                result.Artists = song.Artists.ToArray();
             }
 
             return result;

+ 10 - 13
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -181,20 +181,17 @@ namespace MediaBrowser.Api.UserLibrary
 
             return itemsList
                 .SelectMany(i =>
+                {
+                    var list = new List<string>();
+
+                    if (!string.IsNullOrEmpty(i.AlbumArtist))
                     {
-                        var list = new List<string>();
-
-                        if (!string.IsNullOrEmpty(i.AlbumArtist))
-                        {
-                            list.Add(i.AlbumArtist);
-                        }
-                        if (!string.IsNullOrEmpty(i.Artist))
-                        {
-                            list.Add(i.Artist);
-                        }
-
-                        return list;
-                    })
+                        list.Add(i.AlbumArtist);
+                    }
+                    list.AddRange(i.Artists);
+
+                    return list;
+                })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .Select(name => new IbnStub<Artist>(name, () => itemsList.Where(i => i.HasArtist(name)), GetEntity));
         }

+ 4 - 2
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Runtime.Serialization;
 
 namespace MediaBrowser.Controller.Entities.Audio
@@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         public Audio()
         {
             MediaStreams = new List<MediaStream>();
+            Artists = new List<string>();
         }
 
         /// <summary>
@@ -57,7 +59,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         /// Gets or sets the artist.
         /// </summary>
         /// <value>The artist.</value>
-        public string Artist { get; set; }
+        public List<string> Artists { get; set; }
 
         /// <summary>
         /// Gets or sets the album.
@@ -99,7 +101,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         /// <returns><c>true</c> if the specified name has artist; otherwise, <c>false</c>.</returns>
         public bool HasArtist(string name)
         {
-            return string.Equals(Artist, name, StringComparison.OrdinalIgnoreCase) || string.Equals(AlbumArtist, name, StringComparison.OrdinalIgnoreCase);
+            return Artists.Contains(name, StringComparer.OrdinalIgnoreCase) || string.Equals(AlbumArtist, name, StringComparison.OrdinalIgnoreCase);
         }
     }
 }

+ 2 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -257,7 +257,7 @@ namespace MediaBrowser.Controller.Entities
                 {
                     var songs = recursiveChildren.OfType<Audio.Audio>().ToList();
 
-                    indexFolders = songs.Select(i => i.Artist ?? string.Empty)
+                    indexFolders = songs.SelectMany(i => i.Artists)
                         .Distinct(StringComparer.OrdinalIgnoreCase)
                     .Select(i =>
                     {
@@ -278,7 +278,7 @@ namespace MediaBrowser.Controller.Entities
                     })
                     .Where(i => i != null)
                     .Select(a => new IndexFolder(us, a,
-                                        songs.Where(i => string.Equals(i.Artist, a.Name, StringComparison.OrdinalIgnoreCase)
+                                        songs.Where(i => i.Artists.Contains(a.Name, StringComparer.OrdinalIgnoreCase)
                                         ), currentIndexName)).Concat(indexFolders);
                 }
 

+ 1 - 1
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.MediaInfo
             var album = item.Parent as MusicAlbum;
 
             var filename = item.Album ?? string.Empty;
-            filename += item.Artist ?? string.Empty;
+            filename += item.Artists.FirstOrDefault() ?? string.Empty;
             filename += album == null ? item.Id.ToString("N") + item.DateModified.Ticks : album.Id.ToString("N") + album.DateModified.Ticks;
 
             var path = ImageCache.GetResourcePath(filename + "_primary", ".jpg");

+ 23 - 10
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfoProvider.cs

@@ -128,7 +128,19 @@ namespace MediaBrowser.Providers.MediaInfo
 
             audio.Album = GetDictionaryValue(tags, "album");
 
-            audio.Artist = GetDictionaryValue(tags, "artist");
+            var artist = GetDictionaryValue(tags, "artist");
+
+            if (string.IsNullOrWhiteSpace(artist))
+            {
+                audio.Artists.Clear();
+            }
+            else
+            {
+                audio.Artists = Split(artist)
+                    .Distinct(StringComparer.OrdinalIgnoreCase)
+                    .ToList();
+
+            }
 
             // Several different forms of albumartist
             audio.AlbumArtist = GetDictionaryValue(tags, "albumartist") ?? GetDictionaryValue(tags, "album artist") ?? GetDictionaryValue(tags, "album_artist");
@@ -159,6 +171,8 @@ namespace MediaBrowser.Providers.MediaInfo
 
             if (!audio.LockedFields.Contains(MetadataFields.Studios))
             {
+                audio.Studios.Clear();
+
                 // There's several values in tags may or may not be present
                 FetchStudios(audio, tags, "organization");
                 FetchStudios(audio, tags, "ensemble");
@@ -166,6 +180,8 @@ namespace MediaBrowser.Providers.MediaInfo
             }
         }
 
+        private readonly char[] _nameDelimiters = new[] { '/', '|', ';', '\\' };
+
         /// <summary>
         /// Splits the specified val.
         /// </summary>
@@ -175,9 +191,10 @@ namespace MediaBrowser.Providers.MediaInfo
         {
             // Only use the comma as a delimeter if there are no slashes or pipes. 
             // We want to be careful not to split names that have commas in them
-            var delimeter = val.IndexOf('/') == -1 && val.IndexOf('|') == -1 ? new[] { ',' } : new[] { '/', '|' };
+            var delimeter = _nameDelimiters.Any(i => val.IndexOf(i) != -1) ? _nameDelimiters : new[] { ',' };
 
-            return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries);
+            return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
+                .Where(i => !string.IsNullOrWhiteSpace(i));
         }
 
         /// <summary>
@@ -194,11 +211,8 @@ namespace MediaBrowser.Providers.MediaInfo
             {
                 // Sometimes the artist name is listed here, account for that
                 var studios =
-                    val.Split(new[] { '/', '|' }, StringSplitOptions.RemoveEmptyEntries)
-                    .Where(i => !string.IsNullOrWhiteSpace(i))
-                    .Where(i => !string.Equals(i, audio.Artist, StringComparison.OrdinalIgnoreCase) && !string.Equals(i, audio.AlbumArtist, StringComparison.OrdinalIgnoreCase));
-
-                audio.Studios.Clear();
+                    Split(val)
+                    .Where(i => !audio.HasArtist(i));
 
                 foreach (var studio in studios)
                 {
@@ -221,8 +235,7 @@ namespace MediaBrowser.Providers.MediaInfo
             {
                 audio.Genres.Clear();
 
-                foreach (var genre in val
-                    .Split(new[] { '/', '|' }, StringSplitOptions.RemoveEmptyEntries)
+                foreach (var genre in Split(val)
                     .Where(i => !string.IsNullOrWhiteSpace(i)))
                 {
                     // Account for sloppy tags by trimming

+ 1 - 4
MediaBrowser.Providers/Music/ArtistsPostScanTask.cs

@@ -135,10 +135,7 @@ namespace MediaBrowser.Providers.Music
                     {
                         list.Add(i.AlbumArtist);
                     }
-                    if (!string.IsNullOrEmpty(i.Artist))
-                    {
-                        list.Add(i.Artist);
-                    }
+                    list.AddRange(i.Artists);
 
                     return list;
                 })

+ 2 - 3
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -893,7 +893,7 @@ namespace MediaBrowser.Server.Implementations.Dto
             {
                 dto.Album = audio.Album;
                 dto.AlbumArtist = audio.AlbumArtist;
-                dto.Artists = new[] { audio.Artist };
+                dto.Artists = audio.Artists.ToArray();
 
                 var albumParent = audio.FindParent<MusicAlbum>();
 
@@ -919,8 +919,7 @@ namespace MediaBrowser.Server.Implementations.Dto
                 dto.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i));
 
                 dto.Artists =
-                    songs.Select(i => i.Artist ?? string.Empty)
-                         .Where(i => !string.IsNullOrEmpty(i))
+                    songs.SelectMany(i => i.Artists)
                          .Distinct(StringComparer.OrdinalIgnoreCase)
                          .ToArray();
             }

+ 1 - 4
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -900,10 +900,7 @@ namespace MediaBrowser.Server.Implementations.Library
                     {
                         list.Add(c.AlbumArtist);
                     }
-                    if (!string.IsNullOrEmpty(c.Artist))
-                    {
-                        list.Add(c.Artist);
-                    }
+                    list.AddRange(c.Artists);
 
                     return list;
                 })

+ 12 - 2
MediaBrowser.Server.Implementations/Library/LuceneSearchEngine.cs

@@ -120,8 +120,18 @@ namespace MediaBrowser.Server.Implementations.Library
 
             // Find artists
             var artists = items.OfType<Audio>()
-                .SelectMany(i => new[] { i.Artist, i.AlbumArtist })
-                .Where(i => !string.IsNullOrEmpty(i))
+                .SelectMany(i =>
+                {
+                    var list = new List<string>();
+
+                    if (!string.IsNullOrEmpty(i.AlbumArtist))
+                    {
+                        list.Add(i.AlbumArtist);
+                    }
+                    list.AddRange(i.Artists);
+
+                    return list;
+                })
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToList();
 

+ 1 - 1
MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs

@@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
                 return string.Empty;
             }
 
-            return audio.Artist ?? string.Empty;
+            return audio.Artists.FirstOrDefault() ?? string.Empty;
         }
 
         /// <summary>