aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/IO
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/IO')
-rw-r--r--MediaBrowser.Controller/IO/DirectoryWatchers.cs67
-rw-r--r--MediaBrowser.Controller/IO/FileSystemHelper.cs132
-rw-r--r--MediaBrowser.Controller/IO/Shortcut.cs2
3 files changed, 179 insertions, 22 deletions
diff --git a/MediaBrowser.Controller/IO/DirectoryWatchers.cs b/MediaBrowser.Controller/IO/DirectoryWatchers.cs
index ce7f65d39..eb1358e16 100644
--- a/MediaBrowser.Controller/IO/DirectoryWatchers.cs
+++ b/MediaBrowser.Controller/IO/DirectoryWatchers.cs
@@ -1,4 +1,6 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Common.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
@@ -14,7 +16,7 @@ namespace MediaBrowser.Controller.IO
private Timer updateTimer;
private List<string> affectedPaths = new List<string>();
- private const int TimerDelayInSeconds = 5;
+ private const int TimerDelayInSeconds = 30;
public void Start()
{
@@ -26,32 +28,29 @@ namespace MediaBrowser.Controller.IO
foreach (Folder folder in rootFolder.Children.OfType<Folder>())
{
- foreach (Folder subFolder in folder.Children.OfType<Folder>())
+ foreach (string path in folder.PhysicalLocations)
{
- if (Path.IsPathRooted(subFolder.Path))
+ if (Path.IsPathRooted(path) && !pathsToWatch.ContainsParentFolder(path))
{
- string parent = Path.GetDirectoryName(subFolder.Path);
-
- if (!pathsToWatch.Contains(parent))
- {
- pathsToWatch.Add(parent);
- }
+ pathsToWatch.Add(path);
}
}
}
foreach (string path in pathsToWatch)
{
- var watcher = new FileSystemWatcher(path, "*") { };
+ Logger.LogInfo("Watching directory " + path + " for changes.");
+ var watcher = new FileSystemWatcher(path, "*") { };
watcher.IncludeSubdirectories = true;
- watcher.Changed += watcher_Changed;
+ //watcher.Changed += watcher_Changed;
// All the others seem to trigger change events on the parent, so let's keep it simple for now.
- //watcher.Created += watcher_Changed;
- //watcher.Deleted += watcher_Changed;
- //watcher.Renamed += watcher_Changed;
+ // Actually, we really need to only watch created, deleted and renamed as changed fires too much -ebr
+ watcher.Created += watcher_Changed;
+ watcher.Deleted += watcher_Changed;
+ watcher.Renamed += watcher_Changed;
watcher.EnableRaisingEvents = true;
FileSystemWatchers.Add(watcher);
@@ -60,9 +59,30 @@ namespace MediaBrowser.Controller.IO
void watcher_Changed(object sender, FileSystemEventArgs e)
{
- if (!affectedPaths.Contains(e.FullPath))
+ Logger.LogDebugInfo("****** Watcher sees change of type " + e.ChangeType.ToString() + " to " + e.FullPath);
+ lock (affectedPaths)
{
- affectedPaths.Add(e.FullPath);
+ //Since we're watching created, deleted and renamed we always want the parent of the item to be the affected path
+ var affectedPath = Path.GetDirectoryName(e.FullPath);
+
+ if (e.ChangeType == WatcherChangeTypes.Renamed)
+ {
+ var renamedArgs = e as RenamedEventArgs;
+ if (affectedPaths.Contains(renamedArgs.OldFullPath))
+ {
+ Logger.LogDebugInfo("****** Removing " + renamedArgs.OldFullPath + " from affected paths.");
+ affectedPaths.Remove(renamedArgs.OldFullPath);
+ }
+ }
+
+ //If anything underneath this path was already marked as affected - remove it as it will now get captured by this one
+ affectedPaths.RemoveAll(p => p.StartsWith(e.FullPath, StringComparison.OrdinalIgnoreCase));
+
+ if (!affectedPaths.ContainsParentFolder(affectedPath))
+ {
+ Logger.LogDebugInfo("****** Adding " + affectedPath + " to affected paths.");
+ affectedPaths.Add(affectedPath);
+ }
}
if (updateTimer == null)
@@ -79,9 +99,12 @@ namespace MediaBrowser.Controller.IO
{
updateTimer.Dispose();
updateTimer = null;
-
- List<string> paths = affectedPaths;
- affectedPaths = new List<string>();
+ List<string> paths;
+ lock (affectedPaths)
+ {
+ paths = affectedPaths;
+ affectedPaths = new List<string>();
+ }
await ProcessPathChanges(paths).ConfigureAwait(false);
}
@@ -108,14 +131,16 @@ namespace MediaBrowser.Controller.IO
return Kernel.Instance.ReloadRoot();
}
- return Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
+ foreach (var p in paths) Logger.LogDebugInfo("********* "+ p + " reports change.");
+ foreach (var i in itemsToRefresh) Logger.LogDebugInfo("********* "+i.Name + " ("+ i.Path + ") will be refreshed.");
+ return Task.WhenAll(itemsToRefresh.Select(i => i.ChangedExternally()));
}
private BaseItem GetAffectedBaseItem(string path)
{
BaseItem item = null;
- while (item == null)
+ while (item == null && !string.IsNullOrEmpty(path))
{
item = Kernel.Instance.RootFolder.FindByPath(path);
diff --git a/MediaBrowser.Controller/IO/FileSystemHelper.cs b/MediaBrowser.Controller/IO/FileSystemHelper.cs
new file mode 100644
index 000000000..732cf0803
--- /dev/null
+++ b/MediaBrowser.Controller/IO/FileSystemHelper.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Resolvers;
+using MediaBrowser.Controller.Library;
+
+namespace MediaBrowser.Controller.IO
+{
+ public static class FileSystemHelper
+ {
+ /// <summary>
+ /// Transforms shortcuts into their actual paths and filters out items that should be ignored
+ /// </summary>
+ public static ItemResolveEventArgs FilterChildFileSystemEntries(ItemResolveEventArgs args, bool flattenShortcuts)
+ {
+
+ List<WIN32_FIND_DATA> returnChildren = new List<WIN32_FIND_DATA>();
+ List<WIN32_FIND_DATA> resolvedShortcuts = new List<WIN32_FIND_DATA>();
+
+ foreach (var file in args.FileSystemChildren)
+ {
+ // If it's a shortcut, resolve it
+ if (Shortcut.IsShortcut(file.Path))
+ {
+ string newPath = Shortcut.ResolveShortcut(file.Path);
+ WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath);
+
+ // Find out if the shortcut is pointing to a directory or file
+ if (newPathData.IsDirectory)
+ {
+ // add to our physical locations
+ args.AdditionalLocations.Add(newPath);
+
+ // If we're flattening then get the shortcut's children
+ if (flattenShortcuts)
+ {
+ returnChildren.Add(file);
+ ItemResolveEventArgs newArgs = new ItemResolveEventArgs()
+ {
+ FileSystemChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray()
+ };
+
+ resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newArgs, false).FileSystemChildren);
+ }
+ else
+ {
+ returnChildren.Add(newPathData);
+ }
+ }
+ else
+ {
+ returnChildren.Add(newPathData);
+ }
+ }
+ else
+ {
+ //not a shortcut check to see if we should filter it out
+ if (EntityResolutionHelper.ShouldResolvePath(file))
+ {
+ returnChildren.Add(file);
+ }
+ else
+ {
+ //filtered - see if it is one of our "indicator" folders and mark it now - no reason to search for it again
+ args.IsBDFolder |= file.cFileName.Equals("bdmv", StringComparison.OrdinalIgnoreCase);
+ args.IsDVDFolder |= file.cFileName.Equals("video_ts", StringComparison.OrdinalIgnoreCase);
+ args.IsHDDVDFolder |= file.cFileName.Equals("hvdvd_ts", StringComparison.OrdinalIgnoreCase);
+
+ //and check to see if it is a metadata folder and collect contents now if so
+ if (IsMetadataFolder(file.cFileName))
+ {
+ args.MetadataFiles = Directory.GetFiles(Path.Combine(args.Path, "metadata"), "*", SearchOption.TopDirectoryOnly);
+ }
+ }
+ }
+ }
+
+ if (resolvedShortcuts.Count > 0)
+ {
+ resolvedShortcuts.InsertRange(0, returnChildren);
+ args.FileSystemChildren = resolvedShortcuts.ToArray();
+ }
+ else
+ {
+ args.FileSystemChildren = returnChildren.ToArray();
+ }
+ return args;
+ }
+
+ public static bool IsMetadataFolder(string path)
+ {
+ return path.TrimEnd('\\').EndsWith("metadata", StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsVideoFile(string path)
+ {
+ string extension = System.IO.Path.GetExtension(path).ToLower();
+
+ switch (extension)
+ {
+ case ".mkv":
+ case ".m2ts":
+ case ".iso":
+ case ".ts":
+ case ".rmvb":
+ case ".mov":
+ case ".avi":
+ case ".mpg":
+ case ".mpeg":
+ case ".wmv":
+ case ".mp4":
+ case ".divx":
+ case ".dvr-ms":
+ case ".wtv":
+ case ".ogm":
+ case ".ogv":
+ case ".asf":
+ case ".m4v":
+ case ".flv":
+ case ".f4v":
+ case ".3gp":
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/IO/Shortcut.cs b/MediaBrowser.Controller/IO/Shortcut.cs
index 683f44573..e9ea21f17 100644
--- a/MediaBrowser.Controller/IO/Shortcut.cs
+++ b/MediaBrowser.Controller/IO/Shortcut.cs
@@ -179,7 +179,7 @@ namespace MediaBrowser.Controller.IO
public static bool IsShortcut(string filename)
{
- return Path.GetExtension(filename).EndsWith("lnk", StringComparison.OrdinalIgnoreCase);
+ return filename != null ? Path.GetExtension(filename).EndsWith("lnk", StringComparison.OrdinalIgnoreCase) : false;
}
}
}