1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
using System;
using System.Collections;
using System.IO;
using Muine.PluginLib;
using Gtk;
namespace Muine
{
public class InotifyPlugin : Plugin
{
private IPlayer player;
private ThreadNotify notify;
private ArrayList foldersToAdd = new ArrayList ();
private ArrayList foldersToRemove = new ArrayList ();
private ArrayList filesToAdd = new ArrayList ();
private ArrayList filesToRemove = new ArrayList ();
public override void Initialize (IPlayer player)
{
if (!Inotify.Enabled)
return;
this.player = player;
notify = new ThreadNotify (new ReadyEvent (OnNotify));
foreach (string dir in player.WatchedFolders)
Watch (dir);
player.WatchedFoldersChangedEvent += OnFoldersChanged;
Inotify.Start ();
}
private void OnFoldersChanged ()
{
foreach (string dir in player.WatchedFolders)
Watch (dir);
}
private void OnNotify ()
{
lock (this)
{
foreach (string folder in foldersToAdd)
{
//Console.WriteLine ("Adding folder: " + folder);
Watch (folder);
player.AddFolder (folder);
}
foreach (string folder in foldersToRemove)
{
//Console.WriteLine ("Removing folder: " + folder);
player.RemoveFolder (folder);
}
foreach (string file in filesToAdd) player.AddSong (file);
foreach (string file in filesToRemove) player.RemoveSong (file);
foldersToAdd.Clear ();
foldersToRemove.Clear ();
filesToAdd.Clear ();
filesToRemove.Clear ();
}
}
private bool HasFlag (Inotify.EventType type, Inotify.EventType value)
{
return ((type & value) == value);
}
private void OnInotifyEvent (Inotify.Watch watch, string path, string subitem,
string srcpath, Inotify.EventType type)
{
/*
Console.WriteLine ("Got event ({03}) {0}: {1}/{2}", type, path, subitem,
srcpath);
*/
string fullPath = Path.Combine (path, subitem);
lock (this)
{
if (HasFlag (type, Inotify.EventType.MovedTo) ||
HasFlag (type, Inotify.EventType.CloseWrite))
{
if (HasFlag (type, Inotify.EventType.IsDirectory) &&
!HasFlag (type, Inotify.EventType.CloseWrite))
{
foldersToAdd.Add (fullPath);
if (srcpath != null)
foldersToRemove.Add (srcpath);
}
else
{
filesToAdd.Add (fullPath);
if (srcpath != null)
filesToRemove.Add (srcpath);
}
}
else if (HasFlag (type, Inotify.EventType.Create) &&
HasFlag (type, Inotify.EventType.IsDirectory))
{
Watch (fullPath);
}
else if (HasFlag (type, Inotify.EventType.Delete) ||
HasFlag (type, Inotify.EventType.MovedFrom))
{
if (HasFlag (type, Inotify.EventType.IsDirectory))
foldersToRemove.Add (fullPath);
else
filesToRemove.Add (fullPath);
}
notify.WakeupMain ();
}
}
private void Watch (string folder)
{
/* Do not monitor non existing directories */
if (!Directory.Exists (folder))
return;
/* Do not monitor lost+found directories, since these
* are not accesible to mortal users. */
if (folder.EndsWith("lost+found"))
return;
/* Do not monitor trash folders */
if (folder.EndsWith(".Trash"))
return;
/* Do not monitor per-user trash folders, eg. on removable
* devices. These are * named ".Trash-username" */
if (Path.GetFileName(folder).StartsWith(".Trash-"))
return;
Inotify.Subscribe (folder, new Inotify.InotifyCallback (OnInotifyEvent),
Inotify.EventType.CloseWrite | Inotify.EventType.Delete |
Inotify.EventType.Create | Inotify.EventType.MovedFrom |
Inotify.EventType.MovedTo);
foreach (string dir in Directory.GetDirectories (folder)) {
Watch (dir);
}
}
}
}
|