浏览代码

Switched to low-level io methods for better performance

LukePulverenti Luke Pulverenti luke pulverenti 13 年之前
父节点
当前提交
758d18a652

+ 30 - 14
MediaBrowser.Controller/Events/ItemResolveEventArgs.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.IO;
 
 namespace MediaBrowser.Controller.Events
 {
@@ -10,18 +11,25 @@ namespace MediaBrowser.Controller.Events
     /// </summary>
     public class ItemResolveEventArgs : PreBeginResolveEventArgs
     {
-        public IEnumerable<KeyValuePair<string, FileAttributes>> FileSystemChildren { get; set; }
+        public IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> FileSystemChildren { get; set; }
 
-        public KeyValuePair<string, FileAttributes>? GetFolderByName(string name)
+        public KeyValuePair<string, WIN32_FIND_DATA>? GetFileSystemEntry(string path, bool? isFolder)
         {
-            foreach (KeyValuePair<string, FileAttributes> entry in FileSystemChildren)
+            foreach (KeyValuePair<string, WIN32_FIND_DATA> entry in FileSystemChildren)
             {
-                if (!entry.Value.HasFlag(FileAttributes.Directory))
+                if (isFolder.HasValue)
                 {
-                    continue;
+                    if (isFolder.Value && entry.Value.IsDirectory)
+                    {
+                        continue;
+                    }
+                    else if (!isFolder.Value && !entry.Value.IsDirectory)
+                    {
+                        continue;
+                    }
                 }
 
-                if (System.IO.Path.GetFileName(entry.Key).Equals(name, StringComparison.OrdinalIgnoreCase))
+                if (entry.Key.Equals(path, StringComparison.OrdinalIgnoreCase))
                 {
                     return entry;
                 }
@@ -29,14 +37,21 @@ namespace MediaBrowser.Controller.Events
 
             return null;
         }
-
-        public KeyValuePair<string, FileAttributes>? GetFileByName(string name)
+        
+        public KeyValuePair<string, WIN32_FIND_DATA>? GetFileSystemEntryByName(string name, bool? isFolder)
         {
-            foreach (KeyValuePair<string, FileAttributes> entry in FileSystemChildren)
+            foreach (KeyValuePair<string, WIN32_FIND_DATA> entry in FileSystemChildren)
             {
-                if (entry.Value.HasFlag(FileAttributes.Directory))
+                if (isFolder.HasValue)
                 {
-                    continue;
+                    if (isFolder.Value && entry.Value.IsDirectory)
+                    {
+                        continue;
+                    }
+                    else if (!isFolder.Value && !entry.Value.IsDirectory)
+                    {
+                        continue;
+                    }
                 }
 
                 if (System.IO.Path.GetFileName(entry.Key).Equals(name, StringComparison.OrdinalIgnoreCase))
@@ -50,12 +65,12 @@ namespace MediaBrowser.Controller.Events
 
         public bool ContainsFile(string name)
         {
-            return GetFileByName(name) != null;
+            return GetFileSystemEntryByName(name, false) != null;
         }
 
         public bool ContainsFolder(string name)
         {
-            return GetFolderByName(name) != null;
+            return GetFileSystemEntryByName(name, true) != null;
         }
     }
 
@@ -71,7 +86,8 @@ namespace MediaBrowser.Controller.Events
 
         public bool Cancel { get; set; }
 
-        public FileAttributes FileAttributes { get; set; }
+        public FileAttributes FileAttributes { get { return FileData.dwFileAttributes; } }
+        public WIN32_FIND_DATA FileData { get; set; }
 
         public bool IsFolder
         {

+ 3 - 3
MediaBrowser.Controller/IO/DirectoryWatchers.cs

@@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.IO
             List<string> paths = affectedPaths;
             affectedPaths = new List<string>();
 
-            await ProcessPathChanges(paths);
+            await ProcessPathChanges(paths).ConfigureAwait(false);
         }
 
         private async Task ProcessPathChanges(IEnumerable<string> paths)
@@ -105,11 +105,11 @@ namespace MediaBrowser.Controller.IO
                     return folder != null && folder.IsRoot;
                 }))
             {
-                await Kernel.Instance.ReloadRoot();
+                await Kernel.Instance.ReloadRoot().ConfigureAwait(false);
             }
             else
             {
-                await Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
+                await Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i))).ConfigureAwait(false);
             }
         }
 

+ 96 - 0
MediaBrowser.Controller/IO/FileData.cs

@@ -0,0 +1,96 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace MediaBrowser.Controller.IO
+{
+    public static class FileData
+    {
+        public const int MAX_PATH = 260;
+        public const int MAX_ALTERNATE = 14;
+
+        public static WIN32_FIND_DATA GetFileData(string fileName)
+        {
+            WIN32_FIND_DATA data;
+            IntPtr handle = FindFirstFile(fileName, out data);
+            if (handle == IntPtr.Zero)
+                throw new IOException("FindFirstFile failed");
+            FindClose(handle);
+            return data;
+        }
+
+        [DllImport("kernel32")]
+        private static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA data);
+
+        [DllImport("kernel32")]
+        private static extern bool FindClose(IntPtr hFindFile);
+
+
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct FILETIME
+    {
+        public uint dwLowDateTime;
+        public uint dwHighDateTime;
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    public struct WIN32_FIND_DATA
+    {
+        public FileAttributes dwFileAttributes;
+        public FILETIME ftCreationTime;
+        public FILETIME ftLastAccessTime;
+        public FILETIME ftLastWriteTime;
+        public int nFileSizeHigh;
+        public int nFileSizeLow;
+        public int dwReserved0;
+        public int dwReserved1;
+
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FileData.MAX_PATH)]
+        public string cFileName;
+
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FileData.MAX_ALTERNATE)]
+        public string cAlternate;
+
+        public bool IsDirectory
+        {
+            get
+            {
+                return dwFileAttributes.HasFlag(FileAttributes.Directory);
+            }
+        }
+
+        public DateTime CreationTime
+        {
+            get
+            {
+                return ParseFileTime(ftCreationTime);
+            }
+        }
+
+        public DateTime LastAccessTime
+        {
+            get
+            {
+                return ParseFileTime(ftLastAccessTime);
+            }
+        }
+
+        public DateTime LastWriteTime
+        {
+            get
+            {
+                return ParseFileTime(ftLastWriteTime);
+            }
+        }
+
+        private DateTime ParseFileTime(FILETIME filetime)
+        {
+            long highBits = filetime.dwHighDateTime;
+            highBits = highBits << 32;
+            return DateTime.FromFileTime(highBits + (long)filetime.dwLowDateTime);
+        }
+    }
+
+}

+ 25 - 23
MediaBrowser.Controller/Library/ItemController.cs

@@ -20,13 +20,13 @@ namespace MediaBrowser.Controller.Library
         /// This gives listeners a chance to cancel the operation and cause the path to be ignored.
         /// </summary>
         public event EventHandler<PreBeginResolveEventArgs> PreBeginResolvePath;
-        private bool OnPreBeginResolvePath(Folder parent, string path, FileAttributes attributes)
+        private bool OnPreBeginResolvePath(Folder parent, string path, WIN32_FIND_DATA fileData)
         {
             PreBeginResolveEventArgs args = new PreBeginResolveEventArgs()
             {
                 Path = path,
                 Parent = parent,
-                FileAttributes = attributes,
+                FileData = fileData,
                 Cancel = false
             };
 
@@ -111,39 +111,41 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         public async Task<BaseItem> GetItem(Folder parent, string path)
         {
-            return await GetItemInternal(parent, path, File.GetAttributes(path)).ConfigureAwait(false);
+            WIN32_FIND_DATA fileData = FileData.GetFileData(path);
+
+            return await GetItemInternal(parent, path, fileData).ConfigureAwait(false);
         }
 
         /// <summary>
         /// Resolves a path into a BaseItem
         /// </summary>
-        private async Task<BaseItem> GetItemInternal(Folder parent, string path, FileAttributes attributes)
+        private async Task<BaseItem> GetItemInternal(Folder parent, string path, WIN32_FIND_DATA fileData)
         {
-            if (!OnPreBeginResolvePath(parent, path, attributes))
+            if (!OnPreBeginResolvePath(parent, path, fileData))
             {
                 return null;
             }
 
-            IEnumerable<KeyValuePair<string, FileAttributes>> fileSystemChildren;
+            IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> fileSystemChildren;
 
             // Gather child folder and files
-            if (attributes.HasFlag(FileAttributes.Directory))
+            if (fileData.IsDirectory)
             {
-                fileSystemChildren = Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, FileAttributes>(f, File.GetAttributes(f)));
+                fileSystemChildren = Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, WIN32_FIND_DATA>(f, FileData.GetFileData(f)));
 
                 bool isVirtualFolder = parent != null && parent.IsRoot;
                 fileSystemChildren = FilterChildFileSystemEntries(fileSystemChildren, isVirtualFolder);
             }
             else
             {
-                fileSystemChildren = new KeyValuePair<string, FileAttributes>[] { };
+                fileSystemChildren = new KeyValuePair<string, WIN32_FIND_DATA>[] { };
             }
 
             ItemResolveEventArgs args = new ItemResolveEventArgs()
             {
                 Path = path,
-                FileAttributes = attributes,
                 FileSystemChildren = fileSystemChildren,
+                FileData = fileData,
                 Parent = parent,
                 Cancel = false
             };
@@ -175,9 +177,9 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Finds child BaseItems for a given Folder
         /// </summary>
-        private async Task AttachChildren(Folder folder, IEnumerable<KeyValuePair<string, FileAttributes>> fileSystemChildren)
+        private async Task AttachChildren(Folder folder, IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> fileSystemChildren)
         {
-            KeyValuePair<string, FileAttributes>[] fileSystemChildrenArray = fileSystemChildren.ToArray();
+            KeyValuePair<string, WIN32_FIND_DATA>[] fileSystemChildrenArray = fileSystemChildren.ToArray();
 
             int count = fileSystemChildrenArray.Length;
 
@@ -203,15 +205,15 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Transforms shortcuts into their actual paths
         /// </summary>
-        private List<KeyValuePair<string, FileAttributes>> FilterChildFileSystemEntries(IEnumerable<KeyValuePair<string, FileAttributes>> fileSystemChildren, bool flattenShortcuts)
+        private List<KeyValuePair<string, WIN32_FIND_DATA>> FilterChildFileSystemEntries(IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> fileSystemChildren, bool flattenShortcuts)
         {
-            List<KeyValuePair<string, FileAttributes>> returnFiles = new List<KeyValuePair<string, FileAttributes>>();
+            List<KeyValuePair<string, WIN32_FIND_DATA>> returnFiles = new List<KeyValuePair<string, WIN32_FIND_DATA>>();
 
             // Loop through each file
-            foreach (KeyValuePair<string, FileAttributes> file in fileSystemChildren)
+            foreach (KeyValuePair<string, WIN32_FIND_DATA> file in fileSystemChildren)
             {
                 // Folders
-                if (file.Value.HasFlag(FileAttributes.Directory))
+                if (file.Value.IsDirectory)
                 {
                     returnFiles.Add(file);
                 }
@@ -220,28 +222,28 @@ namespace MediaBrowser.Controller.Library
                 else if (Shortcut.IsShortcut(file.Key))
                 {
                     string newPath = Shortcut.ResolveShortcut(file.Key);
-                    FileAttributes newPathAttributes = File.GetAttributes(newPath);
+                    WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath);
 
                     // Find out if the shortcut is pointing to a directory or file
 
-                    if (newPathAttributes.HasFlag(FileAttributes.Directory))
+                    if (newPathData.IsDirectory)
                     {
                         // If we're flattening then get the shortcut's children
 
                         if (flattenShortcuts)
                         {
-                            IEnumerable<KeyValuePair<string, FileAttributes>> newChildren = Directory.GetFileSystemEntries(newPath, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, FileAttributes>(f, File.GetAttributes(f)));
+                            IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> newChildren = Directory.GetFileSystemEntries(newPath, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, WIN32_FIND_DATA>(f, FileData.GetFileData(f)));
 
                             returnFiles.AddRange(FilterChildFileSystemEntries(newChildren, false));
                         }
                         else
                         {
-                            returnFiles.Add(new KeyValuePair<string, FileAttributes>(newPath, newPathAttributes));
+                            returnFiles.Add(new KeyValuePair<string, WIN32_FIND_DATA>(newPath, newPathData));
                         }
                     }
                     else
                     {
-                        returnFiles.Add(new KeyValuePair<string, FileAttributes>(newPath, newPathAttributes));
+                        returnFiles.Add(new KeyValuePair<string, WIN32_FIND_DATA>(newPath, newPathData));
                     }
                 }
                 else
@@ -335,8 +337,8 @@ namespace MediaBrowser.Controller.Library
 
             ItemResolveEventArgs args = new ItemResolveEventArgs();
             args.Path = path;
-            args.FileAttributes = File.GetAttributes(path);
-            args.FileSystemChildren = Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, FileAttributes>(f, File.GetAttributes(f)));
+            args.FileData = FileData.GetFileData(path);
+            args.FileSystemChildren = Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly).Select(f => new KeyValuePair<string, WIN32_FIND_DATA>(f, FileData.GetFileData(f)));
 
             await Kernel.Instance.ExecuteMetadataProviders(item, args).ConfigureAwait(false);
 

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

@@ -55,6 +55,7 @@
     <Compile Include="FFMpeg\FFProbe.cs" />
     <Compile Include="FFMpeg\FFProbeResult.cs" />
     <Compile Include="IO\DirectoryWatchers.cs" />
+    <Compile Include="IO\FileData.cs" />
     <Compile Include="IO\Shortcut.cs" />
     <Compile Include="Library\ItemController.cs" />
     <Compile Include="Kernel.cs" />

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

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.ComponentModel.Composition;
 using System.IO;
 using System.Linq;
@@ -6,7 +7,6 @@ using System.Threading.Tasks;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.FFMpeg;
 using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Providers
 {

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

@@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Providers
 
         public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
         {
-            var metadataFile = args.GetFileByName("folder.xml");
+            var metadataFile = args.GetFileSystemEntryByName("folder.xml", false);
 
             if (metadataFile.HasValue)
             {

+ 5 - 4
MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs

@@ -6,6 +6,7 @@ using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.IO;
 
 namespace MediaBrowser.Controller.Providers
 {
@@ -47,9 +48,9 @@ namespace MediaBrowser.Controller.Providers
         /// </summary>
         private void PopulateImages(BaseEntity item, ItemResolveEventArgs args)
         {
-            foreach (KeyValuePair<string, FileAttributes> file in args.FileSystemChildren)
+            foreach (KeyValuePair<string, WIN32_FIND_DATA> file in args.FileSystemChildren)
             {
-                if (file.Value.HasFlag(FileAttributes.Directory))
+                if (file.Value.IsDirectory)
                 {
                     continue;
                 }
@@ -80,9 +81,9 @@ namespace MediaBrowser.Controller.Providers
         {
             List<string> backdropFiles = new List<string>();
 
-            foreach (KeyValuePair<string, FileAttributes> file in args.FileSystemChildren)
+            foreach (KeyValuePair<string, WIN32_FIND_DATA> file in args.FileSystemChildren)
             {
-                if (file.Value.HasFlag(FileAttributes.Directory))
+                if (file.Value.IsDirectory)
                 {
                     continue;
                 }

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

@@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Providers
         {
             BaseItem baseItem = item as BaseItem;
 
-            var trailerPath = args.GetFolderByName("trailers");
+            var trailerPath = args.GetFileSystemEntryByName("trailers", true);
 
             if (trailerPath.HasValue)
             {

+ 1 - 6
MediaBrowser.Controller/Providers/VideoInfoProvider.cs

@@ -66,12 +66,7 @@ namespace MediaBrowser.Controller.Providers
                 return false;
             }
 
-            if (string.IsNullOrEmpty(video.FrameRate))
-            {
-                return false;
-            }
-
-            if (video.Height == 0 || video.Width == 0 || video.BitRate == 0)
+            if (video.FrameRate == 0 || video.Height == 0 || video.Width == 0 || video.BitRate == 0)
             {
                 return false;
             }

+ 24 - 7
MediaBrowser.Controller/Resolvers/BaseItemResolver.cs

@@ -3,6 +3,8 @@ using System.IO;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.IO;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Resolvers
 {
@@ -55,7 +57,7 @@ namespace MediaBrowser.Controller.Resolvers
                 EnsureName(item);
 
                 // Make sure DateCreated and DateModified have values
-                EnsureDates(item);
+                EnsureDates(item, args);
             }
 
             return item;
@@ -74,18 +76,33 @@ namespace MediaBrowser.Controller.Resolvers
         /// <summary>
         /// Ensures DateCreated and DateModified have values
         /// </summary>
-        private void EnsureDates(T item)
+        private void EnsureDates(T item, ItemResolveEventArgs args)
         {
-            // If the subclass didn't supply dates, add them here
-            if (item.DateCreated == DateTime.MinValue)
+            if (!Path.IsPathRooted(item.Path))
             {
-                item.DateCreated = Path.IsPathRooted(item.Path) ? File.GetCreationTime(item.Path) : DateTime.Now;
+                return;
             }
 
-            if (item.DateModified == DateTime.MinValue)
+            WIN32_FIND_DATA fileData = args.FileData;
+
+            // See if a different path came out of the resolver than what went in
+            if (!args.Path.Equals(item.Path, StringComparison.OrdinalIgnoreCase))
             {
-                item.DateModified = Path.IsPathRooted(item.Path) ? File.GetLastWriteTime(item.Path) : DateTime.Now;
+                KeyValuePair<string, WIN32_FIND_DATA>? childData = args.GetFileSystemEntry(item.Path, null);
+
+                if (childData != null)
+                {
+                    fileData = childData.Value.Value;
+                }
+                else
+                {
+                    fileData = FileData.GetFileData(item.Path);
+                }
             }
+
+            item.DateCreated = fileData.CreationTime;
+
+            item.DateModified = fileData.LastWriteTime;
         }
     }
 

+ 3 - 2
MediaBrowser.Controller/Resolvers/VideoResolver.cs

@@ -2,6 +2,7 @@
 using System.ComponentModel.Composition;
 using System.IO;
 using MediaBrowser.Controller.Events;
+using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Controller.Resolvers
@@ -50,9 +51,9 @@ namespace MediaBrowser.Controller.Resolvers
                 }
 
                 // Also check the subfolders for bluray or dvd
-                foreach (KeyValuePair<string, FileAttributes> folder in args.FileSystemChildren)
+                foreach (KeyValuePair<string, WIN32_FIND_DATA> folder in args.FileSystemChildren)
                 {
-                    if (!folder.Value.HasFlag(FileAttributes.Directory))
+                    if (!folder.Value.IsDirectory)
                     {
                         continue;
                     }

+ 1 - 12
MediaBrowser.Controller/Xml/BaseItemXmlParser.cs

@@ -33,17 +33,6 @@ namespace MediaBrowser.Controller.Xml
                     }
                 }
             }
-
-            // If dates weren't supplied in metadata, use values from the xml file
-            if (item.DateCreated == DateTime.MinValue)
-            {
-                item.DateCreated = File.GetCreationTime(metadataFile);
-            }
-
-            if (item.DateModified == DateTime.MinValue)
-            {
-                item.DateModified = File.GetLastWriteTime(metadataFile);
-            }
         }
 
         /// <summary>
@@ -414,7 +403,7 @@ namespace MediaBrowser.Controller.Xml
                             break;
 
                         case "FrameRate":
-                            item.FrameRate = reader.ReadElementContentAsString();
+                            item.FrameRate = reader.ReadFloatSafe();
                             break;
 
                         case "ScanType":

+ 1 - 1
MediaBrowser.Model/Entities/Video.cs

@@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Entities
         public int Height { get; set; }
         public int Width { get; set; }
         public string ScanType { get; set; }
-        public string FrameRate { get; set; }
+        public float FrameRate { get; set; }
         public int BitRate { get; set; }
         public string Codec { get; set; }
     }

+ 1 - 1
MediaBrowser.Movies/Providers/MovieProviderFromXml.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.Movies.Providers
 
         public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
         {
-            var metadataFile = args.GetFileByName("movie.xml");
+            var metadataFile = args.GetFileSystemEntryByName("movie.xml", false);
 
             if (metadataFile.HasValue)
             {

+ 5 - 4
MediaBrowser.Movies/Resolvers/MovieResolver.cs

@@ -5,6 +5,7 @@ using System.IO;
 using System.Linq;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Events;
+using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Movies.Entities;
@@ -24,7 +25,7 @@ namespace MediaBrowser.Movies.Resolvers
                     return null;
                 }
 
-                var metadataFile = args.GetFileByName("movie.xml");
+                var metadataFile = args.GetFileSystemEntryByName("movie.xml", false);
 
                 if (metadataFile.HasValue || Path.GetFileName(args.Path).IndexOf("[tmdbid=", StringComparison.OrdinalIgnoreCase) != -1)
                 {
@@ -57,8 +58,8 @@ namespace MediaBrowser.Movies.Resolvers
                 ItemResolveEventArgs childArgs = new ItemResolveEventArgs()
                 {
                     Path = child.Key,
-                    FileAttributes = child.Value,
-                    FileSystemChildren = new KeyValuePair<string, FileAttributes>[] { }
+                    FileData = child.Value,
+                    FileSystemChildren = new KeyValuePair<string, WIN32_FIND_DATA>[] { }
                 };
 
                 var item = base.Resolve(childArgs);
@@ -78,7 +79,7 @@ namespace MediaBrowser.Movies.Resolvers
 
         private void PopulateBonusFeatures(Movie item, ItemResolveEventArgs args)
         {
-            var trailerPath = args.GetFolderByName("specials");
+            var trailerPath = args.GetFileSystemEntryByName("specials", true);
 
             if (trailerPath.HasValue)
             {

+ 1 - 1
MediaBrowser.TV/Providers/SeriesProviderFromXml.cs

@@ -23,7 +23,7 @@ namespace MediaBrowser.TV.Providers
 
         public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
         {
-            var metadataFile = args.GetFileByName("series.xml");
+            var metadataFile = args.GetFileSystemEntryByName("series.xml", false);
 
             if (metadataFile.HasValue)
             {

+ 1 - 1
MediaBrowser.TV/Resolvers/SeriesResolver.cs

@@ -26,7 +26,7 @@ namespace MediaBrowser.TV.Resolvers
                     return null;
                 }
 
-                var metadataFile = args.GetFileByName("series.xml");
+                var metadataFile = args.GetFileSystemEntryByName("series.xml", false);
 
                 if (metadataFile.HasValue || Path.GetFileName(args.Path).IndexOf("[tvdbid=", StringComparison.OrdinalIgnoreCase) != -1 || TVUtils.IsSeriesFolder(args.Path, args.FileSystemChildren))
                 {

+ 4 - 3
MediaBrowser.TV/TVUtils.cs

@@ -1,7 +1,8 @@
 using System.Collections.Generic;
-using System.Text.RegularExpressions;
 using System.IO;
 using System.Linq;
+using System.Text.RegularExpressions;
+using MediaBrowser.Controller.IO;
 
 namespace MediaBrowser.TV
 {
@@ -52,11 +53,11 @@ namespace MediaBrowser.TV
             return seasonPathExpressions.Any(r => r.IsMatch(path));
         }
 
-        public static bool IsSeriesFolder(string path, IEnumerable<KeyValuePair<string, FileAttributes>> fileSystemChildren)
+        public static bool IsSeriesFolder(string path, IEnumerable<KeyValuePair<string, WIN32_FIND_DATA>> fileSystemChildren)
         {
             foreach (var child in fileSystemChildren)
             {
-                if (child.Value.HasFlag(FileAttributes.Directory))
+                if (child.Value.IsDirectory)
                 {
                     if (IsSeasonFolder(child.Key))
                     {