瀏覽代碼

use music brainz values from audio files with bottom up refresh

Luke Pulverenti 11 年之前
父節點
當前提交
12757d094b
共有 37 個文件被更改,包括 544 次插入132 次删除
  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>