Pennyworth

Context Sensing for Mac OS X

Developing compatible applications

First of all, before embedding Pennyworth-specific code within your application, please review the AppleScripting documentation to determine if a more general AppleScripting approach is appropriate for your application. AppleScripting gives you the following advantages:

  • Applications other than Pennyworth will be able to control your program.

  • AppleScript is a fairly robust and user-friendly way of allowing your users to automate and script your application.

However, AppleScripting includes a few downsides when used with Pennyworth:

  • Pennyworth throttles the number of AppleScript calls it makes in order to manage performance. If your context switches six times within the span of a second, only the sixth will be sent to the AppleScripts.

  • Implementing an AppleScript interface may be difficult (depending upon your application's design).

  • AppleScripts are not nearly as fast as native applications and they may not share useful third-party libraries.

If incorporating native code to communicate with Pennyworth is the best option for your application, read on.

Using your application as a Pennyworth sensor

If you would like to expose some information about the internal state of your application to Pennyworth as an observation or sensor reading (a good example is whether your user is reading or writing a document), your application can communicate with Pennyworth using NSDistributedNotificationCenter:

NSMutableDictionary * note = [NSMutableDictionary dictionary];

[note setValue:[[NSDate date] description] 
        forKey:COCOA_OBSERVATION_VALUE];
[note setValue:@"My Cocoa Sensor" 
        forKey:COCOA_OBSERVER];
[note setValue:[NSNumber numberWithInt:10]
        forKey:COCOA_OBSERVATION_DURATION];

[[NSDistributedNotificationCenter defaultCenter] 
                    postNotificationName:COCOA_OBSERVATION
                                  object:@"my.application.id"
                                userInfo:note];

The COCOA_OBSERVER entry corresponds with the name of your sensor, COCOA_OBSERVATION_DURATION is an optional duration (in seconds) for the observation, and COCOA_OBSERVATION_VALUE is the value (e.g. Reading or Writing). The observation value may be any data type that can be serialized using XML property lists (see this document for details) and may include NSString and NSArray objects. In the example above, the native sensor sends a string representing the current date and time as a reading.

Listening for context changes

If your application needs to take action based on changes in the user's context, your application may receive these changes by adding an observer to the default NSDistributedNotificationCenter:

[[NSDistributedNotificationCenter defaultCenter] 
                    addObserver:self 
                       selector:@selector(process:) 
                           name:PREDICTION_FETCHED 
                         object:nil];

The observed notification will contain a userInfo dictionary with a key and prediction entry:

- (void) process:(NSNotification *) theNote
{
    NSString * key = [[theNote userInfo] valueForKey:KEY];
    NSString * prediction = [[theNote userInfo] valueForKey:PREDICTION];
	
    NSLog (@"%@ = %@", key, prediction);
}

The key corresponds to the context element (Activity, Location, or Social Context), while the prediction contains the value (e.g. Programming, Home, With Family).

Sample code

If you need a more concrete example demonstrating how to implement the functions described above, we prepared a small Xcode project that implements both sending and receiving functions in the AppDelegate class. It isn't the most sophisticated example, but it should be sufficient to get you started.

Comments

This is an early version of a document that we plan on refining and improving as needed. If you have any questions or comments, please send us an e-mail. Over time, we hope to expand this section provide more information and serve as a general resource for Pennyworth-aware software developers.