diff -r 000000000000 -r 629c7605ab2a MYDirectoryWatcher.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MYDirectoryWatcher.m Wed Apr 08 16:31:19 2009 -0700 @@ -0,0 +1,206 @@ +// +// MYDirectoryWatcher.m +// Murky +// +// Copyright 2008 Jens Alfke. All rights reserved. +// + +#import "MYDirectoryWatcher.h" +#import + + +static void directoryWatcherCallback(ConstFSEventStreamRef streamRef, + void *clientCallBackInfo, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]); + +@interface MYDirectoryEvent () +- (id) _initWithWatcher: (MYDirectoryWatcher*)itsWatcher + path: (NSString*)itsPath + flags: (FSEventStreamEventFlags)itsFlags + eventID: (FSEventStreamEventId)itsEventID; +@end + + +@implementation MYDirectoryWatcher + + +- (id) initWithDirectory: (NSString*)path target: (id)target action: (SEL)action +{ + NSParameterAssert(path); + self = [super init]; + if (self != nil) { + _path = path.copy; + _target = target; + _action = action; + _latency = 5.0; + _lastEventID = kFSEventStreamEventIdSinceNow; + } + return self; +} + +- (void) dealloc +{ + [self stop]; + [_path release]; + [super dealloc]; +} + +- (void) finalize +{ + [self stop]; + [super finalize]; +} + + +@synthesize path=_path, latency=_latency, lastEventID=_lastEventID; + + +- (BOOL) start +{ + if( ! _stream ) { + FSEventStreamContext context = {0,self,NULL,NULL,NULL}; + _stream = FSEventStreamCreate(NULL, + &directoryWatcherCallback, &context, + (CFArrayRef)[NSArray arrayWithObject: _path], + _lastEventID, + _latency, + kFSEventStreamCreateFlagUseCFTypes); + if( ! _stream ) + return NO; + FSEventStreamScheduleWithRunLoop(_stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + if( ! FSEventStreamStart(_stream) ) { + [self stop]; + return NO; + } + _historyDone = (_lastEventID == kFSEventStreamEventIdSinceNow); + Log(@"MYDirectoryWatcher: Started on %@ (latency=%g, lastEvent=%llu)",_path,_latency,_lastEventID); + } + return YES; +} + +- (void) pause +{ + if( _stream ) { + FSEventStreamStop(_stream); + FSEventStreamInvalidate(_stream); + FSEventStreamRelease(_stream); + _stream = NULL; + Log(@"MYDirectoryWatcher: Stopped on %@ (lastEvent=%llu)",_path,_lastEventID); + } +} + +- (void) stop +{ + [self pause]; + _lastEventID = kFSEventStreamEventIdSinceNow; // so events from now till next start will be dropped + [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(start) object: nil]; +} + +- (void) stopTemporarily +{ + if( _stream ) { + [self stop]; + [self performSelector: @selector(start) withObject: nil afterDelay: 0.0]; + } +} + + +- (void) _notifyEvents: (size_t)numEvents + paths: (NSArray*)paths + flags: (const FSEventStreamEventFlags[])eventFlags + eventIDs: (const FSEventStreamEventId[])eventIDs +{ + for (size_t i=0; i