fixes #616 - Support images in collection folders

This commit is contained in:
Luke Pulverenti 2013-11-07 10:56:35 -05:00
parent a2cd03610f
commit d609d0edec
5 changed files with 149 additions and 136 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
return GetImageFromLocation(location, filenameWithoutExtension);
}
if (!directoryInfo.Exists)
protected override Guid GetFileSystemStamp(BaseItem item)
{
var location = GetLocation(item);
try
{
return null;
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);
}
var files = directoryInfo.EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList();
var file = files.FirstOrDefault(i => string.Equals(i.Name, filenameWithoutExtension + ".png", StringComparison.OrdinalIgnoreCase));
if (file != null)
catch (DirectoryNotFoundException)
{
return file;
// User doesn't have the folder. No need to log or blow up
return Guid.Empty;
}
file = files.FirstOrDefault(i => string.Equals(i.Name, filenameWithoutExtension + ".jpg", StringComparison.OrdinalIgnoreCase));
if (file != null)
{
return file;
}
return null;
}
}
}

View File

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