Browse Source

use music brainz values from audio files with bottom up refresh

Luke Pulverenti 11 years ago
parent
commit
12757d094b
37 changed files with 544 additions and 132 deletions
  1. 1 6
      MediaBrowser.Api/Images/ImageService.cs
  2. 1 7
      MediaBrowser.Api/Images/RemoteImageService.cs
  3. 10 1
      MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
  4. 26 1
      MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
  5. 25 0
      MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
  6. 8 3
      MediaBrowser.Controller/Entities/BaseItem.cs
  7. 25 1
      MediaBrowser.Controller/Entities/GameGenre.cs
  8. 25 0
      MediaBrowser.Controller/Entities/Genre.cs
  9. 28 3
      MediaBrowser.Controller/Entities/Person.cs
  10. 25 0
      MediaBrowser.Controller/Entities/Studio.cs
  11. 30 0
      MediaBrowser.Controller/Entities/User.cs
  12. 25 0
      MediaBrowser.Controller/Entities/Year.cs
  13. 25 0
      MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
  14. 25 0
      MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
  15. 25 0
      MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
  16. 25 0
      MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
  17. 20 2
      MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
  18. 1 1
      MediaBrowser.Controller/Providers/ILocalImageProvider.cs
  19. 3 4
      MediaBrowser.Model/Entities/MetadataProviders.cs
  20. 36 49
      MediaBrowser.Providers/All/LocalImageProvider.cs
  21. 4 4
      MediaBrowser.Providers/Manager/ItemImageProvider.cs
  22. 0 5
      MediaBrowser.Providers/Manager/MetadataService.cs
  23. 1 0
      MediaBrowser.Providers/MediaBrowser.Providers.csproj
  24. 5 0
      MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
  25. 67 0
      MediaBrowser.Providers/Music/Extensions.cs
  26. 13 9
      MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
  27. 2 2
      MediaBrowser.Providers/Music/FanArtArtistProvider.cs
  28. 3 1
      MediaBrowser.Providers/Music/LastFmImageProvider.cs
  29. 10 7
      MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
  30. 1 3
      MediaBrowser.Providers/Music/LastfmArtistProvider.cs
  31. 22 10
      MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
  32. 2 2
      MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
  33. 16 2
      MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
  34. 4 4
      MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs
  35. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  36. 1 1
      Nuget/MediaBrowser.Common.nuspec
  37. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 1 - 6
MediaBrowser.Api/Images/ImageService.cs

@@ -789,12 +789,7 @@ namespace MediaBrowser.Api.Images
 
 
                 await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
                 await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
 
 
-                await entity.RefreshMetadata(new MetadataRefreshOptions
-                {
-                    ImageRefreshMode = ImageRefreshMode.ValidationOnly,
-                    ForceSave = true
-
-                }, CancellationToken.None).ConfigureAwait(false);
+                await entity.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
             }
             }
         }
         }
     }
     }

+ 1 - 7
MediaBrowser.Api/Images/RemoteImageService.cs

@@ -281,13 +281,7 @@ namespace MediaBrowser.Api.Images
         {
         {
             await _providerManager.SaveImage(item, request.ImageUrl, null, request.Type, null, CancellationToken.None).ConfigureAwait(false);
             await _providerManager.SaveImage(item, request.ImageUrl, null, request.Type, null, CancellationToken.None).ConfigureAwait(false);
 
 
-            await item.RefreshMetadata(new MetadataRefreshOptions
-            {
-                ForceSave = true,
-                ImageRefreshMode = ImageRefreshMode.ValidationOnly,
-                MetadataRefreshMode = MetadataRefreshMode.None
-
-            }, CancellationToken.None).ConfigureAwait(false);
+            await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 10 - 1
MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs

@@ -22,6 +22,15 @@ namespace MediaBrowser.Controller.Entities.Audio
             Tags = new List<string>();
             Tags = new List<string>();
         }
         }
 
 
+        [IgnoreDataMember]
+        public MusicArtist MusicArtist
+        {
+            get
+            {
+                return Parents.OfType<MusicArtist>().FirstOrDefault();
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets or sets the tags.
         /// Gets or sets the tags.
         /// </summary>
         /// </summary>
@@ -99,7 +108,7 @@ namespace MediaBrowser.Controller.Entities.Audio
                 return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
                 return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
             }
             }
 
 
-            id = this.GetProviderId(MetadataProviders.Musicbrainz);
+            id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
 
             if (!string.IsNullOrEmpty(id))
             if (!string.IsNullOrEmpty(id))
             {
             {

+ 26 - 1
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -89,6 +89,31 @@ namespace MediaBrowser.Controller.Entities.Audio
             return GetUserDataKey(this);
             return GetUserDataKey(this);
         }
         }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>
@@ -96,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
         private static string GetUserDataKey(MusicArtist item)
         private static string GetUserDataKey(MusicArtist item)
         {
         {
-            var id = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!string.IsNullOrEmpty(id))
             if (!string.IsNullOrEmpty(id))
             {
             {

+ 25 - 0
MediaBrowser.Controller/Entities/Audio/MusicGenre.cs

@@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities.Audio
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
         public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 8 - 3
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities
         }
         }
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
-        public bool IsOwnedItem
+        public virtual bool IsOwnedItem
         {
         {
             get
             get
             {
             {
@@ -1215,7 +1215,12 @@ namespace MediaBrowser.Controller.Entities
                 currentFile.Delete();
                 currentFile.Delete();
             }
             }
 
 
-            return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, CancellationToken.None);
+            return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
+        }
+
+        public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
+        {
+            return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, cancellationToken);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1370,7 +1375,7 @@ namespace MediaBrowser.Controller.Entities
             info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path);
             info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path);
             info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path);
             info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path);
 
 
-            return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, CancellationToken.None);
+            return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
         }
         }
 
 
         public virtual bool IsPlayed(User user)
         public virtual bool IsPlayed(User user)

+ 25 - 1
MediaBrowser.Controller/Entities/GameGenre.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
 
 
@@ -23,5 +22,30 @@ namespace MediaBrowser.Controller.Entities
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
         public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 25 - 0
MediaBrowser.Controller/Entities/Genre.cs

@@ -25,5 +25,30 @@ namespace MediaBrowser.Controller.Entities
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
         public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 28 - 3
MediaBrowser.Controller/Entities/Person.cs

@@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
     /// <summary>
     /// <summary>
     /// This is the full Person object that can be retrieved with all of it's data.
     /// This is the full Person object that can be retrieved with all of it's data.
     /// </summary>
     /// </summary>
-    public class Person : BaseItem, IItemByName, IHasLookupInfo<Providers.PersonLookupInfo>
+    public class Person : BaseItem, IItemByName, IHasLookupInfo<PersonLookupInfo>
     {
     {
         public Person()
         public Person()
         {
         {
@@ -33,9 +33,34 @@ namespace MediaBrowser.Controller.Entities
             return "Person-" + Name;
             return "Person-" + Name;
         }
         }
 
 
-        public Providers.PersonLookupInfo GetLookupInfo()
+        public PersonLookupInfo GetLookupInfo()
         {
         {
-            return GetItemLookupInfo<Providers.PersonLookupInfo>();
+            return GetItemLookupInfo<PersonLookupInfo>();
+        }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
         }
         }
     }
     }
 
 

+ 25 - 0
MediaBrowser.Controller/Entities/Studio.cs

@@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
         public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 30 - 0
MediaBrowser.Controller/Entities/User.cs

@@ -72,6 +72,31 @@ namespace MediaBrowser.Controller.Entities
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// The _root folder
         /// The _root folder
         /// </summary>
         /// </summary>
@@ -222,6 +247,11 @@ namespace MediaBrowser.Controller.Entities
             }, CancellationToken.None);
             }, CancellationToken.None);
         }
         }
 
 
+        public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
+        {
+            return UserManager.UpdateUser(this);
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the path to the user's configuration directory
         /// Gets the path to the user's configuration directory
         /// </summary>
         /// </summary>

+ 25 - 0
MediaBrowser.Controller/Entities/Year.cs

@@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities
         {
         {
             return "Year-" + Name;
             return "Year-" + Name;
         }
         }
+
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 25 - 0
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs

@@ -25,6 +25,31 @@ namespace MediaBrowser.Controller.LiveTv
 
 
         public string ServiceName { get; set; }
         public string ServiceName { get; set; }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         public override string MediaType
         public override string MediaType
         {
         {
             get
             get

+ 25 - 0
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -25,6 +25,31 @@ namespace MediaBrowser.Controller.LiveTv
         [IgnoreDataMember]
         [IgnoreDataMember]
         public List<ItemByNameCounts> UserItemCountList { get; set; }
         public List<ItemByNameCounts> UserItemCountList { get; set; }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets or sets the number.
         /// Gets or sets the number.
         /// </summary>
         /// </summary>

+ 25 - 0
MediaBrowser.Controller/LiveTv/LiveTvProgram.cs

@@ -127,6 +127,31 @@ namespace MediaBrowser.Controller.LiveTv
         /// <value><c>true</c> if this instance is premiere; otherwise, <c>false</c>.</value>
         /// <value><c>true</c> if this instance is premiere; otherwise, <c>false</c>.</value>
         public bool IsPremiere { get; set; }
         public bool IsPremiere { get; set; }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         public override string MediaType
         public override string MediaType
         {
         {
             get
             get

+ 25 - 0
MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs

@@ -46,6 +46,31 @@ namespace MediaBrowser.Controller.LiveTv
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Returns the folder containing the item.
+        /// If the item is a folder, it returns the folder itself
+        /// </summary>
+        /// <value>The containing folder path.</value>
+        public override string ContainingFolderPath
+        {
+            get
+            {
+                return Path;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is owned item.
+        /// </summary>
+        /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value>
+        public override bool IsOwnedItem
+        {
+            get
+            {
+                return false;
+            }
+        }
+
         public override string GetClientTypeName()
         public override string GetClientTypeName()
         {
         {
             return "Recording";
             return "Recording";

+ 20 - 2
MediaBrowser.Controller/Providers/BaseItemXmlParser.cs

@@ -680,12 +680,30 @@ namespace MediaBrowser.Controller.Providers
                         }
                         }
                         break;
                         break;
                     }
                     }
-                case "MusicbrainzId":
+                case "MusicBrainzAlbumId":
                     {
                     {
                         var mbz = reader.ReadElementContentAsString();
                         var mbz = reader.ReadElementContentAsString();
                         if (!string.IsNullOrWhiteSpace(mbz))
                         if (!string.IsNullOrWhiteSpace(mbz))
                         {
                         {
-                            item.SetProviderId(MetadataProviders.Musicbrainz, mbz);
+                            item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz);
+                        }
+                        break;
+                    }
+                case "MusicBrainzAlbumArtistId":
+                    {
+                        var mbz = reader.ReadElementContentAsString();
+                        if (!string.IsNullOrWhiteSpace(mbz))
+                        {
+                            item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mbz);
+                        }
+                        break;
+                    }
+                case "MusicBrainzArtistId":
+                    {
+                        var mbz = reader.ReadElementContentAsString();
+                        if (!string.IsNullOrWhiteSpace(mbz))
+                        {
+                            item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz);
                         }
                         }
                         break;
                         break;
                     }
                     }

+ 1 - 1
MediaBrowser.Controller/Providers/ILocalImageProvider.cs

@@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Providers
 
 
     public class LocalImageInfo
     public class LocalImageInfo
     {
     {
-        public string Path { get; set; }
+        public FileInfo FileInfo { get; set; }
         public ImageType Type { get; set; }
         public ImageType Type { get; set; }
     }
     }
 
 

+ 3 - 4
MediaBrowser.Model/Entities/MetadataProviders.cs

@@ -24,10 +24,6 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// </summary>
         Tvcom,
         Tvcom,
         /// <summary>
         /// <summary>
-        /// MusicBrainz
-        /// </summary>
-        Musicbrainz,
-        /// <summary>
         /// The rotten tomatoes
         /// The rotten tomatoes
         /// </summary>
         /// </summary>
         RottenTomatoes,
         RottenTomatoes,
@@ -35,6 +31,9 @@ namespace MediaBrowser.Model.Entities
         /// Tmdb Collection Id
         /// Tmdb Collection Id
         /// </summary>
         /// </summary>
         TmdbCollection,
         TmdbCollection,
+        MusicBrainzAlbum,
+        MusicBrainzAlbumArtist,
+        MusicBrainzArtist,
         MusicBrainzReleaseGroup,
         MusicBrainzReleaseGroup,
         Zap2It,
         Zap2It,
         NesBox,
         NesBox,

+ 36 - 49
MediaBrowser.Providers/All/LocalImageProvider.cs

@@ -65,25 +65,29 @@ namespace MediaBrowser.Providers.All
             return false;
             return false;
         }
         }
 
 
-        private IEnumerable<string> GetFiles(IHasImages item, bool includeDirectories)
+        private IEnumerable<FileSystemInfo> GetFiles(IHasImages item, bool includeDirectories)
         {
         {
             if (item.LocationType != LocationType.FileSystem)
             if (item.LocationType != LocationType.FileSystem)
             {
             {
-                return new List<string>();
+                return new List<FileSystemInfo>();
             }
             }
 
 
             var path = item.ContainingFolderPath;
             var path = item.ContainingFolderPath;
 
 
             if (includeDirectories)
             if (includeDirectories)
             {
             {
-                return Directory.EnumerateFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly);
+                return new DirectoryInfo(path).EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly)
+                .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) ||
+                (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory);
             }
             }
-            return Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
+
+            return new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+                .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase));
         }
         }
 
 
         public List<LocalImageInfo> GetImages(IHasImages item)
         public List<LocalImageInfo> GetImages(IHasImages item)
         {
         {
-            var files = GetFileDictionary(GetFiles(item, true));
+            var files = GetFiles(item, true).ToList();
 
 
             var list = new List<LocalImageInfo>();
             var list = new List<LocalImageInfo>();
 
 
@@ -92,7 +96,7 @@ namespace MediaBrowser.Providers.All
             return list;
             return list;
         }
         }
 
 
-        private void PopulateImages(IHasImages item, List<LocalImageInfo> images, Dictionary<string, string> files)
+        private void PopulateImages(IHasImages item, List<LocalImageInfo> images, List<FileSystemInfo> files)
         {
         {
             var imagePrefix = string.Empty;
             var imagePrefix = string.Empty;
 
 
@@ -130,7 +134,7 @@ namespace MediaBrowser.Providers.All
             }
             }
         }
         }
 
 
-        private void PopulatePrimaryImages(IHasImages item, List<LocalImageInfo> images, Dictionary<string, string> files, string imagePrefix)
+        private void PopulatePrimaryImages(IHasImages item, List<LocalImageInfo> images, List<FileSystemInfo> files, string imagePrefix)
         {
         {
             AddImage(files, images, imagePrefix + "folder", ImageType.Primary);
             AddImage(files, images, imagePrefix + "folder", ImageType.Primary);
             AddImage(files, images, imagePrefix + "cover", ImageType.Primary);
             AddImage(files, images, imagePrefix + "cover", ImageType.Primary);
@@ -161,7 +165,7 @@ namespace MediaBrowser.Providers.All
             }
             }
         }
         }
 
 
-        private void PopulateBackdrops(IHasImages item, List<LocalImageInfo> images, Dictionary<string, string> files, string imagePrefix)
+        private void PopulateBackdrops(IHasImages item, List<LocalImageInfo> images, List<FileSystemInfo> files, string imagePrefix)
         {
         {
             PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", ImageType.Backdrop);
             PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", ImageType.Backdrop);
 
 
@@ -179,19 +183,21 @@ namespace MediaBrowser.Providers.All
             PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop);
             PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop);
             PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop);
             PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop);
 
 
-            string extraFanartFolder;
-            if (files.TryGetValue("extrafanart", out extraFanartFolder))
+            var extraFanartFolder = files.OfType<DirectoryInfo>()
+                .FirstOrDefault(i => string.Equals(i.Name, "extrafanart", StringComparison.OrdinalIgnoreCase));
+
+            if (extraFanartFolder != null)
             {
             {
-                PopulateBackdropsFromExtraFanart(extraFanartFolder, images);
+                PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images);
             }
             }
         }
         }
 
 
         private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images)
         private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images)
         {
         {
-            var imageFiles = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly)
+            var imageFiles = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
                 .Where(i =>
                 .Where(i =>
                 {
                 {
-                    var extension = Path.GetExtension(i);
+                    var extension = i.Extension;
 
 
                     if (string.IsNullOrEmpty(extension))
                     if (string.IsNullOrEmpty(extension))
                     {
                     {
@@ -203,17 +209,17 @@ namespace MediaBrowser.Providers.All
 
 
             images.AddRange(imageFiles.Select(i => new LocalImageInfo
             images.AddRange(imageFiles.Select(i => new LocalImageInfo
             {
             {
-                Path = i,
+                FileInfo = i,
                 Type = ImageType.Backdrop
                 Type = ImageType.Backdrop
             }));
             }));
         }
         }
 
 
-        private void PopulateScreenshots(List<LocalImageInfo> images, Dictionary<string, string> files, string imagePrefix)
+        private void PopulateScreenshots(List<LocalImageInfo> images, List<FileSystemInfo> files, string imagePrefix)
         {
         {
             PopulateBackdrops(images, files, imagePrefix, "screenshot", "screenshot", ImageType.Screenshot);
             PopulateBackdrops(images, files, imagePrefix, "screenshot", "screenshot", ImageType.Screenshot);
         }
         }
 
 
-        private void PopulateBackdrops(List<LocalImageInfo> images, Dictionary<string, string> files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type)
+        private void PopulateBackdrops(List<LocalImageInfo> images, List<FileSystemInfo> files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type)
         {
         {
             AddImage(files, images, imagePrefix + firstFileName, type);
             AddImage(files, images, imagePrefix + firstFileName, type);
 
 
@@ -246,7 +252,7 @@ namespace MediaBrowser.Providers.All
                 return;
                 return;
             }
             }
 
 
-            var files = GetFileDictionary(GetFiles(series, false));
+            var seriesFiles = GetFiles(series, false).ToList();
 
 
             // Try using the season name
             // Try using the season name
             var prefix = season.Name.ToLower().Replace(" ", string.Empty);
             var prefix = season.Name.ToLower().Replace(" ", string.Empty);
@@ -265,39 +271,22 @@ namespace MediaBrowser.Providers.All
 
 
             foreach (var filename in filenamePrefixes)
             foreach (var filename in filenamePrefixes)
             {
             {
-                AddImage(files, images, filename + "-poster", ImageType.Primary);
-                AddImage(files, images, filename + "-fanart", ImageType.Backdrop);
-                AddImage(files, images, filename + "-banner", ImageType.Banner);
-                AddImage(files, images, filename + "-landscape", ImageType.Thumb);
+                AddImage(seriesFiles, images, filename + "-poster", ImageType.Primary);
+                AddImage(seriesFiles, images, filename + "-fanart", ImageType.Backdrop);
+                AddImage(seriesFiles, images, filename + "-banner", ImageType.Banner);
+                AddImage(seriesFiles, images, filename + "-landscape", ImageType.Thumb);
             }
             }
         }
         }
 
 
-        private Dictionary<string, string> GetFileDictionary(IEnumerable<string> paths)
+        private bool AddImage(List<FileSystemInfo> files, List<LocalImageInfo> images, string name, ImageType type)
         {
         {
-            var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
-            foreach (var path in paths)
-            {
-                var filename = Path.GetFileName(path);
-
-                if (!string.IsNullOrEmpty(filename))
-                {
-                    dict[filename] = path;
-                }
-            }
-
-            return dict;
-        }
-
-        private bool AddImage(Dictionary<string, string> dict, List<LocalImageInfo> images, string name, ImageType type)
-        {
-            var image = GetImage(dict, name);
+            var image = GetImage(files, name) as FileInfo;
 
 
             if (image != null)
             if (image != null)
             {
             {
                 images.Add(new LocalImageInfo
                 images.Add(new LocalImageInfo
                 {
                 {
-                    Path = image,
+                    FileInfo = image,
                     Type = type
                     Type = type
                 });
                 });
 
 
@@ -307,16 +296,14 @@ namespace MediaBrowser.Providers.All
             return false;
             return false;
         }
         }
 
 
-        private string GetImage(Dictionary<string, string> dict, string name)
+        private FileSystemInfo GetImage(IEnumerable<FileSystemInfo> files, string name)
         {
         {
-            return BaseItem.SupportedImageExtensions
-                .Select(i =>
-                {
-                    var filename = name + i;
-                    string path;
+            var candidates = files
+                .Where(i => string.Equals(name, Path.GetFileNameWithoutExtension(i.Name), StringComparison.OrdinalIgnoreCase))
+                .ToList();
 
 
-                    return dict.TryGetValue(filename, out path) ? path : null;
-                })
+            return BaseItem.SupportedImageExtensions
+                .Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase)))
                 .FirstOrDefault(i => i != null);
                 .FirstOrDefault(i => i != null);
         }
         }
     }
     }

+ 4 - 4
MediaBrowser.Providers/Manager/ItemImageProvider.cs

@@ -275,9 +275,9 @@ namespace MediaBrowser.Providers.Manager
                 {
                 {
                     var currentImage = item.GetImageInfo(type, 0);
                     var currentImage = item.GetImageInfo(type, 0);
 
 
-                    if (currentImage == null || !string.Equals(currentImage.Path, image.Path, StringComparison.OrdinalIgnoreCase))
+                    if (currentImage == null || !string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
                     {
                     {
-                        item.SetImagePath(type, new FileInfo(image.Path));
+                        item.SetImagePath(type, image.FileInfo);
                         changed = true;
                         changed = true;
                     }
                     }
                 }
                 }
@@ -287,7 +287,7 @@ namespace MediaBrowser.Providers.Manager
             if (backdrops.Count > 0)
             if (backdrops.Count > 0)
             {
             {
                 var foundImages = images.Where(i => i.Type == ImageType.Backdrop)
                 var foundImages = images.Where(i => i.Type == ImageType.Backdrop)
-                    .Select(i => new FileInfo(i.Path))
+                    .Select(i => i.FileInfo)
                     .ToList();
                     .ToList();
 
 
                 if (foundImages.Count > 0)
                 if (foundImages.Count > 0)
@@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.Manager
             if (hasScreenshots != null)
             if (hasScreenshots != null)
             {
             {
                 var foundImages = images.Where(i => i.Type == ImageType.Screenshot)
                 var foundImages = images.Where(i => i.Type == ImageType.Screenshot)
-                    .Select(i => new FileInfo(i.Path))
+                    .Select(i => i.FileInfo)
                     .ToList();
                     .ToList();
 
 
                 if (foundImages.Count > 0)
                 if (foundImages.Count > 0)

+ 0 - 5
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -197,11 +197,6 @@ namespace MediaBrowser.Providers.Manager
                     .Where(i => i.HasChanged(currentItem, currentItem.DateLastSaved))
                     .Where(i => i.HasChanged(currentItem, currentItem.DateLastSaved))
                     .ToList();
                     .ToList();
 
 
-                if (providersWithChanges.Count > 0)
-                {
-                    var b = true;
-                }
-
                 // If local providers are the only ones with changes, then just run those
                 // If local providers are the only ones with changes, then just run those
                 if (providersWithChanges.All(i => i is ILocalMetadataProvider))
                 if (providersWithChanges.All(i => i is ILocalMetadataProvider))
                 {
                 {

+ 1 - 0
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -117,6 +117,7 @@
     <Compile Include="Music\AlbumMetadataService.cs" />
     <Compile Include="Music\AlbumMetadataService.cs" />
     <Compile Include="Music\ArtistMetadataService.cs" />
     <Compile Include="Music\ArtistMetadataService.cs" />
     <Compile Include="Music\AudioMetadataService.cs" />
     <Compile Include="Music\AudioMetadataService.cs" />
+    <Compile Include="Music\Extensions.cs" />
     <Compile Include="Music\LastfmArtistProvider.cs" />
     <Compile Include="Music\LastfmArtistProvider.cs" />
     <Compile Include="Music\MovieDbMusicVideoProvider.cs" />
     <Compile Include="Music\MovieDbMusicVideoProvider.cs" />
     <Compile Include="Music\MusicBrainzArtistProvider.cs" />
     <Compile Include="Music\MusicBrainzArtistProvider.cs" />

+ 5 - 0
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs

@@ -178,6 +178,11 @@ namespace MediaBrowser.Providers.MediaInfo
                 FetchStudios(audio, tags, "ensemble");
                 FetchStudios(audio, tags, "ensemble");
                 FetchStudios(audio, tags, "publisher");
                 FetchStudios(audio, tags, "publisher");
             }
             }
+
+            audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id"));
+            audio.SetProviderId(MetadataProviders.MusicBrainzArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id"));
+            audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id"));
+            audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id"));
         }
         }
 
 
         private readonly char[] _nameDelimiters = new[] { '/', '|', ';', '\\' };
         private readonly char[] _nameDelimiters = new[] { '/', '|', ';', '\\' };

+ 67 - 0
MediaBrowser.Providers/Music/Extensions.cs

@@ -0,0 +1,67 @@
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System.Linq;
+
+namespace MediaBrowser.Providers.Music
+{
+    public static class Extensions
+    {
+        public static string GetAlbumArtist(this AlbumInfo info)
+        {
+            var id = info.AlbumArtist;
+
+            if (string.IsNullOrEmpty(id))
+            {
+                return info.SongInfos.Select(i => i.AlbumArtist)
+                    .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+            }
+
+            return id;
+        }
+
+        public static string GetReleaseGroupId(this AlbumInfo info)
+        {
+            var id = info.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+            if (string.IsNullOrEmpty(id))
+            {
+                return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup))
+                    .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+            }
+
+            return id;
+        }
+
+        public static string GetReleaseId(this AlbumInfo info)
+        {
+            var id = info.GetProviderId(MetadataProviders.MusicBrainzAlbum);
+
+            if (string.IsNullOrEmpty(id))
+            {
+                return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbum))
+                    .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+            }
+
+            return id;
+        }
+
+        public static string GetArtistId(this AlbumInfo info)
+        {
+            string id;
+            info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzAlbumArtist.ToString(), out id);
+
+            if (string.IsNullOrEmpty(id))
+            {
+                info.ArtistProviderIds.TryGetValue(MetadataProviders.MusicBrainzArtist.ToString(), out id);
+            }
+            
+            if (string.IsNullOrEmpty(id))
+            {
+                return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist))
+                    .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+            }
+
+            return id;
+        }
+    }
+}

+ 13 - 9
MediaBrowser.Providers/Music/FanArtAlbumProvider.cs

@@ -70,7 +70,7 @@ namespace MediaBrowser.Providers.Music
 
 
             var list = new List<RemoteImageInfo>();
             var list = new List<RemoteImageInfo>();
 
 
-            var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
+            var artistMusicBrainzId = album.MusicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!string.IsNullOrEmpty(artistMusicBrainzId))
             if (!string.IsNullOrEmpty(artistMusicBrainzId))
             {
             {
@@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.Music
 
 
                 var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
                 var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
 
 
-                var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz);
+                var musicBrainzId = album.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
 
                 try
                 try
                 {
                 {
@@ -365,17 +365,21 @@ namespace MediaBrowser.Providers.Music
             }
             }
 
 
             var album = (MusicAlbum)item;
             var album = (MusicAlbum)item;
+            var artist = album.MusicArtist;
 
 
-            var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
-
-            if (!String.IsNullOrEmpty(artistMusicBrainzId))
+            if (artist != null)
             {
             {
-                // Process images
-                var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
+                var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
-                var fileInfo = new FileInfo(artistXmlPath);
+                if (!String.IsNullOrEmpty(artistMusicBrainzId))
+                {
+                    // Process images
+                    var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
 
 
-                return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
+                    var fileInfo = new FileInfo(artistXmlPath);
+
+                    return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
+                }
             }
             }
 
 
             return false;
             return false;

+ 2 - 2
MediaBrowser.Providers/Music/FanArtArtistProvider.cs

@@ -82,7 +82,7 @@ namespace MediaBrowser.Providers.Music
 
 
             var list = new List<RemoteImageInfo>();
             var list = new List<RemoteImageInfo>();
 
 
-            var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
+            var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!String.IsNullOrEmpty(artistMusicBrainzId))
             if (!String.IsNullOrEmpty(artistMusicBrainzId))
             {
             {
@@ -381,7 +381,7 @@ namespace MediaBrowser.Providers.Music
                 return false;
                 return false;
             }
             }
 
 
-            var id = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!String.IsNullOrEmpty(id))
             if (!String.IsNullOrEmpty(id))
             {
             {

+ 3 - 1
MediaBrowser.Providers/Music/LastFmImageProvider.cs

@@ -61,7 +61,9 @@ namespace MediaBrowser.Providers.Music
 
 
             RemoteImageInfo info = null;
             RemoteImageInfo info = null;
 
 
-            var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var musicBrainzId = item is MusicAlbum ?
+                item.GetProviderId(MetadataProviders.MusicBrainzAlbum) :
+                item.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!string.IsNullOrEmpty(musicBrainzId))
             if (!string.IsNullOrEmpty(musicBrainzId))
             {
             {

+ 10 - 7
MediaBrowser.Providers/Music/LastfmAlbumProvider.cs

@@ -48,9 +48,10 @@ namespace MediaBrowser.Providers.Music
         private async Task<LastfmGetAlbumResult> GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken)
         private async Task<LastfmGetAlbumResult> GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken)
         {
         {
             // Try album release Id
             // Try album release Id
-            if (!string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz)))
+            var id = item.GetReleaseId();
+            if (!string.IsNullOrEmpty(id))
             {
             {
-                var result = await GetAlbumResult(item.GetProviderId(MetadataProviders.Musicbrainz), cancellationToken).ConfigureAwait(false);
+                var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false);
 
 
                 if (result != null && result.album != null)
                 if (result != null && result.album != null)
                 {
                 {
@@ -59,9 +60,10 @@ namespace MediaBrowser.Providers.Music
             }
             }
 
 
             // Try album release group Id
             // Try album release group Id
-            if (!string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup)))
+            id = item.GetReleaseGroupId();
+            if (!string.IsNullOrEmpty(id))
             {
             {
-                var result = await GetAlbumResult(item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup), cancellationToken).ConfigureAwait(false);
+                var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false);
 
 
                 if (result != null && result.album != null)
                 if (result != null && result.album != null)
                 {
                 {
@@ -69,6 +71,7 @@ namespace MediaBrowser.Providers.Music
                 }
                 }
             }
             }
 
 
+            var albumArtist = item.GetAlbumArtist();
             //// Get each song, distinct by the combination of AlbumArtist and Album
             //// Get each song, distinct by the combination of AlbumArtist and Album
             //var songs = item.RecursiveChildren.OfType<Audio>().DistinctBy(i => (i.AlbumArtist ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
             //var songs = item.RecursiveChildren.OfType<Audio>().DistinctBy(i => (i.AlbumArtist ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
 
 
@@ -82,12 +85,12 @@ namespace MediaBrowser.Providers.Music
             //    }
             //    }
             //}
             //}
 
 
-            if (string.IsNullOrEmpty(item.AlbumArtist))
+            if (string.IsNullOrEmpty(albumArtist))
             {
             {
                 return null;
                 return null;
             }
             }
 
 
-            return await GetAlbumResult(item.AlbumArtist, item.Name, cancellationToken);
+            return await GetAlbumResult(albumArtist, item.Name, cancellationToken);
         }
         }
 
 
         private async Task<LastfmGetAlbumResult> GetAlbumResult(string artist, string album, CancellationToken cancellationToken)
         private async Task<LastfmGetAlbumResult> GetAlbumResult(string artist, string album, CancellationToken cancellationToken)
@@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.Music
             string imageSize;
             string imageSize;
             var url = LastfmHelper.GetImageUrl(data, out imageSize);
             var url = LastfmHelper.GetImageUrl(data, out imageSize);
 
 
-            var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz) ??
+            var musicBrainzId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum) ??
                 item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
                 item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
 
 
             LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
             LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);

+ 1 - 3
MediaBrowser.Providers/Music/LastfmArtistProvider.cs

@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music
         {
         {
             var result = new MetadataResult<MusicArtist>();
             var result = new MetadataResult<MusicArtist>();
 
 
-            var musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz);
+            var musicBrainzId = id.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
 
             if (!String.IsNullOrWhiteSpace(musicBrainzId))
             if (!String.IsNullOrWhiteSpace(musicBrainzId))
             {
             {
@@ -51,8 +51,6 @@ namespace MediaBrowser.Providers.Music
                 result.Item = new MusicArtist();
                 result.Item = new MusicArtist();
                 result.HasMetadata = true;
                 result.HasMetadata = true;
 
 
-                result.Item.SetProviderId(MetadataProviders.Musicbrainz, musicBrainzId);
-
                 await FetchLastfmData(result.Item, musicBrainzId, cancellationToken).ConfigureAwait(false);
                 await FetchLastfmData(result.Item, musicBrainzId, cancellationToken).ConfigureAwait(false);
             }
             }
 
 

+ 22 - 10
MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs

@@ -29,26 +29,25 @@ namespace MediaBrowser.Providers.Music
 
 
         public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
         public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
         {
         {
-            var albumId = id;
-            var releaseId = albumId.GetProviderId(MetadataProviders.Musicbrainz);
-            var releaseGroupId = albumId.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+            var releaseId = id.GetReleaseId();
+            var releaseGroupId = id.GetReleaseGroupId();
 
 
-            var result = new MetadataResult<MusicAlbum>();
+            var result = new MetadataResult<MusicAlbum>
+            {
+                Item = new MusicAlbum()
+            };
 
 
             if (string.IsNullOrEmpty(releaseId))
             if (string.IsNullOrEmpty(releaseId))
             {
             {
-                string artistMusicBrainzId;
-                albumId.ArtistProviderIds.TryGetValue(MetadataProviders.Musicbrainz.ToString(), out artistMusicBrainzId);
-
-                var releaseResult = await GetReleaseResult(artistMusicBrainzId, albumId.AlbumArtist, albumId.Name, cancellationToken).ConfigureAwait(false);
+                var artistMusicBrainzId = id.GetArtistId();
 
 
-                result.Item = new MusicAlbum();
+                var releaseResult = await GetReleaseResult(artistMusicBrainzId, id.GetAlbumArtist(), id.Name, cancellationToken).ConfigureAwait(false);
 
 
                 if (!string.IsNullOrEmpty(releaseResult.ReleaseId))
                 if (!string.IsNullOrEmpty(releaseResult.ReleaseId))
                 {
                 {
                     releaseId = releaseResult.ReleaseId;
                     releaseId = releaseResult.ReleaseId;
                     result.HasMetadata = true;
                     result.HasMetadata = true;
-                    result.Item.SetProviderId(MetadataProviders.Musicbrainz, releaseId);
+                    result.Item.SetProviderId(MetadataProviders.MusicBrainzAlbum, releaseId);
                 }
                 }
 
 
                 if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId))
                 if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId))
@@ -67,6 +66,19 @@ namespace MediaBrowser.Providers.Music
                 result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
                 result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
             }
             }
 
 
+            if (result.HasMetadata)
+            {
+                if (!string.IsNullOrEmpty(releaseId))
+                {
+                    result.Item.SetProviderId(MetadataProviders.MusicBrainzAlbum, releaseId);
+                }
+
+                if (!string.IsNullOrEmpty(releaseGroupId))
+                {
+                    result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId);
+                }
+            }
+
             return result;
             return result;
         }
         }
 
 

+ 2 - 2
MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs

@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music
         {
         {
             var result = new MetadataResult<MusicArtist>();
             var result = new MetadataResult<MusicArtist>();
            
            
-            var musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(id, cancellationToken).ConfigureAwait(false);
+            var musicBrainzId = id.GetProviderId(MetadataProviders.MusicBrainzArtist) ?? await FindId(id, cancellationToken).ConfigureAwait(false);
 
 
             if (!string.IsNullOrWhiteSpace(musicBrainzId))
             if (!string.IsNullOrWhiteSpace(musicBrainzId))
             {
             {
@@ -27,7 +27,7 @@ namespace MediaBrowser.Providers.Music
                 result.Item = new MusicArtist();
                 result.Item = new MusicArtist();
                 result.HasMetadata = true;
                 result.HasMetadata = true;
 
 
-                result.Item.SetProviderId(MetadataProviders.Musicbrainz, musicBrainzId);
+                result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId);
             }
             }
 
 
             return result;
             return result;

+ 16 - 2
MediaBrowser.Providers/Savers/XmlSaverHelpers.cs

@@ -415,11 +415,25 @@ namespace MediaBrowser.Providers.Savers
                 builder.Append("<Zap2ItId>" + SecurityElement.Escape(zap2It) + "</Zap2ItId>");
                 builder.Append("<Zap2ItId>" + SecurityElement.Escape(zap2It) + "</Zap2ItId>");
             }
             }
 
 
-            var mbz = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var mbz = item.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
 
             if (!string.IsNullOrEmpty(mbz))
             if (!string.IsNullOrEmpty(mbz))
             {
             {
-                builder.Append("<MusicbrainzId>" + SecurityElement.Escape(mbz) + "</MusicbrainzId>");
+                builder.Append("<MusicBrainzAlbumId>" + SecurityElement.Escape(mbz) + "</MusicBrainzAlbumId>");
+            }
+
+            mbz = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist);
+
+            if (!string.IsNullOrEmpty(mbz))
+            {
+                builder.Append("<MusicBrainzAlbumArtistId>" + SecurityElement.Escape(mbz) + "</MusicBrainzAlbumArtistId>");
+            }
+
+            mbz = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
+
+            if (!string.IsNullOrEmpty(mbz))
+            {
+                builder.Append("<MusicBrainzArtistId>" + SecurityElement.Escape(mbz) + "</MusicBrainzArtistId>");
             }
             }
 
 
             mbz = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
             mbz = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);

+ 4 - 4
MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs

@@ -28,12 +28,12 @@ namespace MediaBrowser.Providers.TV
             var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path);
             var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path);
             var thumbName = nameWithoutExtension + "-thumb";
             var thumbName = nameWithoutExtension + "-thumb";
 
 
-            return Directory.EnumerateFiles(parentPath, "*", SearchOption.AllDirectories)
+            return new DirectoryInfo(parentPath).EnumerateFiles("*", SearchOption.AllDirectories)
                 .Where(i =>
                 .Where(i =>
                 {
                 {
-                    if (BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i) ?? string.Empty))
+                    if (BaseItem.SupportedImageExtensions.Contains(i.Extension))
                     {
                     {
-                        var currentNameWithoutExtension = Path.GetFileNameWithoutExtension(i);
+                        var currentNameWithoutExtension = Path.GetFileNameWithoutExtension(i.Name);
 
 
                         if (string.Equals(nameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
                         if (string.Equals(nameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
                         {
                         {
@@ -50,7 +50,7 @@ namespace MediaBrowser.Providers.TV
                 })
                 })
                 .Select(i => new LocalImageInfo
                 .Select(i => new LocalImageInfo
                 {
                 {
-                    Path = i,
+                    FileInfo = i,
                     Type = ImageType.Primary
                     Type = ImageType.Primary
                 })
                 })
                 .ToList();
                 .ToList();

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.320</version>
+        <version>3.0.321</version>
         <title>MediaBrowser.Common.Internal</title>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.320" />
+            <dependency id="MediaBrowser.Common" version="3.0.321" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="SimpleInjector" version="2.4.1" />
             <dependency id="SimpleInjector" version="2.4.1" />
             <dependency id="sharpcompress" version="0.10.2" />
             <dependency id="sharpcompress" version="0.10.2" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common</id>
         <id>MediaBrowser.Common</id>
-        <version>3.0.320</version>
+        <version>3.0.321</version>
         <title>MediaBrowser.Common</title>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Server.Core</id>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.320</version>
+        <version>3.0.321</version>
         <title>Media Browser.Server.Core</title>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.320" />
+            <dependency id="MediaBrowser.Common" version="3.0.321" />
         </dependencies>
         </dependencies>
     </metadata>
     </metadata>
     <files>
     <files>