diff --git a/MediaBrowser.Controller/FFMpeg/FFProbe.cs b/MediaBrowser.Controller/FFMpeg/FFProbe.cs index 83f70af3a..fac1d4667 100644 --- a/MediaBrowser.Controller/FFMpeg/FFProbe.cs +++ b/MediaBrowser.Controller/FFMpeg/FFProbe.cs @@ -13,12 +13,15 @@ namespace MediaBrowser.Controller.FFMpeg /// public static class FFProbe { + /// + /// Runs FFProbe against an Audio file, caches the result and returns the output + /// public static FFProbeResult Run(Audio item) { // Use try catch to avoid having to use File.Exists try { - return GetCachedResult(GetFFProbeAudioCachePath(item)); + return GetCachedResult(GetFFProbeCachePath(item)); } catch (FileNotFoundException) { @@ -31,16 +34,22 @@ namespace MediaBrowser.Controller.FFMpeg FFProbeResult result = Run(item.Path); // Fire and forget - CacheResult(result, GetFFProbeAudioCachePath(item)); + CacheResult(result, GetFFProbeCachePath(item)); return result; } + /// + /// Gets the cached result of an FFProbe operation + /// private static FFProbeResult GetCachedResult(string path) { return ProtobufSerializer.DeserializeFromFile(path); } + /// + /// Caches the result of an FFProbe operation + /// private static async void CacheResult(FFProbeResult result, string outputCachePath) { await Task.Run(() => @@ -56,12 +65,15 @@ namespace MediaBrowser.Controller.FFMpeg }).ConfigureAwait(false); } + /// + /// Runs FFProbe against a Video file, caches the result and returns the output + /// public static FFProbeResult Run(Video item) { // Use try catch to avoid having to use File.Exists try { - return GetCachedResult(GetFFProbeVideoCachePath(item)); + return GetCachedResult(GetFFProbeCachePath(item)); } catch (FileNotFoundException) { @@ -74,7 +86,7 @@ namespace MediaBrowser.Controller.FFMpeg FFProbeResult result = Run(item.Path); // Fire and forget - CacheResult(result, GetFFProbeVideoCachePath(item)); + CacheResult(result, GetFFProbeCachePath(item)); return result; } @@ -131,14 +143,14 @@ namespace MediaBrowser.Controller.FFMpeg } } - private static string GetFFProbeAudioCachePath(BaseEntity item) + private static string GetFFProbeCachePath(Audio item) { string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1)); return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".pb"); } - private static string GetFFProbeVideoCachePath(BaseEntity item) + private static string GetFFProbeCachePath(Video item) { string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1)); diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index eca166ead..21d090a27 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -1,32 +1,61 @@ using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; -using System.Runtime.ConstrainedExecution; -using Microsoft.Win32.SafeHandles; -using System.Collections.Generic; -using System.Linq; - namespace MediaBrowser.Controller.IO { + /// + /// Provides low level File access that is much faster than the File/Directory api's + /// public static class FileData { public const int MAX_PATH = 260; public const int MAX_ALTERNATE = 14; - public static WIN32_FIND_DATA GetFileData(string fileName) + /// + /// Gets information about a path + /// + public static WIN32_FIND_DATA GetFileData(string path) { WIN32_FIND_DATA data; - IntPtr handle = FindFirstFile(fileName, out data); + IntPtr handle = FindFirstFile(path, out data); if (handle == IntPtr.Zero) throw new IOException("FindFirstFile failed"); FindClose(handle); - data.Path = fileName; + data.Path = path; return data; } + /// + /// Gets all file system entries within a foler + /// public static IEnumerable GetFileSystemEntries(string path, string searchPattern) + { + return GetFileSystemEntries(path, searchPattern, true, true); + } + + /// + /// Gets all files within a folder + /// + public static IEnumerable GetFiles(string path, string searchPattern) + { + return GetFileSystemEntries(path, searchPattern, true, false); + } + + /// + /// Gets all sub-directories within a folder + /// + public static IEnumerable GetDirectories(string path, string searchPattern) + { + return GetFileSystemEntries(path, searchPattern, false, true); + } + + /// + /// Gets all file system entries within a foler + /// + public static IEnumerable GetFileSystemEntries(string path, string searchPattern, bool includeFiles, bool includeDirectories) { string lpFileName = Path.Combine(path, searchPattern); @@ -43,14 +72,14 @@ namespace MediaBrowser.Controller.IO yield break; } - if (IsValid(lpFindFileData.cFileName)) + if (IncludeInOutput(lpFindFileData.cFileName, lpFindFileData.dwFileAttributes, includeFiles, includeDirectories)) { yield return lpFindFileData; } while (FindNextFile(handle, out lpFindFileData) != IntPtr.Zero) { - if (IsValid(lpFindFileData.cFileName)) + if (IncludeInOutput(lpFindFileData.cFileName, lpFindFileData.dwFileAttributes, includeFiles, includeDirectories)) { lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName); yield return lpFindFileData; @@ -60,7 +89,7 @@ namespace MediaBrowser.Controller.IO FindClose(handle); } - private static bool IsValid(string cFileName) + private static bool IncludeInOutput(string cFileName, FileAttributes attributes, bool includeFiles, bool includeDirectories) { if (cFileName.Equals(".", StringComparison.OrdinalIgnoreCase)) { @@ -71,6 +100,16 @@ namespace MediaBrowser.Controller.IO return false; } + if (!includeFiles && !attributes.HasFlag(FileAttributes.Directory)) + { + return false; + } + + if (!includeDirectories && attributes.HasFlag(FileAttributes.Directory)) + { + return false; + } + return true; } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index b7e0258e0..44833fe8e 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -9,7 +9,6 @@ using System.Text; using System.Threading.Tasks; using MediaBrowser.Common.Kernel; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.Controller/Library/ItemController.cs b/MediaBrowser.Controller/Library/ItemController.cs index df7cf8810..fdc2276d0 100644 --- a/MediaBrowser.Controller/Library/ItemController.cs +++ b/MediaBrowser.Controller/Library/ItemController.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs b/MediaBrowser.Controller/Library/ItemResolveEventArgs.cs similarity index 94% rename from MediaBrowser.Controller/Events/ItemResolveEventArgs.cs rename to MediaBrowser.Controller/Library/ItemResolveEventArgs.cs index 7251e3ec9..0daca3b44 100644 --- a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveEventArgs.cs @@ -3,7 +3,7 @@ using System.IO; using MediaBrowser.Controller.IO; using MediaBrowser.Model.Entities; -namespace MediaBrowser.Controller.Events +namespace MediaBrowser.Controller.Library { /// /// This is an EventArgs object used when resolving a Path into a BaseItem diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 652a9d736..610a4cc01 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -55,7 +55,7 @@ - + diff --git a/MediaBrowser.Controller/Providers/AudioInfoProvider.cs b/MediaBrowser.Controller/Providers/AudioInfoProvider.cs index d45c5ee68..4166cb152 100644 --- a/MediaBrowser.Controller/Providers/AudioInfoProvider.cs +++ b/MediaBrowser.Controller/Providers/AudioInfoProvider.cs @@ -5,8 +5,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using MediaBrowser.Common.Logging; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.FFMpeg; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers diff --git a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs index 5c536913e..45cd59883 100644 --- a/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/BaseMetadataProvider.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers diff --git a/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs b/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs index d0bd20a47..cdf02e90b 100644 --- a/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs +++ b/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs @@ -1,12 +1,15 @@ using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Xml; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { + /// + /// Provides metadata for Folders and all subclasses by parsing folder.xml + /// [Export(typeof(BaseMetadataProvider))] public class FolderProviderFromXml : BaseMetadataProvider { @@ -22,15 +25,15 @@ namespace MediaBrowser.Controller.Providers public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) { - await Task.Run(() => { Fetch(item, args); }).ConfigureAwait(false); + if (args.ContainsFile("folder.xml")) + { + await Task.Run(() => { Fetch(item, args); }).ConfigureAwait(false); + } } private void Fetch(BaseEntity item, ItemResolveEventArgs args) { - if (args.ContainsFile("folder.xml")) - { - new BaseItemXmlParser().Fetch(item as Folder, Path.Combine(args.Path, "folder.xml")); - } + new BaseItemXmlParser().Fetch(item as Folder, Path.Combine(args.Path, "folder.xml")); } } } diff --git a/MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs b/MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs index 59b58474f..242a139ef 100644 --- a/MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs +++ b/MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs @@ -3,11 +3,14 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { + /// + /// Provides images for all types by looking for standard images - folder, backdrop, logo, etc. + /// [Export(typeof(BaseMetadataProvider))] public class ImageFromMediaLocationProvider : BaseMetadataProvider { diff --git a/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs b/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs index 536294c7b..ac258ee61 100644 --- a/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs +++ b/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs @@ -2,12 +2,15 @@ using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { + /// + /// Provides local trailers by checking the trailers subfolder + /// [Export(typeof(BaseMetadataProvider))] public class LocalTrailerProvider : BaseMetadataProvider { diff --git a/MediaBrowser.Controller/Providers/VideoInfoProvider.cs b/MediaBrowser.Controller/Providers/VideoInfoProvider.cs index 2f8175b7e..9b5a8933d 100644 --- a/MediaBrowser.Controller/Providers/VideoInfoProvider.cs +++ b/MediaBrowser.Controller/Providers/VideoInfoProvider.cs @@ -4,10 +4,9 @@ using System.ComponentModel.Composition; using System.Linq; using System.Threading.Tasks; using MediaBrowser.Common.Logging; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.FFMpeg; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; -using System.IO; namespace MediaBrowser.Controller.Providers { @@ -38,12 +37,6 @@ namespace MediaBrowser.Controller.Providers return; } - // For now - if (Path.GetExtension(video.Path).EndsWith("iso", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (CanSkip(video)) { return; diff --git a/MediaBrowser.Controller/Resolvers/AudioResolver.cs b/MediaBrowser.Controller/Resolvers/AudioResolver.cs index 26b4da310..7b52ccfc4 100644 --- a/MediaBrowser.Controller/Resolvers/AudioResolver.cs +++ b/MediaBrowser.Controller/Resolvers/AudioResolver.cs @@ -1,6 +1,6 @@ using System.ComponentModel.Composition; using System.IO; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Resolvers diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index 948e0cfb5..643580b31 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Resolvers diff --git a/MediaBrowser.Controller/Resolvers/FolderResolver.cs b/MediaBrowser.Controller/Resolvers/FolderResolver.cs index 62fe2f6fb..6857c3574 100644 --- a/MediaBrowser.Controller/Resolvers/FolderResolver.cs +++ b/MediaBrowser.Controller/Resolvers/FolderResolver.cs @@ -1,5 +1,5 @@ using System.ComponentModel.Composition; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Resolvers diff --git a/MediaBrowser.Controller/Resolvers/VideoResolver.cs b/MediaBrowser.Controller/Resolvers/VideoResolver.cs index ee2fc62f3..1157401af 100644 --- a/MediaBrowser.Controller/Resolvers/VideoResolver.cs +++ b/MediaBrowser.Controller/Resolvers/VideoResolver.cs @@ -1,6 +1,6 @@ using System.ComponentModel.Composition; using System.IO; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Resolvers diff --git a/MediaBrowser.Controller/Resolvers/VirtualFolderResolver.cs b/MediaBrowser.Controller/Resolvers/VirtualFolderResolver.cs index 19bf66f29..e7940ef14 100644 --- a/MediaBrowser.Controller/Resolvers/VirtualFolderResolver.cs +++ b/MediaBrowser.Controller/Resolvers/VirtualFolderResolver.cs @@ -1,6 +1,6 @@ using System.ComponentModel.Composition; using System.IO; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Resolvers diff --git a/MediaBrowser.Movies/MediaBrowser.Movies.csproj b/MediaBrowser.Movies/MediaBrowser.Movies.csproj index 588a23e90..5eefa6b81 100644 --- a/MediaBrowser.Movies/MediaBrowser.Movies.csproj +++ b/MediaBrowser.Movies/MediaBrowser.Movies.csproj @@ -43,6 +43,7 @@ + diff --git a/MediaBrowser.Movies/Providers/MovieProviderFromXml.cs b/MediaBrowser.Movies/Providers/MovieProviderFromXml.cs index 689e786d1..0498deb9a 100644 --- a/MediaBrowser.Movies/Providers/MovieProviderFromXml.cs +++ b/MediaBrowser.Movies/Providers/MovieProviderFromXml.cs @@ -1,7 +1,7 @@ using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Xml; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Movies/Providers/MovieSpecialFeaturesProvider.cs b/MediaBrowser.Movies/Providers/MovieSpecialFeaturesProvider.cs new file mode 100644 index 000000000..a70c56747 --- /dev/null +++ b/MediaBrowser.Movies/Providers/MovieSpecialFeaturesProvider.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Threading.Tasks; +using MediaBrowser.Controller; +using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Movies.Entities; + +namespace MediaBrowser.Movies.Providers +{ + [Export(typeof(BaseMetadataProvider))] + public class MovieSpecialFeaturesProvider : BaseMetadataProvider + { + public override bool Supports(BaseEntity item) + { + return item is Movie; + } + + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.First; } + } + + public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) + { + if (args.ContainsFolder("specials")) + { + List