Skip to content

Instantly share code, notes, and snippets.

@mauricio
Created March 22, 2012 20:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mauricio/2164127 to your computer and use it in GitHub Desktop.
Save mauricio/2164127 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using MonoMac.Foundation;
using System.Threading;
using NUnit.Framework;
using System.Text;
namespace Test
{
class MainClass
{
private FSEventStreamCallback callback;
public void Main ()
{
this.callback = this.Callback;
string testFolder = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "mono-test");
if (Directory.Exists (testFolder)) {
Directory.Delete (testFolder, true);
}
Directory.CreateDirectory (testFolder);
IntPtr path = CFStringCreateWithCString (IntPtr.Zero, testFolder, 0);
IntPtr paths = CFArrayCreate (IntPtr.Zero, new IntPtr [1] { path }, 1, IntPtr.Zero);
IntPtr stream = FSEventStreamCreate (IntPtr.Zero, this.callback, IntPtr.Zero, paths, FSEventStreamEventIdSinceNow, 0, FSEventStreamCreateFlags.WatchRoot | FSEventStreamCreateFlags.FileEvents);
CFRelease (paths);
CFRelease (path);
Thread runLoop = new Thread (delegate() {
FSEventStreamScheduleWithRunLoop (stream, CFRunLoopGetCurrent (), kCFRunLoopDefaultMode);
FSEventStreamStart (stream);
CFRunLoopRun ();
});
runLoop.Name = "FSEventStream";
runLoop.Start ();
Thread.Sleep (3000);
string file1 = Path.Combine (testFolder, "file1.txt");
//Thread.Sleep(1000);
using (System.IO.File.Create(file1)) {
}
//Thread.Sleep(1000);
System.IO.File.WriteAllText (file1, "file1");
//Thread.Sleep(1000);
System.IO.File.Delete (file1);
}
public static void Main (string[] args)
{
new MainClass ().Main();
}
private static IDictionary<IntPtr, MainClass> thisDict = new Dictionary<IntPtr, MainClass> ();
private void Callback (IntPtr streamRef, IntPtr clientCallBackInfo, int numEvents, IntPtr eventPaths, IntPtr eventFlags, IntPtr eventIds)
{
MainClass thisObj;
if (this != null) {
thisDict.Add (streamRef, this);
thisObj = this;
} else {
thisObj = thisDict [streamRef];
}
Console.WriteLine ("\n{0}", this != null ? "this is not null" : "this is null");
string[] paths = new string[numEvents];
UInt32[] flags = new UInt32[numEvents];
UInt64[] ids = new UInt64[numEvents];
unsafe {
char** eventPathsPointer = (char**)eventPaths.ToPointer ();
uint* eventFlagsPointer = (uint*)eventFlags.ToPointer ();
ulong* eventIdsPointer = (ulong*)eventIds.ToPointer ();
for (int i = 0; i < numEvents; i++) {
paths [i] = Marshal.PtrToStringAuto (new IntPtr (eventPathsPointer [i]));
flags [i] = eventFlagsPointer [i];
ids [i] = eventIdsPointer [i];
}
}
Console.WriteLine ("Number of events: {0}", numEvents);
for (int i = 0; i < numEvents; i++) {
Console.WriteLine ("{0} {1:x8} {2}", ids [i], flags [i], paths [i]);
Console.WriteLine ("Modified: {0:x8}", (flags [i] & (uint)FSEventStreamEventFlagItem.Modified));
Console.WriteLine ("Created: {0:x8}", (flags [i] & (uint)FSEventStreamEventFlagItem.Created));
Console.WriteLine ("Removed: {0:x8}", (flags [i] & (uint)FSEventStreamEventFlagItem.Removed));
Console.WriteLine ("Renamed: {0:x8}", (flags [i] & (uint)FSEventStreamEventFlagItem.Renamed));
Console.WriteLine ();
}
}
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFStringCreateWithCString (IntPtr allocator, string value, int encoding);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr [] values, int numValues, IntPtr callBacks);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFArrayGetValueAtIndex (IntPtr array, int index);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static void CFRelease (IntPtr cf);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFRunLoopGetCurrent ();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFRunLoopGetMain ();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static void CFRunLoopRun ();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static int CFRunLoopRunInMode (IntPtr mode, double seconds, int returnAfterSourceHandled);
delegate void FSEventStreamCallback (IntPtr streamRef,IntPtr clientCallBackInfo,int numEvents,IntPtr eventPaths,IntPtr eventFlags,IntPtr eventIds);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static IntPtr FSEventStreamCreate (IntPtr allocator, FSEventStreamCallback callback, IntPtr context, IntPtr pathsToWatch, ulong sinceWhen, double latency, FSEventStreamCreateFlags flags);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static int FSEventStreamStart (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamStop (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamRelease (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamScheduleWithRunLoop (IntPtr streamRef, IntPtr runLoop, IntPtr runLoopMode);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamUnscheduleFromRunLoop (IntPtr streamRef, IntPtr runLoop, IntPtr runLoopMode);
const ulong FSEventStreamEventIdSinceNow = ulong.MaxValue;
private static IntPtr kCFRunLoopDefaultMode = CFStringCreateWithCString (IntPtr.Zero, "kCFRunLoopDefaultMode", 0);
[Flags()]
enum FSEventStreamCreateFlags : uint
{
None = 0x00000000,
UseCFTypes = 0x00000001,
NoDefer = 0x00000002,
WatchRoot = 0x00000004,
IgnoreSelf = 0x00000008,
FileEvents = 0x00000010
}
[Flags()]
enum FSEventStreamEventFlag : uint
{
None = 0x00000000,
MustScanSubDirs = 0x00000001,
UserDropped = 0x00000002,
KernelDropped = 0x00000004,
EventIdsWrapped = 0x00000008,
HistoryDone = 0x00000010,
RootChanged = 0x00000020,
FlagMount = 0x00000040,
Unmount = 0x00000080
}
[Flags()]
enum FSEventStreamEventFlagItem : uint
{
Created = 0x00000100,
Removed = 0x00000200,
InodeMetaMod = 0x00000400,
Renamed = 0x00000800,
Modified = 0x00001000,
FinderInfoMod = 0x00002000,
ChangeOwner = 0x00004000,
XattrMod = 0x00008000,
IsFile = 0x00010000,
IsDir = 0x00020000,
IsSymlink = 0x00040000
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment