Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting AppleScript return value in Obj-C

I'm using some AppleScript in my Obj-C cocoa project to control QuickTime player (play, pause, stop, jog forward and back etc.) with great success, though my knowledge of AppleScript is very limited. However, what I want most of all is the movie's 'Current Time' offset to convert into time-stamps for writing a subtitle script.

The following simple method shows the precise current position in (float) seconds in a dialog, but I'd really like the AppleScript to return me a variable that I can use in the rest of app. How could I modify the code below to do that? Is it even possible to access this value? Thanks a million in advance :-)

-(IBAction)currentPlayTime:(id)sender
{
    NSString *scriptString=[NSString stringWithFormat:
        // get time of current frame... (works perfectly)!
        @"tell application \"QuickTime Player\"\n"
            @"set timeScale to 600\n"
            @"set curr_pos to current time of movie 1/timeScale\n"
            @"display dialog curr_pos\n" // ...not in a practical form to use
        @"end tell\n"];

    NSDictionary *errorDict= nil;
    NSAppleScript *appleScriptObject=[[NSAppleScript alloc] initWithSource:scriptString];
    NSAppleEventDescriptor *eventDescriptor=[appleScriptObject executeAndReturnError:   &errorDict];
    // handle any errors here (snipped for brevity)
    [appleScriptObject release]; // can I retain this?
}
like image 710
Bender Avatar asked Jul 24 '11 02:07

Bender


1 Answers

Here's the appropriate AppleScript that you'd want to run:

property timeScale : 600

set currentPosition to missing value

tell application "QuickTime Player"
    set currentPosition to (current time of document 1) / timeScale
end tell

return currentPosition

In case you're not familiar with it, property is a way to specify a global variable in AppleScript. Also, missing value is the AppleScript equivalent of nil in Objective-C. So, this script first defines a variable named currentPosition, and sets the value to missing value. It then enters the tell block which, if it succeeds, will alter the currentPosition variable. Then, outside of the tell block, it returns the currentPosition variable.

In the Objective-C code, when you create an NSAppleScript with the above code, its -executeAndReturnError: method will return the currentPosition variable in an NSAppleScriptEventDescriptor.

-(IBAction)currentPlayTime:(id)sender {

    NSDictionary *error = nil;

    NSMutableString *scriptText = [NSMutableString stringWithString:@"property timeScale : 600\n"];
    [scriptText appendString:@"set currentPosition to missing value\n"];
    [scriptText appendString:@"tell application \"QuickTime Player\"\n "];
    [scriptText appendString:@"set currentPosition to (current time of document 1) / timeScale\n"];
    [scriptText appendString:@"end tell\n"];
    [scriptText appendString:@"return currentPosition\n"];

    NSAppleScript *script = [[[NSAppleScript alloc] initWithSource:scriptText] autorelease];

    NSAppleEventDescriptor *result = [script executeAndReturnError:&error];

    NSLog(@"result == %@", result);

    DescType descriptorType = [result descriptorType];

    NSLog(@"descriptorType == %@", NSFileTypeForHFSTypeCode(descriptorType));

    // returns a double

    NSData *data = [result data];
    double currentPosition = 0;

    [data getBytes:&currentPosition length:[data length]];

    NSLog(@"currentPosition == %f", currentPosition);
}

You can extract the contents of the NSAppleEventDescriptor as shown above.

Using the Scripting Bridge framework does have a slight learning curve, but would allow working with native types such as NSNumbers rather than having to go the somewhat "messier" route of extracting the raw bytes out of AppleEvent descriptor.

like image 122
NSGod Avatar answered Sep 24 '22 05:09

NSGod