开发者

Getting AppleScript return value in Obj-C

开发者 https://www.devze.com 2023-03-22 23:54 出处:网络
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.

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开发者_如何学Python 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?
}


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.


Use Scripting Bridge. This is a bridge between AppleScript and Objective-C, and other applications (e.g. QuickTime Player) is represented as an Objectve-C object in your code. So, you don't have to construct AppleScript code by hand.

Some say AppScript is better than Scripting Bridge.


NSAppleEventDescriptor has some methods to convert to some objective-C types, if you go to my site and download the NDScript project, it has a category of NSAppleEventDescriptor which adds a lot more methods for coercion to Objective-C type. You can use that category without the rest of the project. http://homepage.mac.com/nathan_day/pages/source.xml

0

精彩评论

暂无评论...
验证码 换一张
取 消