// // AppleScript.m // Pennyworth // // Created by Chris Karr on 1/27/08. // Copyright 2008 Chris J. Karr. All rights reserved. // #import "AppleScriptSensor.h" #import "Context.h" #import #define SCRIPT_PATH [NSString stringWithFormat:@"%@/Library/Application Support/Pennyworth/AppleScript/Sensors", NSHomeDirectory ()] #define OSASCRIPT_PATH @"/usr/bin/osascript" #define REFRESH_SCRIPTS 300 #define REFRESH 1 #define DEFAULT_REFRESH 30 #define UPDATE_INTERVAL_KEY @"Script Update Interval" #define LAST_UPDATE_KEY @"Script Last Update" #define IDENTIFIER_KEY @"Script Identifier" @implementation AppleScriptSensor - (void) awakeFromNib { scripts = [[NSMutableDictionary alloc] init]; timer = [[NSTimer scheduledTimerWithTimeInterval:REFRESH_SCRIPTS target:self selector:@selector(refreshScripts:) userInfo:nil repeats:YES] retain]; [timer fire]; callTimer = [[NSTimer scheduledTimerWithTimeInterval:REFRESH target:self selector:@selector(callScripts:) userInfo:nil repeats:YES] retain]; } - (void) callScripts:(NSTimer *) theTimer { NSDate * now = [NSDate date]; NSArray * runningApps = [[NSWorkspace sharedWorkspace] launchedApplications]; for (NSString * path in [scripts allKeys]) { NSMutableDictionary * script = [scripts valueForKey:path]; BOOL running = NO; NSString * scriptIdentifier = [script valueForKey:IDENTIFIER_KEY]; if (scriptIdentifier != nil) { for (NSDictionary * app in runningApps) { if ([[app valueForKey:@"NSApplicationBundleIdentifier"] isEqual:scriptIdentifier]) running = YES; } } else running = YES; NSDate * lastUpdate = [script valueForKey:LAST_UPDATE_KEY]; if (lastUpdate == nil) lastUpdate = [NSDate distantPast]; NSNumber * updateInterval = [script valueForKey:UPDATE_INTERVAL_KEY]; if ([now timeIntervalSinceDate:lastUpdate] > [updateInterval doubleValue] && running) { [NSTask launchedTaskWithLaunchPath:OSASCRIPT_PATH arguments:[NSArray arrayWithObject:path]]; [script setValue:now forKey:LAST_UPDATE_KEY]; } } } - (void) refreshScripts:(NSTimer *) theTimer { [scripts removeAllObjects]; NSFileManager * fm = [NSFileManager defaultManager]; BOOL isDir = NO; if ([fm fileExistsAtPath:SCRIPT_PATH isDirectory:&isDir] && isDir) { NSArray * files = [[fm directoryContentsAtPath:SCRIPT_PATH] sortedArrayUsingSelector:@selector(compare:)]; for (NSString * file in files) { if ([file hasSuffix:@".scpt"]) { NSMutableDictionary * scriptOptions = [scripts valueForKey:[NSString stringWithFormat:@"%@/%@", SCRIPT_PATH, file]]; if (scriptOptions == nil) { scriptOptions = [NSMutableDictionary dictionary]; NSDictionary * errors = nil; NSURL * scriptUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", SCRIPT_PATH, file]]; NSAppleScript * scpt = [[NSAppleScript alloc] initWithContentsOfURL:scriptUrl error:&errors]; if (scpt != nil) { if ([scpt compileAndReturnError:&errors]) { ProcessSerialNumber psn = { 0, kCurrentProcess }; NSAppleEventDescriptor * target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)]; NSAppleEventDescriptor * handler = [NSAppleEventDescriptor descriptorWithString:@"get_interval"]; NSAppleEventDescriptor * event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:handler forKeyword:keyASSubroutineName]; NSAppleEventDescriptor * results = [scpt executeAppleEvent:event error:&errors]; if (results != nil) [scriptOptions setValue:[NSNumber numberWithInt:[results int32Value]] forKey:UPDATE_INTERVAL_KEY]; else [scriptOptions setValue:[NSNumber numberWithInt:DEFAULT_REFRESH] forKey:UPDATE_INTERVAL_KEY]; handler = [NSAppleEventDescriptor descriptorWithString:@"get_identifier"]; event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; [event setParamDescriptor:handler forKeyword:keyASSubroutineName]; results = [scpt executeAppleEvent:event error:&errors]; if (results != nil) [scriptOptions setValue:[results stringValue] forKey:IDENTIFIER_KEY]; [scpt release]; } } [scripts setValue:scriptOptions forKey:[NSString stringWithFormat:@"%@/%@", SCRIPT_PATH, file]]; } } } } else [fm createDirectoryAtPath:SCRIPT_PATH withIntermediateDirectories:YES attributes:nil error:nil]; } @end