From 0c07b8c44c22963fe59230b83c9386ea4147ecad Mon Sep 17 00:00:00 2001 From: James Coleman Date: Sun, 29 Jul 2012 16:49:33 -0500 Subject: [PATCH] Updated the path subscriber as Mountain Lion seemed to have deprecated and broke FNSubscribeByPath. The new update checks if you are on 10.5 or later and if you are it will use the new FileSystem Events. --- Classes/CocoaShare/MGMPathSubscriber.m | 78 ++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 11 deletions(-) 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];