diff --git a/Classes/CocoaShare/MGMPathSubscriber.m b/Classes/CocoaShare/MGMPathSubscriber.m index 3f34c57..1afe3db 100644 --- a/Classes/CocoaShare/MGMPathSubscriber.m +++ b/Classes/CocoaShare/MGMPathSubscriber.m @@ -10,6 +10,7 @@ @interface MGMPathSubscriber (MGMPrivate) - (void)subscriptionChanged:(FNSubscriptionRef)theSubscription; +- (void)subscriptionFSChanged:(ConstFSEventStreamRef)theSubscription; - (void)sendNotificationForPath:(NSString *)thePath; @end @@ -17,10 +18,19 @@ static MGMPathSubscriber *MGMSharedPathSubscriber; NSString * const MGMSubscribedPathChangedNotification = @"MGMSubscribedPathChangedNotification"; void MGMPathSubscriptionChange(FNMessage theMessage, OptionBits theFlags, void *thePathSubscription, FNSubscriptionRef theSubscription) { - if (theMessage==kFNDirectoryModifiedMessage) - [(MGMPathSubscriber *)thePathSubscription subscriptionChanged:theSubscription]; + if (theMessage==kFNDirectoryModifiedMessage) + [(MGMPathSubscriber *)thePathSubscription subscriptionChanged:theSubscription]; else - NSLog(@"MGMPathSubscription: Received Unknown message: %d", (int)theMessage); + NSLog(@"MGMPathSubscription: Received Unknown message: %u", theMessage); +} + +void MGMPathSubscriptionFSChange(ConstFSEventStreamRef streamRef, void *thePathSubscription, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { + for (size_t i=0; i=5) { + FSEventStreamRef stream = FSEventStreamCreate(NULL, &MGMPathSubscriptionFSChange, &context, (CFArrayRef)[NSArray arrayWithObject:thePath], kFSEventStreamEventIdSinceNow, 0.5, kFSEventStreamCreateFlagNone); + if (stream==NULL) { + NSLog(@"MGMPathSubscription: Unable to subscribe to %@", thePath); + return; + } + FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + FSEventStreamStart(stream); + [subscriptions setObject:[NSValue valueWithPointer:stream] forKey:thePath]; + } else { + FNSubscriptionRef subscription = NULL; + OSStatus error = FNSubscribeByPath((UInt8 *)[thePath fileSystemRepresentation], subscriptionUPP, self, kFNNotifyInBackground, &subscription); + if (error!=noErr) { + NSLog(@"MGMPathSubscription: Unable to subscribe to %@ due to the error %ld", thePath, (long)error); + return; + } + [subscriptions setObject:[NSValue valueWithPointer:subscription] forKey:thePath]; } - [subscriptions setObject:[NSValue valueWithPointer:subscription] forKey:thePath]; } - (void)removePath:(NSString *)thePath { NSValue *value = [subscriptions objectForKey:thePath]; if (value!=nil) { - FNUnsubscribe([value pointerValue]); - [subscriptions removeObjectForKey:thePath]; + if ([self OSMajorVersion]==10 && [self OSMinorVersion]>=5) { + FSEventStreamRef stream = [value pointerValue]; + FSEventStreamStop(stream); + FSEventStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + FSEventStreamInvalidate(stream); + FSEventStreamRelease(stream); + [subscriptions removeObjectForKey:thePath]; + } else { + FNUnsubscribe([value pointerValue]); + [subscriptions removeObjectForKey:thePath]; + } } } - (void)removeAllPaths { @@ -93,6 +139,16 @@ void MGMPathSubscriptionChange(FNMessage theMessage, OptionBits theFlags, void * } } } +- (void)subscriptionFSChanged:(ConstFSEventStreamRef)theSubscription { + NSArray *keys = [subscriptions allKeysForObject:[NSValue valueWithPointer:theSubscription]]; + if ([keys count]>=1) { + NSString *path = [keys objectAtIndex:0]; + if (![notificationsSending containsObject:path]) { + [notificationsSending addObject:path]; + [self performSelector:@selector(sendNotificationForPath:) withObject:path afterDelay:0.5]; + } + } +} - (void)sendNotificationForPath:(NSString *)thePath { [[NSNotificationCenter defaultCenter] postNotificationName:MGMSubscribedPathChangedNotification object:thePath]; if ([delegate respondsToSelector:@selector(subscribedPathChanged:)]) [delegate subscribedPathChanged:thePath];