Created
January 5, 2009 10:13
-
-
Save farcaller/afd6d189306b7bccc75d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From c0591174b25f350a68cc3c2bb1f4ce1c5896e1f5 Mon Sep 17 00:00:00 2001 | |
From: Vladimir Pouzanov <farcaller@gmail.com> | |
Date: Mon, 5 Jan 2009 12:00:42 +0200 | |
Subject: [PATCH] Added spotlight comments to torrent files | |
--- | |
macosx/Torrent.h | 5 ++ | |
macosx/Torrent.m | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
2 files changed, 135 insertions(+), 0 deletions(-) | |
diff --git a/macosx/Torrent.h b/macosx/Torrent.h | |
index cc2b037..31f3362 100644 | |
--- a/macosx/Torrent.h | |
+++ b/macosx/Torrent.h | |
@@ -74,6 +74,10 @@ typedef enum | |
BOOL fAddedTrackers; | |
NSDictionary * fQuickPauseDict; | |
+ | |
+ BOOL fSpotlightSeeding; | |
+ BOOL fSpotlightActive; | |
+ NSString * fSpotlightGroup; | |
} | |
- (id) initWithPath: (NSString *) path location: (NSString *) location deleteTorrentFile: (torrentFileState) torrentDelete | |
@@ -94,6 +98,7 @@ typedef enum | |
- (NSIndexSet *) previousFinishedPieces; | |
-(void) setPreviousFinishedPieces: (NSIndexSet *) indexes; | |
+- (void)updateSpotlightComment:(BOOL)forcedQuit; | |
- (void) update; | |
- (void) startTransfer; | |
diff --git a/macosx/Torrent.m b/macosx/Torrent.m | |
index d30e225..3e62f2f 100644 | |
--- a/macosx/Torrent.m | |
+++ b/macosx/Torrent.m | |
@@ -175,6 +175,7 @@ int trashDataFile(const char * filename) | |
- (void) dealloc | |
{ | |
+ [self updateSpotlightComment:YES]; | |
[[NSNotificationCenter defaultCenter] removeObserver: self]; | |
if (fFileStat) | |
@@ -198,6 +199,8 @@ int trashDataFile(const char * filename) | |
[fQuickPauseDict release]; | |
+ [fSpotlightGroup release]; | |
+ | |
[super dealloc]; | |
} | |
@@ -212,6 +215,7 @@ int trashDataFile(const char * filename) | |
[self setTimeMachineExclude: NO forPath: [[self downloadFolder] stringByAppendingPathComponent: [self name]]]; | |
tr_torrentRemove(fHandle); | |
+ [self updateSpotlightComment:YES]; | |
} | |
- (void) changeIncompleteDownloadFolder: (NSString *) folder | |
@@ -268,6 +272,125 @@ int trashDataFile(const char * filename) | |
fPreviousFinishedIndexesDate = indexes != nil ? [[NSDate alloc] init] : nil; | |
} | |
+// Comment set code from Bibdesk by Adam Maxwell | |
+// Sets a file ref descriptor from a path, without following symlinks | |
+// Based on OAAppKit's fillAEDescFromPath and an example in http://www.cocoadev.com/index.pl?FSMakeFSSpec | |
+static OSErr BDSKFillAEDescFromPath(AEDesc *fileRefDescPtr, NSString *path, BOOL isSymLink) | |
+{ | |
+ FSRef fileRef; | |
+ AEDesc fileRefDesc; | |
+ OSErr err; | |
+ | |
+ bzero(&fileRef, sizeof(fileRef)); | |
+ | |
+ err = FSPathMakeRefWithOptions((UInt8 *)[path fileSystemRepresentation], kFSPathMakeRefDoNotFollowLeafSymlink, &fileRef, NULL); | |
+ | |
+ if (err != noErr) | |
+ return err; | |
+ | |
+ AEInitializeDesc(&fileRefDesc); | |
+ err = AECreateDesc(typeFSRef, &fileRef, sizeof(fileRef), &fileRefDesc); | |
+ | |
+ // Omni says the Finder isn't very good at coercions, so we have to do this ourselves; however we don't want to lose symlinks | |
+ if (err == noErr){ | |
+ if(isSymLink == NO) | |
+ err = AECoerceDesc(&fileRefDesc, typeAlias, fileRefDescPtr); | |
+ else | |
+ err = AEDuplicateDesc(&fileRefDesc, fileRefDescPtr); | |
+ } | |
+ AEDisposeDesc(&fileRefDesc); | |
+ | |
+ return err; | |
+} | |
+ | |
+static OSType finderSignatureBytes = 'MACS'; | |
+ | |
+// Sets the Finder comment (Spotlight comment) field via the Finder; this method takes 0.01s to execute, vs. 0.5s for NSAppleScript | |
+// Based on OAAppKit's setComment:forPath: and http://developer.apple.com/samplecode/MoreAppleEvents/MoreAppleEvents.html (which is dated) | |
+- (BOOL)setSpotlightComment:(NSString *)comment forPath:(NSString *)filePath; | |
+{ | |
+ NSParameterAssert(comment != nil); | |
+ //NSParameterAssert([fileURL isFileURL]); | |
+ NSString *path = filePath; | |
+ BOOL isSymLink = NO; //[[[self fileAttributesAtPath:path traverseLink:NO] objectForKey:NSFileType] isEqualToString:NSFileTypeSymbolicLink]; | |
+ BOOL success = YES; | |
+ NSAppleEventDescriptor *commentTextDesc; | |
+ OSErr err; | |
+ AEDesc fileDesc, builtEvent; | |
+ const char *eventFormat = | |
+ "'----': 'obj '{ " // Direct object is the file comment we want to modify | |
+ " form: enum(prop), " // ... the comment is an object's property... | |
+ " seld: type(comt), " // ... selected by the 'comt' 4CC ... | |
+ " want: type(prop), " // ... which we want to interpret as a property (not as e.g. text). | |
+ " from: 'obj '{ " // It's the property of an object... | |
+ " form: enum(indx), " | |
+ " want: type(file), " // ... of type 'file' ... | |
+ " seld: @," // ... selected by an alias ... | |
+ " from: null() " // ... according to the receiving application. | |
+ " }" | |
+ " }, " | |
+ "data: @"; // The data is what we want to set the direct object to. | |
+ | |
+ commentTextDesc = [NSAppleEventDescriptor descriptorWithString:comment]; | |
+ | |
+ AEInitializeDesc(&builtEvent); | |
+ | |
+ err = BDSKFillAEDescFromPath(&fileDesc, path, isSymLink); | |
+ | |
+ if (err == noErr) | |
+ err = AEBuildAppleEvent(kAECoreSuite, kAESetData, | |
+ typeApplSignature, &finderSignatureBytes, sizeof(finderSignatureBytes), | |
+ kAutoGenerateReturnID, kAnyTransactionID, | |
+ &builtEvent, NULL, | |
+ eventFormat, | |
+ &fileDesc, [commentTextDesc aeDesc]); | |
+ | |
+ //AEDisposeDesc(&fileDesc); | |
+ | |
+ if (err == noErr) | |
+ err = AESendMessage(&builtEvent, NULL, kAENoReply, kAEDefaultTimeout); | |
+ | |
+ AEDisposeDesc(&builtEvent); | |
+ | |
+ if (err != noErr) { | |
+ NSLog(@"Unable to set comment for file %@", filePath); | |
+ success = NO; | |
+ } | |
+ NSLog(@"%@ for %@", comment, filePath); | |
+ return success; | |
+} | |
+ | |
+- (void)updateSpotlightComment:(BOOL)forcedQuit | |
+{ | |
+ NSString *newGrp = [[GroupsController groups] nameForIndex:fGroupValue]; | |
+ [fSpotlightGroup release]; | |
+ fSpotlightGroup = [newGrp retain]; | |
+ if(!forcedQuit) { | |
+ fSpotlightSeeding = [self isSeeding]; | |
+ fSpotlightActive = [self isActive]; | |
+ } else { | |
+ fSpotlightSeeding = NO; | |
+ fSpotlightActive = NO; | |
+ } | |
+ NSMutableString *cmnt = [NSMutableString stringWithFormat:@"state_%s%s", | |
+ fSpotlightActive?"active":"stopped", | |
+ fSpotlightSeeding?" state_seeding":""]; | |
+ if(fSpotlightGroup) | |
+ [cmnt appendFormat:@" group: %@", fSpotlightGroup]; | |
+ NSString *torComment = [self comment]; | |
+ if([torComment length]) | |
+ [cmnt appendFormat:@" comment:%@", torComment]; | |
+ NSString *pfx = [self shouldUseIncompleteFolderForName: [self name]] ? fIncompleteFolder : fDownloadFolder; | |
+ for(FileListNode *fn in fFileList) { | |
+ [self setSpotlightComment:cmnt forPath:[pfx stringByAppendingFormat:@"/%@",[fn fullPath]]]; | |
+ } | |
+ | |
+ // TODO: figure a better way if we have a torrent dir | |
+ if([fFileList count] > 1) { | |
+ [self setSpotlightComment:cmnt forPath:[pfx stringByAppendingFormat:@"/%@",fNameString]]; | |
+ } | |
+} | |
+ | |
- (void) update | |
{ | |
//get previous status values before update | |
@@ -301,6 +424,11 @@ int trashDataFile(const char * filename) | |
//update queue for checking (from downloading to seeding), stalled, or error | |
if ((wasChecking && ![self isChecking]) || (wasStalled != fStalled) || (!wasError && [self isError] && [self isActive])) | |
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self]; | |
+ | |
+ //update spotlight comment if changed | |
+ NSString *newGrp = [[GroupsController groups] nameForIndex:fGroupValue]; | |
+ if ((fSpotlightActive != [self isActive]) || (fSpotlightSeeding != [self isSeeding]) || (![newGrp isEqualToString:fSpotlightGroup])) | |
+ [self updateSpotlightComment:NO]; | |
} | |
- (void) startTransfer | |
@@ -311,6 +439,7 @@ int trashDataFile(const char * filename) | |
if (![self isActive] && [self alertForFolderAvailable] && [self alertForRemainingDiskSpace]) | |
{ | |
tr_torrentStart(fHandle); | |
+ [self updateSpotlightComment:NO]; | |
[self update]; | |
} | |
} | |
@@ -322,6 +451,7 @@ int trashDataFile(const char * filename) | |
if ([self isActive]) | |
{ | |
tr_torrentStop(fHandle); | |
+ [self updateSpotlightComment:NO]; | |
[self update]; | |
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self]; | |
-- | |
1.6.1+GitX |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment