Skip to content

Instantly share code, notes, and snippets.

@farcaller
Created January 5, 2009 10:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save farcaller/afd6d189306b7bccc75d to your computer and use it in GitHub Desktop.
Save farcaller/afd6d189306b7bccc75d to your computer and use it in GitHub Desktop.
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