Browse Source

use music brainz values from audio files with bottom up refresh

Luke Pulverenti 11 năm trước cách đây
mục cha
commit
12757d094b
37 tập tin đã thay đổi với 544 bổ sung132 xóa
  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 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 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>

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

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

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

@@ -89,6 +89,31 @@ namespace MediaBrowser.Controller.Entities.Audio
             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>
         /// Gets the user data key.
         /// </summary>
@@ -96,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         /// <returns>System.String.</returns>
         private static string GetUserDataKey(MusicArtist item)
         {
-            var id = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
             if (!string.IsNullOrEmpty(id))
             {

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

@@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities.Audio
 
         [IgnoreDataMember]
         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]
-        public bool IsOwnedItem
+        public virtual bool IsOwnedItem
         {
             get
             {
@@ -1215,7 +1215,12 @@ namespace MediaBrowser.Controller.Entities
                 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>
@@ -1370,7 +1375,7 @@ namespace MediaBrowser.Controller.Entities
             info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.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)

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

@@ -1,5 +1,4 @@
 using MediaBrowser.Model.Dto;
-using System;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
 
@@ -23,5 +22,30 @@ namespace MediaBrowser.Controller.Entities
 
         [IgnoreDataMember]
         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]
         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>
     /// This is the full Person object that can be retrieved with all of it's data.
     /// </summary>
-    public class Person : BaseItem, IItemByName, IHasLookupInfo<Providers.PersonLookupInfo>
+    public class Person : BaseItem, IItemByName, IHasLookupInfo<PersonLookupInfo>
     {
         public Person()
         {
@@ -33,9 +33,34 @@ namespace MediaBrowser.Controller.Entities
             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]
         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>
         /// The _root folder
         /// </summary>
@@ -222,6 +247,11 @@ namespace MediaBrowser.Controller.Entities
             }, CancellationToken.None);
         }
 
+        public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
+        {
+            return UserManager.UpdateUser(this);
+        }
+
         /// <summary>
         /// Gets the path to the user's configuration directory
         /// </summary>

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

@@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities
         {
             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; }
 
+        /// <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
         {
             get

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

@@ -25,6 +25,31 @@ namespace MediaBrowser.Controller.LiveTv
         [IgnoreDataMember]
         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>
         /// Gets or sets the number.
         /// </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>
         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
         {
             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()
         {
             return "Recording";

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

@@ -680,12 +680,30 @@ namespace MediaBrowser.Controller.Providers
                         }
                         break;
                     }
-                case "MusicbrainzId":
+                case "MusicBrainzAlbumId":
                     {
                         var mbz = reader.ReadElementContentAsString();
                         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;
                     }

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

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

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

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

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

@@ -65,25 +65,29 @@ namespace MediaBrowser.Providers.All
             return false;
         }
 
-        private IEnumerable<string> GetFiles(IHasImages item, bool includeDirectories)
+        private IEnumerable<FileSystemInfo> GetFiles(IHasImages item, bool includeDirectories)
         {
             if (item.LocationType != LocationType.FileSystem)
             {
-                return new List<string>();
+                return new List<FileSystemInfo>();
             }
 
             var path = item.ContainingFolderPath;
 
             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)
         {
-            var files = GetFileDictionary(GetFiles(item, true));
+            var files = GetFiles(item, true).ToList();
 
             var list = new List<LocalImageInfo>();
 
@@ -92,7 +96,7 @@ namespace MediaBrowser.Providers.All
             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;
 
@@ -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 + "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);
 
@@ -179,19 +183,21 @@ namespace MediaBrowser.Providers.All
             PopulateBackdrops(images, files, imagePrefix, "background", "background-", 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)
         {
-            var imageFiles = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly)
+            var imageFiles = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
                 .Where(i =>
                 {
-                    var extension = Path.GetExtension(i);
+                    var extension = i.Extension;
 
                     if (string.IsNullOrEmpty(extension))
                     {
@@ -203,17 +209,17 @@ namespace MediaBrowser.Providers.All
 
             images.AddRange(imageFiles.Select(i => new LocalImageInfo
             {
-                Path = i,
+                FileInfo = i,
                 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);
         }
 
-        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);
 
@@ -246,7 +252,7 @@ namespace MediaBrowser.Providers.All
                 return;
             }
 
-            var files = GetFileDictionary(GetFiles(series, false));
+            var seriesFiles = GetFiles(series, false).ToList();
 
             // Try using the season name
             var prefix = season.Name.ToLower().Replace(" ", string.Empty);
@@ -265,39 +271,22 @@ namespace MediaBrowser.Providers.All
 
             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)
             {
                 images.Add(new LocalImageInfo
                 {
-                    Path = image,
+                    FileInfo = image,
                     Type = type
                 });
 
@@ -307,16 +296,14 @@ namespace MediaBrowser.Providers.All
             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);
         }
     }

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

@@ -275,9 +275,9 @@ namespace MediaBrowser.Providers.Manager
                 {
                     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;
                     }
                 }
@@ -287,7 +287,7 @@ namespace MediaBrowser.Providers.Manager
             if (backdrops.Count > 0)
             {
                 var foundImages = images.Where(i => i.Type == ImageType.Backdrop)
-                    .Select(i => new FileInfo(i.Path))
+                    .Select(i => i.FileInfo)
                     .ToList();
 
                 if (foundImages.Count > 0)
@@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.Manager
             if (hasScreenshots != null)
             {
                 var foundImages = images.Where(i => i.Type == ImageType.Screenshot)
-                    .Select(i => new FileInfo(i.Path))
+                    .Select(i => i.FileInfo)
                     .ToList();
 
                 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))
                     .ToList();
 
-                if (providersWithChanges.Count > 0)
-                {
-                    var b = true;
-                }
-
                 // If local providers are the only ones with changes, then just run those
                 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\ArtistMetadataService.cs" />
     <Compile Include="Music\AudioMetadataService.cs" />
+    <Compile Include="Music\Extensions.cs" />
     <Compile Include="Music\LastfmArtistProvider.cs" />
     <Compile Include="Music\MovieDbMusicVideoProvider.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, "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[] { '/', '|', ';', '\\' };

+ 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 artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz);
+            var artistMusicBrainzId = album.MusicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
             if (!string.IsNullOrEmpty(artistMusicBrainzId))
             {
@@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.Music
 
                 var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
 
-                var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz);
+                var musicBrainzId = album.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
                 try
                 {
@@ -365,17 +365,21 @@ namespace MediaBrowser.Providers.Music
             }
 
             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;

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

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

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

@@ -61,7 +61,9 @@ namespace MediaBrowser.Providers.Music
 
             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))
             {

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

@@ -48,9 +48,10 @@ namespace MediaBrowser.Providers.Music
         private async Task<LastfmGetAlbumResult> GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken)
         {
             // 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)
                 {
@@ -59,9 +60,10 @@ namespace MediaBrowser.Providers.Music
             }
 
             // 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)
                 {
@@ -69,6 +71,7 @@ namespace MediaBrowser.Providers.Music
                 }
             }
 
+            var albumArtist = item.GetAlbumArtist();
             //// 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();
 
@@ -82,12 +85,12 @@ namespace MediaBrowser.Providers.Music
             //    }
             //}
 
-            if (string.IsNullOrEmpty(item.AlbumArtist))
+            if (string.IsNullOrEmpty(albumArtist))
             {
                 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)
@@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.Music
             string imageSize;
             var url = LastfmHelper.GetImageUrl(data, out imageSize);
 
-            var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz) ??
+            var musicBrainzId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum) ??
                 item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
 
             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 musicBrainzId = id.GetProviderId(MetadataProviders.Musicbrainz);
+            var musicBrainzId = id.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
             if (!String.IsNullOrWhiteSpace(musicBrainzId))
             {
@@ -51,8 +51,6 @@ namespace MediaBrowser.Providers.Music
                 result.Item = new MusicArtist();
                 result.HasMetadata = true;
 
-                result.Item.SetProviderId(MetadataProviders.Musicbrainz, musicBrainzId);
-
                 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)
         {
-            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))
             {
-                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))
                 {
                     releaseId = releaseResult.ReleaseId;
                     result.HasMetadata = true;
-                    result.Item.SetProviderId(MetadataProviders.Musicbrainz, releaseId);
+                    result.Item.SetProviderId(MetadataProviders.MusicBrainzAlbum, releaseId);
                 }
 
                 if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId))
@@ -67,6 +66,19 @@ namespace MediaBrowser.Providers.Music
                 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;
         }
 

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

@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music
         {
             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))
             {
@@ -27,7 +27,7 @@ namespace MediaBrowser.Providers.Music
                 result.Item = new MusicArtist();
                 result.HasMetadata = true;
 
-                result.Item.SetProviderId(MetadataProviders.Musicbrainz, musicBrainzId);
+                result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId);
             }
 
             return result;

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

@@ -415,11 +415,25 @@ namespace MediaBrowser.Providers.Savers
                 builder.Append("<Zap2ItId>" + SecurityElement.Escape(zap2It) + "</Zap2ItId>");
             }
 
-            var mbz = item.GetProviderId(MetadataProviders.Musicbrainz);
+            var mbz = item.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
             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);

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

@@ -28,12 +28,12 @@ namespace MediaBrowser.Providers.TV
             var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path);
             var thumbName = nameWithoutExtension + "-thumb";
 
-            return Directory.EnumerateFiles(parentPath, "*", SearchOption.AllDirectories)
+            return new DirectoryInfo(parentPath).EnumerateFiles("*", SearchOption.AllDirectories)
                 .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))
                         {
@@ -50,7 +50,7 @@ namespace MediaBrowser.Providers.TV
                 })
                 .Select(i => new LocalImageInfo
                 {
-                    Path = i,
+                    FileInfo = i,
                     Type = ImageType.Primary
                 })
                 .ToList();

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

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