Selaa lähdekoodia

fixes #616 - Support images in collection folders

Luke Pulverenti 11 vuotta sitten
vanhempi
sitoutus
d609d0edec

+ 27 - 6
MediaBrowser.Controller/Providers/BaseMetadataProvider.cs

@@ -24,6 +24,7 @@ namespace MediaBrowser.Controller.Providers
         /// </summary>
         /// <value>The logger.</value>
         protected ILogger Logger { get; set; }
+
         protected ILogManager LogManager { get; set; }
 
         /// <summary>
@@ -41,6 +42,7 @@ namespace MediaBrowser.Controller.Providers
         /// The true task result
         /// </summary>
         protected static readonly Task<bool> TrueTaskResult = Task.FromResult(true);
+
         protected static readonly Task<bool> FalseTaskResult = Task.FromResult(false);
 
         protected static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(5, 5);
@@ -132,7 +134,8 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="providerVersion">The provider version.</param>
         /// <param name="status">The status.</param>
         /// <exception cref="System.ArgumentNullException">item</exception>
-        public virtual void SetLastRefreshed(BaseItem item, DateTime value, string providerVersion, ProviderRefreshStatus status = ProviderRefreshStatus.Success)
+        public virtual void SetLastRefreshed(BaseItem item, DateTime value, string providerVersion,
+            ProviderRefreshStatus status = ProviderRefreshStatus.Success)
         {
             if (item == null)
             {
@@ -172,7 +175,8 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="item">The item.</param>
         /// <param name="value">The value.</param>
         /// <param name="status">The status.</param>
-        public void SetLastRefreshed(BaseItem item, DateTime value, ProviderRefreshStatus status = ProviderRefreshStatus.Success)
+        public void SetLastRefreshed(BaseItem item, DateTime value,
+            ProviderRefreshStatus status = ProviderRefreshStatus.Success)
         {
             SetLastRefreshed(item, value, ProviderVersion, status);
         }
@@ -238,7 +242,8 @@ namespace MediaBrowser.Controller.Providers
                 return true;
             }
 
-            if (RefreshOnFileSystemStampChange && item.LocationType == LocationType.FileSystem && HasFileSystemStampChanged(item, providerInfo))
+            if (RefreshOnFileSystemStampChange && item.LocationType == LocationType.FileSystem &&
+                HasFileSystemStampChanged(item, providerInfo))
             {
                 return true;
             }
@@ -349,21 +354,23 @@ namespace MediaBrowser.Controller.Providers
         }
 
         private Dictionary<string, string> _fileStampExtensionsDictionary;
+
         private Dictionary<string, string> FileStampExtensionsDictionary
         {
             get
             {
                 return _fileStampExtensionsDictionary ??
                        (_fileStampExtensionsDictionary =
-                        FilestampExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase));
+                           FilestampExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase));
             }
         }
+
         /// <summary>
         /// Gets the file system stamp.
         /// </summary>
         /// <param name="item">The item.</param>
         /// <returns>Guid.</returns>
-        private Guid GetFileSystemStamp(BaseItem item)
+        protected virtual Guid GetFileSystemStamp(BaseItem item)
         {
             // If there's no path or the item is a file, there's nothing to do
             if (item.LocationType != LocationType.FileSystem)
@@ -404,6 +411,20 @@ namespace MediaBrowser.Controller.Providers
         private static readonly Dictionary<string, string> FoldersToMonitor = new[] { "extrafanart", "extrathumbs" }
             .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
 
+        protected Guid GetFileSystemStamp(IEnumerable<FileSystemInfo> files)
+        {
+            var sb = new StringBuilder();
+
+            var extensions = FileStampExtensionsDictionary;
+            var numExtensions = FilestampExtensions.Length;
+
+            // Record the name of each file 
+            // Need to sort these because accoring to msdn docs, our i/o methods are not guaranteed in any order
+            AddFiles(sb, files, extensions, numExtensions);
+
+            return sb.ToString().GetMD5();
+        }
+
         /// <summary>
         /// Adds the files.
         /// </summary>
@@ -424,7 +445,7 @@ namespace MediaBrowser.Controller.Providers
                         {
                             sb.Append(file.Name);
 
-                            var children = ((DirectoryInfo) file).EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList();
+                            var children = ((DirectoryInfo)file).EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList();
                             AddFiles(sb, children, extensions, numExtensions);
                         }
                     }

+ 55 - 0
MediaBrowser.Providers/CollectionFolderImageProvider.cs

@@ -0,0 +1,55 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Providers
+{
+    public class CollectionFolderImageProvider : ImageFromMediaLocationProvider
+    {
+        public CollectionFolderImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
+            : base(logManager, configurationManager, fileSystem)
+        {
+        }
+
+        public override bool Supports(BaseItem item)
+        {
+            return item is CollectionFolder && item.LocationType == LocationType.FileSystem;
+        }
+
+        public override MetadataProviderPriority Priority
+        {
+            get { return MetadataProviderPriority.Second; }
+        }
+
+        protected override FileSystemInfo GetImage(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension)
+        {
+            return item.ResolveArgs.PhysicalLocations
+                .Select(i => GetImageFromLocation(i, filenameWithoutExtension))
+                .FirstOrDefault(i => i != null);
+        }
+
+        protected override Guid GetFileSystemStamp(BaseItem item)
+        {
+            var files = item.ResolveArgs.PhysicalLocations
+                .Select(i => new DirectoryInfo(i))
+                .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
+                .Where(i =>
+                {
+                    var ext = i.Extension;
+
+                    return !string.IsNullOrEmpty(ext) &&
+                        BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
+                })
+                .ToList();
+
+            return GetFileSystemStamp(files);
+        }
+    }
+}

+ 38 - 2
MediaBrowser.Providers/ImageFromMediaLocationProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
@@ -21,9 +22,12 @@ namespace MediaBrowser.Providers
     /// </summary>
     public class ImageFromMediaLocationProvider : BaseMetadataProvider
     {
-        public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+        protected readonly IFileSystem FileSystem;
+        
+        public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
             : base(logManager, configurationManager)
         {
+            FileSystem = fileSystem;
         }
 
         public override ItemUpdateType ItemUpdateType
@@ -543,5 +547,37 @@ namespace MediaBrowser.Providers
                 item.ScreenshotImagePaths = screenshotFiles;
             }
         }
+
+        protected FileSystemInfo GetImageFromLocation(string path, string filenameWithoutExtension)
+        {
+            try
+            {
+                var files = new DirectoryInfo(path)
+                    .EnumerateFiles()
+                    .Where(i =>
+                    {
+                        var fileName = Path.GetFileNameWithoutExtension(i.FullName);
+
+                        if (!string.Equals(fileName, filenameWithoutExtension, StringComparison.OrdinalIgnoreCase))
+                        {
+                            return false;
+                        }
+
+                        var ext = i.Extension;
+
+                        return !string.IsNullOrEmpty(ext) &&
+                            BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
+                    })
+                    .ToList();
+
+                return BaseItem.SupportedImageExtensions
+                    .Select(ext => files.FirstOrDefault(i => string.Equals(ext, i.Extension, StringComparison.OrdinalIgnoreCase)))
+                    .FirstOrDefault(file => file != null);
+            }
+            catch (DirectoryNotFoundException)
+            {
+                return null;
+            }
+        }
     }
 }

+ 27 - 127
MediaBrowser.Providers/ImagesByNameProvider.cs

@@ -1,16 +1,12 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Logging;
 using System;
 using System.IO;
 using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
 
 namespace MediaBrowser.Providers
 {
@@ -19,22 +15,11 @@ namespace MediaBrowser.Providers
     /// </summary>
     public class ImagesByNameProvider : ImageFromMediaLocationProvider
     {
-        private readonly IFileSystem _fileSystem;
-        
         public ImagesByNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
-            : base(logManager, configurationManager)
+            : base(logManager, configurationManager, fileSystem)
         {
-            _fileSystem = fileSystem;
         }
 
-        public override ItemUpdateType ItemUpdateType
-        {
-            get
-            {
-                return ItemUpdateType.ImageUpdate;
-            }
-        }
-        
         /// <summary>
         /// Supportses the specified item.
         /// </summary>
@@ -42,8 +27,8 @@ namespace MediaBrowser.Providers
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
         public override bool Supports(BaseItem item)
         {
-            //only run for these generic types since we are expensive in file i/o
-            return item is IndexFolder || item is BasePluginFolder || item is CollectionFolder;
+            // Only run for these generic types since we are expensive in file i/o
+            return item is BasePluginFolder || item is CollectionFolder;
         }
 
         /// <summary>
@@ -58,95 +43,6 @@ namespace MediaBrowser.Providers
             }
         }
 
-        /// <summary>
-        /// Needses the refresh internal.
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <param name="providerInfo">The provider info.</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
-        {
-            // Force a refresh if the IBN path changed
-            if (providerInfo.FileStamp != ConfigurationManager.ApplicationPaths.ItemsByNamePath.GetMD5())
-            {
-                return true;
-            }
-
-            return base.NeedsRefreshInternal(item, providerInfo);
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether [refresh on file system stamp change].
-        /// </summary>
-        /// <value><c>true</c> if [refresh on file system stamp change]; otherwise, <c>false</c>.</value>
-        protected override bool RefreshOnFileSystemStampChange
-        {
-            get
-            {
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Override this to return the date that should be compared to the last refresh date
-        /// to determine if this provider should be re-fetched.
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <returns>DateTime.</returns>
-        protected override DateTime CompareDate(BaseItem item)
-        {
-            // If the IBN location exists return the last modified date of any file in it
-            var location = GetLocation(item);
-
-            var directoryInfo = new DirectoryInfo(location);
-
-            if (!directoryInfo.Exists)
-            {
-                return DateTime.MinValue;
-            }
-
-            var files = directoryInfo.EnumerateFiles().ToList();
-
-            if (files.Count == 0)
-            {
-                return DateTime.MinValue;
-            }
-
-            return files.Select(f =>
-            {
-                var lastWriteTime = _fileSystem.GetLastWriteTimeUtc(f);
-                var creationTime = _fileSystem.GetCreationTimeUtc(f);
-
-                return creationTime > lastWriteTime ? creationTime : lastWriteTime;
-
-            }).Max();
-        }
-
-        /// <summary>
-        /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <param name="force">if set to <c>true</c> [force].</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task{System.Boolean}.</returns>
-        public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
-        {
-            var result = await base.FetchAsync(item, force, cancellationToken).ConfigureAwait(false);
-
-            BaseProviderInfo data;
-
-            if (!item.ProviderData.TryGetValue(Id, out data))
-            {
-                data = new BaseProviderInfo();
-                item.ProviderData[Id] = data;
-            }
-
-            data.FileStamp = ConfigurationManager.ApplicationPaths.ItemsByNamePath.GetMD5();
-            SetLastRefreshed(item, DateTime.UtcNow);
-     
-            return result;
-        }
-
         /// <summary>
         /// Gets the location.
         /// </summary>
@@ -154,7 +50,7 @@ namespace MediaBrowser.Providers
         /// <returns>System.String.</returns>
         protected string GetLocation(BaseItem item)
         {
-            var name = _fileSystem.GetValidFilename(item.Name);
+            var name = FileSystem.GetValidFilename(item.Name);
 
             return Path.Combine(ConfigurationManager.ApplicationPaths.GeneralPath, name);
         }
@@ -170,30 +66,34 @@ namespace MediaBrowser.Providers
         {
             var location = GetLocation(item);
 
-            var directoryInfo = new DirectoryInfo(location);
-
-            if (!directoryInfo.Exists)
-            {
-                return null;
-            }
-
-            var files = directoryInfo.EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList();
+            return GetImageFromLocation(location, filenameWithoutExtension);
+        }
 
-            var file = files.FirstOrDefault(i => string.Equals(i.Name, filenameWithoutExtension + ".png", StringComparison.OrdinalIgnoreCase));
+        protected override Guid GetFileSystemStamp(BaseItem item)
+        {
+            var location = GetLocation(item);
 
-            if (file != null)
+            try
             {
-                return file;
+                var files = new DirectoryInfo(location)
+                    .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+                    .Where(i =>
+                    {
+                        var ext = i.Extension;
+
+                        return !string.IsNullOrEmpty(ext) &&
+                            BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
+                    })
+                    .ToList();
+
+                return GetFileSystemStamp(files);
             }
-
-            file = files.FirstOrDefault(i => string.Equals(i.Name, filenameWithoutExtension + ".jpg", StringComparison.OrdinalIgnoreCase));
-
-            if (file != null)
+            catch (DirectoryNotFoundException)
             {
-                return file;
-            }
+                // User doesn't have the folder. No need to log or blow up
 
-            return null;
+                return Guid.Empty;
+            }
         }
     }
 }

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

@@ -47,6 +47,7 @@
     </Reference>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="CollectionFolderImageProvider.cs" />
     <Compile Include="FanartBaseProvider.cs" />
     <Compile Include="FolderProviderFromXml.cs" />
     <Compile Include="Games\GameXmlParser.cs" />