def _update(self): newObservedFolders = set(self.directories) if self.eventStreamRef is not None: if newObservedFolders == self.observedFolders: return FSEventStreamStop(self.eventStreamRef) FSEventStreamUnscheduleFromRunLoop(self.eventStreamRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode) FSEventStreamInvalidate(self.eventStreamRef) self.observedFolders = newObservedFolders if not newObservedFolders: self.eventStreamRef = None return self.eventStreamRef = FSEventStreamCreate(None, self._fsEventCallback, None, list(newObservedFolders), kFSEventStreamEventIdSinceNow, self.latency, kFSEventStreamCreateFlagNone) FSEventStreamScheduleWithRunLoop(self.eventStreamRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode) FSEventStreamStart(self.eventStreamRef)
def run(self): pool = AppKit.NSAutoreleasePool.alloc().init() self._run_loop = CFRunLoopGetCurrent() FSEventStreamScheduleWithRunLoop(self._stream_ref, self._run_loop, kCFRunLoopDefaultMode) if not FSEventStreamStart(self._stream_ref): FSEventStreamInvalidate(self._stream_ref) FSEventStreamRelease(self._stream_ref) raise IOError('FSEvents. Could not start stream.') CFRunLoopRun() FSEventStreamStop(self._stream_ref) FSEventStreamInvalidate(self._stream_ref) FSEventStreamRelease(self._stream_ref) del pool self._queue.put(None)
def __process_queues(self, timer, context): # Die when asked to. self.lock.acquire() if self.die: CFRunLoopStop(CFRunLoopGetCurrent()) self.lock.release() # Process add queue. self.lock.acquire() if not self.add_queue.empty(): (path, event_mask) = self.add_queue.get() self.lock.release() self.__add_dir(path, event_mask) else: self.lock.release() # Process remove queue. self.lock.acquire() if not self.remove_queue.empty(): path = self.add_queue.get() self.lock.release() self.__remove_dir(path) else: self.lock.release() # Ensure all monitored paths are actually being monitored. If they're # not yet being monitored, start doing so. for path in self.monitored_paths.keys(): if self.monitored_paths[path].monitoring: continue streamRef = self.monitored_paths[path].fsmonitor_ref # Schedule stream on a loop. FSEventStreamScheduleWithRunLoop(streamRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode) # Register with the FS Events service to receive events. started = FSEventStreamStart(streamRef) if not started: raise CouldNotStartError else: self.monitored_paths[path].monitoring = True # Generate the missed events. # TODO: use FSEvents' sinceWhen parameter instead of the current # inefficient scanning method. if self.persistent: FSMonitor.generate_missed_events(self, path)
def start_fs_events(): stream_ref = FSEventStreamCreate( None, # Use the default CFAllocator fsevent_callback, None, # We don't need a FSEventStreamContext FS_WATCHED_FILES.keys(), kFSEventStreamEventIdSinceNow, # We only want events which happen in the future 1.0, # Process events within 1 second 0 # We don't need any special flags for our stream ) if not stream_ref: raise RuntimeError("FSEventStreamCreate() failed!") FSEventStreamScheduleWithRunLoop(stream_ref, NSRunLoop.currentRunLoop().getCFRunLoop(), kCFRunLoopDefaultMode) if not FSEventStreamStart(stream_ref): raise RuntimeError("Unable to start FSEvent stream!") logging.debug("FSEventStream started for %d paths: %s" % (len(FS_WATCHED_FILES), ", ".join(FS_WATCHED_FILES)))