-
-
Save pudquick/a412dd6a87c751f96160e8699d203dc4 to your computer and use it in GitHub Desktop.
[Catalyst] Registering for & responding to AppleScript events in a Mac Catalyst app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<key>NSAppleScriptEnabled</key> | |
<true/> | |
<key>OSAScriptingDefinition</key> | |
<string>ScriptableTasks.sdef</string> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MRDScripting.h | |
// RadioIntegration | |
// | |
// Created by Steven Troughton-Smith on 26/10/2019. | |
// Copyright © 2019 High Caffeine Content. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
NS_ASSUME_NONNULL_BEGIN | |
@protocol MRDScriptingDelegate <NSObject> | |
-(void)playRadioStation:(NSString *)station; | |
-(void)pause; | |
-(void)setVolume:(CGFloat)volume; | |
@end | |
@interface MRDScripting : NSObject | |
@property id <MRDScriptingDelegate> delegate; | |
+ (instancetype)sharedInstance; | |
+(void)initScripting; | |
@end | |
NS_ASSUME_NONNULL_END |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MRDScripting.m | |
// RadioIntegration | |
// | |
// Created by Steven Troughton-Smith on 26/10/2019. | |
// Copyright © 2019 High Caffeine Content. All rights reserved. | |
// | |
#import "MRDScripting.h" | |
@import AppleScriptKit; | |
@implementation MRDScripting | |
OSErr myPauseHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, SRefCon handlerRefcon) | |
{ | |
if ([MRDScripting sharedInstance].delegate && [[MRDScripting sharedInstance].delegate respondsToSelector:@selector(pause)]) | |
[[MRDScripting sharedInstance].delegate pause]; | |
return noErr; | |
} | |
OSErr myHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, SRefCon handlerRefcon) | |
{ | |
NSLog(@"Handling Apple Event"); | |
AEDesc replyObject; | |
OSErr err; | |
err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &replyObject); | |
if (err != noErr) { | |
NSLog(@"Error decoding %c", replyObject.descriptorType); | |
} | |
CFStringRef descRef = UTCreateStringForOSType(replyObject.descriptorType); | |
NSString * descString = [NSString stringWithString:(__bridge NSString *)descRef]; | |
NSLog(@"Type = %@", descString); | |
Size sz = AEGetDescDataSize(&replyObject); | |
if (sz) | |
{ | |
char *r = malloc(sz); | |
AEGetDescData(&replyObject, &r[0], sz); | |
NSString *param = [[NSString alloc] initWithBytes:r length:sz encoding:NSUTF16LittleEndianStringEncoding]; | |
if ([MRDScripting sharedInstance].delegate && [[MRDScripting sharedInstance].delegate respondsToSelector:@selector(playRadioStation:)]) | |
[[MRDScripting sharedInstance].delegate playRadioStation:param]; | |
} | |
return noErr; | |
} | |
OSErr myVolumeHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, SRefCon handlerRefcon) | |
{ | |
NSLog(@"Handling Apple Event"); | |
AEDesc replyObject; | |
OSErr err; | |
err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &replyObject); | |
if (err != noErr) { | |
NSLog(@"Error decoding %c", replyObject.descriptorType); | |
} | |
CFStringRef descRef = UTCreateStringForOSType(replyObject.descriptorType); | |
NSString * descString = [NSString stringWithString:(__bridge NSString *)descRef]; | |
NSLog(@"Type = %@", descString); | |
Size sz = AEGetDescDataSize(&replyObject); | |
if (sz) | |
{ | |
if ([descString isEqualToString:@"doub"]) | |
{ | |
CGFloat *r = malloc(sz); | |
AEGetDescData(&replyObject, &r[0], sz); | |
CGFloat volume = r[0]; | |
if (volume >= 0.0 && volume <= 1.0) | |
{ | |
NSLog(@"desired volume = %f", volume); | |
if ([MRDScripting sharedInstance].delegate && [[MRDScripting sharedInstance].delegate respondsToSelector:@selector(setVolume:)]) | |
[[MRDScripting sharedInstance].delegate setVolume:volume]; | |
} | |
else | |
{ | |
return paramErr; | |
} | |
} | |
else if ([descString isEqualToString:@"long"]) | |
{ | |
long *r = malloc(sz); | |
AEGetDescData(&replyObject, &r[0], sz); | |
long volume = r[0]; | |
if (volume >= 0.0 && volume <= 1.0) | |
{ | |
NSLog(@"desired volume LONG = %ld", volume); | |
if ([MRDScripting sharedInstance].delegate && [[MRDScripting sharedInstance].delegate respondsToSelector:@selector(setVolume:)]) | |
[[MRDScripting sharedInstance].delegate setVolume:(CGFloat)volume]; | |
} | |
else | |
{ | |
return paramErr; | |
} | |
} | |
} | |
return noErr; | |
} | |
+(void)initScripting | |
{ | |
AEInstallEventHandler('HCCR', 'play', myHandler, NULL, false); | |
AEInstallEventHandler('HCCR', 'paus', myPauseHandler, NULL, false); | |
AEInstallEventHandler('HCCR', 'volu', myVolumeHandler, NULL, false); | |
} | |
+ (instancetype)sharedInstance | |
{ | |
static dispatch_once_t once; | |
static id sharedInstance; | |
dispatch_once(&once, ^{ | |
sharedInstance = [[self alloc] init]; | |
}); | |
return sharedInstance; | |
} | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd"> | |
<dictionary> | |
<suite name="HCC Radio suite" code="HCCR" description="Standard terms for HCC Radio scripting"> | |
<command name="play" code="HCCRplay" description="Plays a radio station"> | |
<direct-parameter type="text" optional="no" description="the name of the station to play"/> | |
</command> | |
<command name="pause" code="HCCRpaus" description="Pauses playback"> | |
</command> | |
<command name="set volume" code="HCCRvolu" description="Sets playback volume"> | |
<direct-parameter type="number" optional="no" description="the desired volume, valid from 0.0 to 1.0"/> | |
</command> | |
</suite> | |
</dictionary> | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Loading your AppKit bundle */ | |
NSError *error = nil; | |
[[NSBundle bundleWithPath:[[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"RadioIntegration.framework"]] loadAndReturnError:&error]; | |
/* After loading your AppKit framework/bundle */ | |
[NSClassFromString(@"MRDScripting") initScripting]; | |
/* In class that wants to register for scripting delegate callbacks */ | |
[[NSClassFromString(@"MRDScripting") sharedInstance] setDelegate:self]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment