jellyfin-server/MediaBrowser.Controller/IO/DirectoryWatchers.cs

148 lines
4.4 KiB
C#
Raw Normal View History

using MediaBrowser.Controller.Entities;
using System;
2012-07-12 06:55:27 +00:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.IO
{
public class DirectoryWatchers
{
2012-09-11 18:20:12 +00:00
private readonly List<FileSystemWatcher> FileSystemWatchers = new List<FileSystemWatcher>();
private Timer updateTimer;
2012-07-12 06:55:27 +00:00
private List<string> affectedPaths = new List<string>();
private const int TimerDelayInSeconds = 5;
public void Start()
{
2012-09-11 19:37:14 +00:00
var pathsToWatch = new List<string>();
2012-07-12 06:55:27 +00:00
var rootFolder = Kernel.Instance.RootFolder;
pathsToWatch.Add(rootFolder.Path);
foreach (Folder folder in rootFolder.Children.OfType<Folder>())
2012-07-12 06:55:27 +00:00
{
foreach (Folder subFolder in folder.Children.OfType<Folder>())
2012-07-12 06:55:27 +00:00
{
if (Path.IsPathRooted(subFolder.Path))
{
string parent = Path.GetDirectoryName(subFolder.Path);
if (!pathsToWatch.Contains(parent))
{
pathsToWatch.Add(parent);
}
}
}
}
foreach (string path in pathsToWatch)
{
2012-09-11 19:37:14 +00:00
var watcher = new FileSystemWatcher(path, "*") { };
2012-07-12 06:55:27 +00:00
watcher.IncludeSubdirectories = true;
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;
watcher.EnableRaisingEvents = true;
FileSystemWatchers.Add(watcher);
}
}
void watcher_Changed(object sender, FileSystemEventArgs e)
{
if (!affectedPaths.Contains(e.FullPath))
{
affectedPaths.Add(e.FullPath);
}
if (updateTimer == null)
{
updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(TimerDelayInSeconds), TimeSpan.FromMilliseconds(-1));
}
else
{
updateTimer.Change(TimeSpan.FromSeconds(TimerDelayInSeconds), TimeSpan.FromMilliseconds(-1));
}
}
private async void TimerStopped(object stateInfo)
2012-07-12 06:55:27 +00:00
{
updateTimer.Dispose();
updateTimer = null;
List<string> paths = affectedPaths;
affectedPaths = new List<string>();
await ProcessPathChanges(paths).ConfigureAwait(false);
2012-07-12 06:55:27 +00:00
}
2012-08-22 02:50:59 +00:00
private Task ProcessPathChanges(IEnumerable<string> paths)
2012-07-12 06:55:27 +00:00
{
2012-09-11 19:37:14 +00:00
var itemsToRefresh = new List<BaseItem>();
2012-07-12 06:55:27 +00:00
foreach (BaseItem item in paths.Select(p => GetAffectedBaseItem(p)))
{
if (item != null && !itemsToRefresh.Contains(item))
{
itemsToRefresh.Add(item);
}
}
if (itemsToRefresh.Any(i =>
{
var folder = i as Folder;
return folder != null && folder.IsRoot;
}))
{
2012-08-22 02:50:59 +00:00
return Kernel.Instance.ReloadRoot();
2012-07-12 06:55:27 +00:00
}
2012-09-11 18:20:12 +00:00
return Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
2012-07-12 06:55:27 +00:00
}
private BaseItem GetAffectedBaseItem(string path)
{
BaseItem item = null;
while (item == null)
{
item = Kernel.Instance.RootFolder.FindByPath(path);
path = Path.GetDirectoryName(path);
}
return item;
}
public void Stop()
{
foreach (FileSystemWatcher watcher in FileSystemWatchers)
{
watcher.Changed -= watcher_Changed;
watcher.EnableRaisingEvents = false;
watcher.Dispose();
}
if (updateTimer != null)
{
updateTimer.Dispose();
updateTimer = null;
}
FileSystemWatchers.Clear();
affectedPaths.Clear();
}
}
}