Reputation: 357
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?
}
Upvotes: 8
Views: 5272
Reputation: 6037
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
Upvotes: 1
Reputation: 22948
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:¤tPosition 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 NSNumber
s rather than having to go the somewhat "messier" route of extracting the raw bytes out of AppleEvent descriptor.
Upvotes: 17
Reputation: 34185
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.
Upvotes: 1