rb-scpt 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES +497 -0
- data/doc/aem-manual/01_introduction.html +60 -0
- data/doc/aem-manual/02_apioverview.html +107 -0
- data/doc/aem-manual/03_packingandunpackingdata.html +135 -0
- data/doc/aem-manual/04_references.html +409 -0
- data/doc/aem-manual/05_targetingapplications.html +164 -0
- data/doc/aem-manual/06_buildingandsendingevents.html +229 -0
- data/doc/aem-manual/07_findapp.html +63 -0
- data/doc/aem-manual/08_examples.html +94 -0
- data/doc/aem-manual/aemreferenceinheritance.gif +0 -0
- data/doc/aem-manual/index.html +56 -0
- data/doc/appscript-manual/01_introduction.html +94 -0
- data/doc/appscript-manual/02_aboutappscripting.html +247 -0
- data/doc/appscript-manual/03_quicktutorial.html +167 -0
- data/doc/appscript-manual/04_gettinghelp.html +188 -0
- data/doc/appscript-manual/05_keywordconversion.html +106 -0
- data/doc/appscript-manual/06_classesandenums.html +192 -0
- data/doc/appscript-manual/07_applicationobjects.html +211 -0
- data/doc/appscript-manual/08_realvsgenericreferences.html +96 -0
- data/doc/appscript-manual/09_referenceforms.html +241 -0
- data/doc/appscript-manual/10_referenceexamples.html +154 -0
- data/doc/appscript-manual/11_applicationcommands.html +245 -0
- data/doc/appscript-manual/12_commandexamples.html +138 -0
- data/doc/appscript-manual/13_performanceissues.html +142 -0
- data/doc/appscript-manual/14_notes.html +80 -0
- data/doc/appscript-manual/application_architecture.gif +0 -0
- data/doc/appscript-manual/application_architecture2.gif +0 -0
- data/doc/appscript-manual/finder_to_textedit_event.gif +0 -0
- data/doc/appscript-manual/index.html +62 -0
- data/doc/appscript-manual/relationships_example.gif +0 -0
- data/doc/appscript-manual/ruby_to_itunes_event.gif +0 -0
- data/doc/full.css +106 -0
- data/doc/index.html +45 -0
- data/doc/mactypes-manual/01_introduction.html +54 -0
- data/doc/mactypes-manual/02_aliasclass.html +124 -0
- data/doc/mactypes-manual/03_fileurlclass.html +126 -0
- data/doc/mactypes-manual/04_unitsclass.html +100 -0
- data/doc/mactypes-manual/index.html +53 -0
- data/doc/osax-manual/01_introduction.html +67 -0
- data/doc/osax-manual/02_interface.html +147 -0
- data/doc/osax-manual/03_examples.html +73 -0
- data/doc/osax-manual/04_notes.html +61 -0
- data/doc/osax-manual/index.html +53 -0
- data/doc/rb-appscript-logo.png +0 -0
- data/extconf.rb +65 -0
- data/rb-scpt.gemspec +14 -0
- data/sample/AB_export_vcard.rb +31 -0
- data/sample/AB_list_people_with_emails.rb +13 -0
- data/sample/Add_iCal_event.rb +21 -0
- data/sample/Create_daily_iCal_todos.rb +75 -0
- data/sample/Export_Address_Book_phone_numbers.rb +59 -0
- data/sample/Hello_world.rb +21 -0
- data/sample/List_iTunes_playlist_names.rb +11 -0
- data/sample/Make_Mail_message.rb +33 -0
- data/sample/Open_file_in_TextEdit.rb +13 -0
- data/sample/Organize_Mail_messages.rb +61 -0
- data/sample/Print_folder_tree.rb +16 -0
- data/sample/Select_all_HTML_files.rb +14 -0
- data/sample/Set_iChat_status.rb +24 -0
- data/sample/Simple_Finder_GUI_Scripting.rb +18 -0
- data/sample/Stagger_Finder_windows.rb +25 -0
- data/sample/TextEdit_demo.rb +130 -0
- data/sample/iTunes_top40_to_html.rb +71 -0
- data/src/SendThreadSafe.c +380 -0
- data/src/SendThreadSafe.h +139 -0
- data/src/lib/_aem/aemreference.rb +1022 -0
- data/src/lib/_aem/codecs.rb +662 -0
- data/src/lib/_aem/connect.rb +205 -0
- data/src/lib/_aem/encodingsupport.rb +77 -0
- data/src/lib/_aem/findapp.rb +85 -0
- data/src/lib/_aem/mactypes.rb +251 -0
- data/src/lib/_aem/send.rb +279 -0
- data/src/lib/_aem/typewrappers.rb +59 -0
- data/src/lib/_appscript/defaultterminology.rb +277 -0
- data/src/lib/_appscript/referencerenderer.rb +245 -0
- data/src/lib/_appscript/reservedkeywords.rb +116 -0
- data/src/lib/_appscript/safeobject.rb +249 -0
- data/src/lib/_appscript/terminology.rb +471 -0
- data/src/lib/aem.rb +253 -0
- data/src/lib/appscript.rb +1075 -0
- data/src/lib/kae.rb +1489 -0
- data/src/lib/osax.rb +659 -0
- data/src/rbae.c +979 -0
- data/test/README +3 -0
- data/test/test_aemreference.rb +118 -0
- data/test/test_appscriptcommands.rb +152 -0
- data/test/test_appscriptreference.rb +106 -0
- data/test/test_codecs.rb +186 -0
- data/test/test_findapp.rb +26 -0
- data/test/test_mactypes.rb +79 -0
- data/test/test_osax.rb +54 -0
- data/test/testall.sh +10 -0
- metadata +145 -0
data/src/rbae.c
ADDED
|
@@ -0,0 +1,979 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* rb-appscript
|
|
3
|
+
*
|
|
4
|
+
* ae -- a low-level API providing a basic Ruby wrapper around the various
|
|
5
|
+
* Apple Event Manager, Process Manager and Launch Services APIs used by aem
|
|
6
|
+
*
|
|
7
|
+
* Thanks to:
|
|
8
|
+
* - FUJIMOTO Hisakuni, author of RubyAEOSA
|
|
9
|
+
* - Jordan Breeding (64-bit support patch)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#include "osx_ruby.h"
|
|
13
|
+
#include <Carbon/Carbon.h>
|
|
14
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
15
|
+
#include "SendThreadSafe.h"
|
|
16
|
+
|
|
17
|
+
// AE module and classes
|
|
18
|
+
static VALUE mAE;
|
|
19
|
+
static VALUE cAEDesc;
|
|
20
|
+
static VALUE cMacOSError;
|
|
21
|
+
|
|
22
|
+
// Note: AEDescs need extra wrapping to avoid nasty problems with Ruby's Data_Wrap_Struct.
|
|
23
|
+
struct rbAE_AEDescWrapper {
|
|
24
|
+
AEDesc desc;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// (these two macros are basically cribbed from RubyAEOSA's aedesc.c)
|
|
28
|
+
#define AEDESC_DATA_PTR(o) ((struct rbAE_AEDescWrapper*)(DATA_PTR(o)))
|
|
29
|
+
#define AEDESC_OF(o) (AEDESC_DATA_PTR(o)->desc)
|
|
30
|
+
|
|
31
|
+
// Event handling
|
|
32
|
+
#if __LP64__
|
|
33
|
+
// SRefCon typedefed as void * by system headers
|
|
34
|
+
#else
|
|
35
|
+
typedef long SRefCon;
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
AEEventHandlerUPP upp_GenericEventHandler;
|
|
39
|
+
AECoercionHandlerUPP upp_GenericCoercionHandler;
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// these macros were added in 1.8.6
|
|
43
|
+
|
|
44
|
+
#if !defined(RSTRING_LEN)
|
|
45
|
+
#define RSTRING_LEN(x) (RSTRING(x)->len)
|
|
46
|
+
#define RSTRING_PTR(x) (RSTRING(x)->ptr)
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**********************************************************************/
|
|
51
|
+
// Raise MacOS error
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* Note: MacOSError should only be raised by AE module; attempting to raise it from Ruby
|
|
55
|
+
* just results in unexpected errors. (I've not quite figured out how to implement an
|
|
56
|
+
* Exception class in C that constructs correctly in both C and Ruby. Not serious, since
|
|
57
|
+
* nobody else needs to raise MacOSErrors - just a bit irritating.)
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
static void
|
|
61
|
+
rbAE_raiseMacOSError(const char *description, OSErr number)
|
|
62
|
+
{
|
|
63
|
+
VALUE errObj;
|
|
64
|
+
|
|
65
|
+
errObj = rb_funcall(cMacOSError, rb_intern("new"), 0);
|
|
66
|
+
rb_iv_set(errObj, "@number", INT2NUM(number)); // returns the OS error number
|
|
67
|
+
rb_iv_set(errObj, "@description", rb_str_new2(description)); // troubleshooting info
|
|
68
|
+
rb_exc_raise(errObj);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/**********************************************************************/
|
|
73
|
+
// MacOSError methods
|
|
74
|
+
|
|
75
|
+
static VALUE
|
|
76
|
+
rbAE_MacOSError_inspect(VALUE self)
|
|
77
|
+
{
|
|
78
|
+
char s[32];
|
|
79
|
+
|
|
80
|
+
sprintf(s, "#<AE::MacOSError %li>", (long)NUM2INT(rb_iv_get(self, "@number")));
|
|
81
|
+
return rb_str_new2(s);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
/**********************************************************************/
|
|
86
|
+
// AEDesc support functions
|
|
87
|
+
|
|
88
|
+
static DescType
|
|
89
|
+
rbStringToDescType(VALUE obj)
|
|
90
|
+
{
|
|
91
|
+
if (rb_obj_is_kind_of(obj, rb_cString) && RSTRING_LEN(obj) == 4) {
|
|
92
|
+
return CFSwapInt32HostToBig(*(DescType *)(RSTRING_PTR(obj)));
|
|
93
|
+
} else {
|
|
94
|
+
rb_raise(rb_eArgError, "Not a four-char-code string.");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static VALUE
|
|
99
|
+
rbDescTypeToString(DescType descType)
|
|
100
|
+
{
|
|
101
|
+
char s[4];
|
|
102
|
+
|
|
103
|
+
*(DescType*)s = CFSwapInt32HostToBig(descType);
|
|
104
|
+
return rb_str_new(s, 4);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*******/
|
|
108
|
+
|
|
109
|
+
static void
|
|
110
|
+
rbAE_freeAEDesc(struct rbAE_AEDescWrapper *p)
|
|
111
|
+
{
|
|
112
|
+
AEDisposeDesc(&(p->desc));
|
|
113
|
+
free(p);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static VALUE
|
|
117
|
+
rbAE_wrapAEDesc(const AEDesc *desc)
|
|
118
|
+
{
|
|
119
|
+
struct rbAE_AEDescWrapper *wrapper;
|
|
120
|
+
|
|
121
|
+
// Found out how to wrap AEDescs so Ruby wouldn't crash by reading RubyAEOSA's aedesc.c
|
|
122
|
+
wrapper = malloc(sizeof(struct rbAE_AEDescWrapper));
|
|
123
|
+
wrapper->desc = *desc;
|
|
124
|
+
return Data_Wrap_Struct(cAEDesc, 0, rbAE_freeAEDesc, wrapper);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/*******/
|
|
128
|
+
// Note: clients should not attempt to use retain/use borrowed AE::AEDesc instances after handler callbacks return,
|
|
129
|
+
// as AEM will have disposed of the underlying AEDesc objects by then
|
|
130
|
+
|
|
131
|
+
static void
|
|
132
|
+
rbAE_freeBorrowedAEDesc(struct rbAE_AEDescWrapper *p)
|
|
133
|
+
{
|
|
134
|
+
free(p);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static VALUE
|
|
138
|
+
rbAE_wrapBorrowedAEDesc(const AEDesc *desc)
|
|
139
|
+
{
|
|
140
|
+
struct rbAE_AEDescWrapper *wrapper;
|
|
141
|
+
|
|
142
|
+
wrapper = malloc(sizeof(struct rbAE_AEDescWrapper));
|
|
143
|
+
wrapper->desc = *desc;
|
|
144
|
+
return Data_Wrap_Struct(cAEDesc, 0, rbAE_freeBorrowedAEDesc, wrapper);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**********************************************************************/
|
|
148
|
+
// AEDesc constructors
|
|
149
|
+
|
|
150
|
+
static VALUE
|
|
151
|
+
rbAE_AEDesc_new(VALUE class, VALUE type, VALUE data)
|
|
152
|
+
{
|
|
153
|
+
OSErr err = noErr;
|
|
154
|
+
AEDesc desc;
|
|
155
|
+
|
|
156
|
+
Check_Type(data, T_STRING);
|
|
157
|
+
err = AECreateDesc(rbStringToDescType(type),
|
|
158
|
+
RSTRING_PTR(data), RSTRING_LEN(data),
|
|
159
|
+
&desc);
|
|
160
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AEDesc.", err);
|
|
161
|
+
return rbAE_wrapAEDesc(&desc);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
static VALUE
|
|
166
|
+
rbAE_AEDesc_newList(VALUE class, VALUE isRecord)
|
|
167
|
+
{
|
|
168
|
+
OSErr err = noErr;
|
|
169
|
+
AEDesc desc;
|
|
170
|
+
|
|
171
|
+
err = AECreateList(NULL, 0, RTEST(isRecord), &desc);
|
|
172
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AEDescList.", err);
|
|
173
|
+
return rbAE_wrapAEDesc(&desc);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
static VALUE
|
|
178
|
+
rbAE_AEDesc_newAppleEvent(VALUE class, VALUE eventClassValue, VALUE eventIDValue,
|
|
179
|
+
VALUE targetValue, VALUE returnIDValue, VALUE transactionIDValue)
|
|
180
|
+
{
|
|
181
|
+
OSErr err = noErr;
|
|
182
|
+
AEEventClass theAEEventClass = rbStringToDescType(eventClassValue);
|
|
183
|
+
AEEventID theAEEventID = rbStringToDescType(eventIDValue);
|
|
184
|
+
AEAddressDesc target = AEDESC_OF(targetValue);
|
|
185
|
+
AEReturnID returnID = NUM2INT(returnIDValue);
|
|
186
|
+
AETransactionID transactionID = NUM2LONG(transactionIDValue);
|
|
187
|
+
AppleEvent result;
|
|
188
|
+
|
|
189
|
+
err = AECreateAppleEvent(theAEEventClass,
|
|
190
|
+
theAEEventID,
|
|
191
|
+
&target,
|
|
192
|
+
returnID,
|
|
193
|
+
transactionID,
|
|
194
|
+
&result);
|
|
195
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AppleEvent.", err);
|
|
196
|
+
// workaround for return ID bug in 10.6
|
|
197
|
+
AEDesc returnIDDesc;
|
|
198
|
+
if (returnID == kAutoGenerateReturnID) {
|
|
199
|
+
err = AEGetAttributeDesc(&result, keyReturnIDAttr, typeSInt32, &returnIDDesc);
|
|
200
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AppleEvent.", err);
|
|
201
|
+
err = AEGetDescData(&returnIDDesc, &returnID, sizeof(returnID));
|
|
202
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AppleEvent.", err);
|
|
203
|
+
if (returnID == -1) {
|
|
204
|
+
AEDisposeDesc(&result);
|
|
205
|
+
err = AECreateAppleEvent(theAEEventClass,
|
|
206
|
+
theAEEventID,
|
|
207
|
+
&target,
|
|
208
|
+
returnID,
|
|
209
|
+
transactionID,
|
|
210
|
+
&result);
|
|
211
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AppleEvent.", err);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return rbAE_wrapAEDesc(&result);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
static VALUE
|
|
219
|
+
rbAE_AEDesc_newUnflatten(VALUE class, VALUE data)
|
|
220
|
+
{
|
|
221
|
+
OSErr err = noErr;
|
|
222
|
+
AEDesc desc;
|
|
223
|
+
|
|
224
|
+
Check_Type(data, T_STRING);
|
|
225
|
+
err = AEUnflattenDesc(RSTRING_PTR(data), &desc);
|
|
226
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AEDesc.", err);
|
|
227
|
+
return rbAE_wrapAEDesc(&desc);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
/**********************************************************************/
|
|
232
|
+
// AEDesc methods
|
|
233
|
+
|
|
234
|
+
static VALUE
|
|
235
|
+
rbAE_AEDesc_inspect(VALUE self)
|
|
236
|
+
{
|
|
237
|
+
VALUE s, type;
|
|
238
|
+
Size dataSize;
|
|
239
|
+
|
|
240
|
+
s = rb_str_new2("#<AE::AEDesc type=%s size=%i>");
|
|
241
|
+
type = rb_funcall(self, rb_intern("type"), 0);
|
|
242
|
+
dataSize = AEGetDescDataSize(&(AEDESC_OF(self)));
|
|
243
|
+
return rb_funcall(s,
|
|
244
|
+
rb_intern("%"),
|
|
245
|
+
1,
|
|
246
|
+
rb_ary_new3(2,
|
|
247
|
+
rb_funcall(type, rb_intern("inspect"), 0),
|
|
248
|
+
INT2NUM(dataSize)
|
|
249
|
+
)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
/*******/
|
|
255
|
+
|
|
256
|
+
static VALUE
|
|
257
|
+
rbAE_AEDesc_type(VALUE self)
|
|
258
|
+
{
|
|
259
|
+
return rbDescTypeToString(AEDESC_OF(self).descriptorType);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
static VALUE
|
|
264
|
+
rbAE_AEDesc_data(VALUE self)
|
|
265
|
+
{
|
|
266
|
+
OSErr err = noErr;
|
|
267
|
+
Size dataSize;
|
|
268
|
+
void *data;
|
|
269
|
+
VALUE result;
|
|
270
|
+
|
|
271
|
+
dataSize = AEGetDescDataSize(&(AEDESC_OF(self)));
|
|
272
|
+
data = malloc(dataSize);
|
|
273
|
+
err = AEGetDescData(&(AEDESC_OF(self)), data, dataSize);
|
|
274
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get AEDesc data.", err);
|
|
275
|
+
result = rb_str_new(data, dataSize);
|
|
276
|
+
free(data);
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
static VALUE
|
|
282
|
+
rbAE_AEDesc_flatten(VALUE self)
|
|
283
|
+
{
|
|
284
|
+
OSErr err = noErr;
|
|
285
|
+
Size dataSize;
|
|
286
|
+
void *data;
|
|
287
|
+
VALUE result;
|
|
288
|
+
|
|
289
|
+
dataSize = AESizeOfFlattenedDesc(&(AEDESC_OF(self)));
|
|
290
|
+
data = malloc(dataSize);
|
|
291
|
+
err = AEFlattenDesc(&(AEDESC_OF(self)), data, dataSize, NULL);
|
|
292
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't flatten AEDesc.", err);
|
|
293
|
+
result = rb_str_new(data, dataSize);
|
|
294
|
+
free(data);
|
|
295
|
+
return result;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
/*******/
|
|
300
|
+
|
|
301
|
+
static VALUE
|
|
302
|
+
rbAE_AEDesc_isRecord(VALUE self)
|
|
303
|
+
{
|
|
304
|
+
return AECheckIsRecord(&(AEDESC_OF(self))) ? Qtrue : Qfalse;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
static VALUE
|
|
309
|
+
rbAE_AEDesc_coerce(VALUE self, VALUE type)
|
|
310
|
+
{
|
|
311
|
+
OSErr err = noErr;
|
|
312
|
+
AEDesc desc;
|
|
313
|
+
|
|
314
|
+
err = AECoerceDesc(&(AEDESC_OF(self)), rbStringToDescType(type), &desc);
|
|
315
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't coerce AEDesc.", err);
|
|
316
|
+
return rbAE_wrapAEDesc(&desc);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
static VALUE
|
|
321
|
+
rbAE_AEDesc_length(VALUE self)
|
|
322
|
+
{
|
|
323
|
+
OSErr err = noErr;
|
|
324
|
+
long length;
|
|
325
|
+
|
|
326
|
+
err = AECountItems(&(AEDESC_OF(self)), &length);
|
|
327
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get length of AEDesc.", err);
|
|
328
|
+
return INT2NUM(length);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
/*******/
|
|
333
|
+
|
|
334
|
+
static VALUE
|
|
335
|
+
rbAE_AEDesc_putItem(VALUE self, VALUE index, VALUE desc)
|
|
336
|
+
{
|
|
337
|
+
OSErr err = noErr;
|
|
338
|
+
|
|
339
|
+
if (rb_obj_is_instance_of(desc, cAEDesc) == Qfalse)
|
|
340
|
+
rb_raise(rb_eTypeError, "Can't put non-AEDesc item into AEDesc.");
|
|
341
|
+
err = AEPutDesc(&(AEDESC_OF(self)), NUM2LONG(index), &(AEDESC_OF(desc)));
|
|
342
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't put item into AEDesc.", err);
|
|
343
|
+
return Qnil;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
static VALUE
|
|
348
|
+
rbAE_AEDesc_putParam(VALUE self, VALUE key, VALUE desc)
|
|
349
|
+
{
|
|
350
|
+
OSErr err = noErr;
|
|
351
|
+
|
|
352
|
+
if (rb_obj_is_instance_of(desc, cAEDesc) == Qfalse)
|
|
353
|
+
rb_raise(rb_eTypeError, "Can't put non-AEDesc parameter into AEDesc.");
|
|
354
|
+
err = AEPutParamDesc(&(AEDESC_OF(self)), rbStringToDescType(key), &(AEDESC_OF(desc)));
|
|
355
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't put parameter into AEDesc.", err);
|
|
356
|
+
return Qnil;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
static VALUE
|
|
361
|
+
rbAE_AEDesc_putAttr(VALUE self, VALUE key, VALUE desc)
|
|
362
|
+
{
|
|
363
|
+
OSErr err = noErr;
|
|
364
|
+
|
|
365
|
+
if (rb_obj_is_instance_of(desc, cAEDesc) == Qfalse)
|
|
366
|
+
rb_raise(rb_eTypeError, "Can't put non-AEDesc attribute into AEDesc.");
|
|
367
|
+
err = AEPutAttributeDesc(&(AEDESC_OF(self)), rbStringToDescType(key), &(AEDESC_OF(desc)));
|
|
368
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't put attribute into AEDesc.", err);
|
|
369
|
+
return Qnil;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
/*******/
|
|
374
|
+
|
|
375
|
+
static VALUE
|
|
376
|
+
rbAE_AEDesc_getItem(VALUE self, VALUE index, VALUE type)
|
|
377
|
+
{
|
|
378
|
+
OSErr err = noErr;
|
|
379
|
+
AEKeyword key;
|
|
380
|
+
AEDesc desc;
|
|
381
|
+
|
|
382
|
+
err = AEGetNthDesc(&(AEDESC_OF(self)),
|
|
383
|
+
NUM2LONG(index),
|
|
384
|
+
rbStringToDescType(type),
|
|
385
|
+
&key,
|
|
386
|
+
&desc);
|
|
387
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get item from AEDesc.", err);
|
|
388
|
+
return rb_ary_new3(2,
|
|
389
|
+
rbDescTypeToString(key),
|
|
390
|
+
rbAE_wrapAEDesc(&desc));
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
static VALUE
|
|
395
|
+
rbAE_AEDesc_getParam(VALUE self, VALUE key, VALUE type)
|
|
396
|
+
{
|
|
397
|
+
OSErr err = noErr;
|
|
398
|
+
AEDesc desc;
|
|
399
|
+
|
|
400
|
+
err = AEGetParamDesc(&(AEDESC_OF(self)),
|
|
401
|
+
rbStringToDescType(key),
|
|
402
|
+
rbStringToDescType(type),
|
|
403
|
+
&desc);
|
|
404
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get parameter from AEDesc.", err);
|
|
405
|
+
return rbAE_wrapAEDesc(&desc);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
static VALUE
|
|
410
|
+
rbAE_AEDesc_getAttr(VALUE self, VALUE key, VALUE type)
|
|
411
|
+
{
|
|
412
|
+
OSErr err = noErr;
|
|
413
|
+
AEDesc desc;
|
|
414
|
+
|
|
415
|
+
err = AEGetAttributeDesc(&(AEDESC_OF(self)),
|
|
416
|
+
rbStringToDescType(key),
|
|
417
|
+
rbStringToDescType(type),
|
|
418
|
+
&desc);
|
|
419
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get attribute from AEDesc.", err);
|
|
420
|
+
return rbAE_wrapAEDesc(&desc);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
/*******/
|
|
425
|
+
|
|
426
|
+
static VALUE
|
|
427
|
+
rbAE_AEDesc_send(VALUE self, VALUE sendMode, VALUE timeout)
|
|
428
|
+
{
|
|
429
|
+
OSErr err = noErr;
|
|
430
|
+
AppleEvent reply;
|
|
431
|
+
|
|
432
|
+
err = AESendMessage(&(AEDESC_OF(self)),
|
|
433
|
+
&reply,
|
|
434
|
+
(AESendMode)NUM2LONG(sendMode),
|
|
435
|
+
NUM2LONG(timeout));
|
|
436
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't send Apple event.", err);
|
|
437
|
+
return rbAE_wrapAEDesc(&reply);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
static VALUE
|
|
441
|
+
rbAE_AEDesc_sendThreadSafe(VALUE self, VALUE sendMode, VALUE timeout)
|
|
442
|
+
{
|
|
443
|
+
OSErr err = noErr;
|
|
444
|
+
AppleEvent reply;
|
|
445
|
+
|
|
446
|
+
err = SendMessageThreadSafe(&(AEDESC_OF(self)),
|
|
447
|
+
&reply,
|
|
448
|
+
(AESendMode)NUM2LONG(sendMode),
|
|
449
|
+
NUM2LONG(timeout));
|
|
450
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't send Apple event.", err);
|
|
451
|
+
return rbAE_wrapAEDesc(&reply);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
/**********************************************************************/
|
|
456
|
+
// Find and launch applications
|
|
457
|
+
|
|
458
|
+
static VALUE
|
|
459
|
+
rbAE_findApplication(VALUE self, VALUE creator, VALUE bundleID, VALUE name)
|
|
460
|
+
{
|
|
461
|
+
OSStatus err = 0;
|
|
462
|
+
|
|
463
|
+
OSType inCreator;
|
|
464
|
+
CFStringRef inName;
|
|
465
|
+
CFStringRef inBundleID;
|
|
466
|
+
FSRef outAppRef;
|
|
467
|
+
UInt8 path[PATH_MAX];
|
|
468
|
+
|
|
469
|
+
inCreator = (creator == Qnil) ? kLSUnknownCreator : rbStringToDescType(creator);
|
|
470
|
+
if (bundleID != Qnil) {
|
|
471
|
+
inBundleID = CFStringCreateWithBytes(NULL,
|
|
472
|
+
(UInt8 *)(RSTRING_PTR(bundleID)),
|
|
473
|
+
(CFIndex)(RSTRING_LEN(bundleID)),
|
|
474
|
+
kCFStringEncodingUTF8,
|
|
475
|
+
false);
|
|
476
|
+
if (inBundleID == NULL) rb_raise(rb_eRuntimeError, "Invalid bundle ID string.");
|
|
477
|
+
} else {
|
|
478
|
+
inBundleID = NULL;
|
|
479
|
+
}
|
|
480
|
+
if (name != Qnil) {
|
|
481
|
+
inName = CFStringCreateWithBytes(NULL,
|
|
482
|
+
(UInt8 *)(RSTRING_PTR(name)),
|
|
483
|
+
(CFIndex)(RSTRING_LEN(name)),
|
|
484
|
+
kCFStringEncodingUTF8,
|
|
485
|
+
false);
|
|
486
|
+
if (inName == NULL) {
|
|
487
|
+
if (inBundleID != NULL) CFRelease(inBundleID);
|
|
488
|
+
rb_raise(rb_eRuntimeError, "Invalid name string.");
|
|
489
|
+
}
|
|
490
|
+
} else {
|
|
491
|
+
inName = NULL;
|
|
492
|
+
}
|
|
493
|
+
err = LSFindApplicationForInfo(inCreator,
|
|
494
|
+
inBundleID,
|
|
495
|
+
inName,
|
|
496
|
+
&outAppRef,
|
|
497
|
+
NULL);
|
|
498
|
+
if (inBundleID != NULL) CFRelease(inBundleID);
|
|
499
|
+
if (inName != NULL) CFRelease(inName);
|
|
500
|
+
if (err != 0) rbAE_raiseMacOSError("Couldn't find application.", err);
|
|
501
|
+
err = FSRefMakePath(&outAppRef, path, PATH_MAX);
|
|
502
|
+
if (err != 0) rbAE_raiseMacOSError("Couldn't get application path.", err);
|
|
503
|
+
return rb_str_new2((char *)path);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
static VALUE
|
|
508
|
+
rbAE_psnForApplicationPath(VALUE self, VALUE path)
|
|
509
|
+
{
|
|
510
|
+
OSStatus err = noErr;
|
|
511
|
+
ProcessSerialNumber psn = {0, kNoProcess};
|
|
512
|
+
FSRef appRef, foundRef;
|
|
513
|
+
|
|
514
|
+
err = FSPathMakeRef((UInt8 *)StringValuePtr(path), &appRef, NULL);
|
|
515
|
+
if (err != 0) rbAE_raiseMacOSError("Couldn't make FSRef for application.", err);
|
|
516
|
+
while (1) {
|
|
517
|
+
err = GetNextProcess(&psn);
|
|
518
|
+
if (err != 0) rbAE_raiseMacOSError("Can't get next process.", err); // -600 if no more processes left
|
|
519
|
+
err = GetProcessBundleLocation(&psn, &foundRef);
|
|
520
|
+
if (err != 0) continue;
|
|
521
|
+
if (FSCompareFSRefs(&appRef, &foundRef) == noErr)
|
|
522
|
+
return rb_ary_new3(2, INT2NUM(psn.highLongOfPSN), INT2NUM(psn.lowLongOfPSN));
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
static VALUE
|
|
528
|
+
rbAE_psnForPID(VALUE self, VALUE pid)
|
|
529
|
+
{
|
|
530
|
+
OSStatus err = noErr;
|
|
531
|
+
ProcessSerialNumber psn = {0, kNoProcess};
|
|
532
|
+
|
|
533
|
+
err = GetProcessForPID(NUM2INT(pid), &psn);
|
|
534
|
+
if (err != 0) rbAE_raiseMacOSError("Can't get next process.", err); // -600 if process not found
|
|
535
|
+
return rb_ary_new3(2, INT2NUM(psn.highLongOfPSN), INT2NUM(psn.lowLongOfPSN));
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
static VALUE
|
|
540
|
+
rbAE_launchApplication(VALUE self, VALUE path, VALUE firstEvent, VALUE flags)
|
|
541
|
+
{
|
|
542
|
+
FSRef appRef;
|
|
543
|
+
ProcessSerialNumber psn;
|
|
544
|
+
OSStatus err = noErr;
|
|
545
|
+
|
|
546
|
+
err = FSPathMakeRef((UInt8 *)StringValuePtr(path), &appRef, NULL);
|
|
547
|
+
if (err != noErr) rbAE_raiseMacOSError("Couldn't make FSRef for application.", err);
|
|
548
|
+
LSApplicationParameters appParams = {0,
|
|
549
|
+
(LSLaunchFlags)NUM2UINT(flags),
|
|
550
|
+
&appRef,
|
|
551
|
+
NULL, NULL, NULL,
|
|
552
|
+
&(AEDESC_OF(firstEvent))};
|
|
553
|
+
err = LSOpenApplication(&appParams, &psn);
|
|
554
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't launch application.", err);
|
|
555
|
+
return rb_ary_new3(2, INT2NUM(psn.highLongOfPSN), INT2NUM(psn.lowLongOfPSN));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**********************************************************************/
|
|
559
|
+
// HFS/POSIX path conversions
|
|
560
|
+
|
|
561
|
+
static VALUE
|
|
562
|
+
rbAE_convertPathToURL(VALUE self, VALUE path, VALUE pathStyle)
|
|
563
|
+
{
|
|
564
|
+
CFStringRef str;
|
|
565
|
+
CFURLRef url;
|
|
566
|
+
UInt8 buffer[PATH_MAX];
|
|
567
|
+
|
|
568
|
+
str = CFStringCreateWithBytes(NULL,
|
|
569
|
+
(UInt8 *)(RSTRING_PTR(path)),
|
|
570
|
+
(CFIndex)(RSTRING_LEN(path)),
|
|
571
|
+
kCFStringEncodingUTF8,
|
|
572
|
+
false);
|
|
573
|
+
if (str == NULL) rb_raise(rb_eRuntimeError, "Bad path string.");
|
|
574
|
+
url = CFURLCreateWithFileSystemPath(NULL,
|
|
575
|
+
str,
|
|
576
|
+
NUM2LONG(pathStyle),
|
|
577
|
+
false);
|
|
578
|
+
CFRelease(str);
|
|
579
|
+
if (url == NULL) rb_raise(rb_eRuntimeError, "Invalid path.");
|
|
580
|
+
buffer[CFURLGetBytes(url, buffer, PATH_MAX - 1)] = '\0';
|
|
581
|
+
CFRelease(url);
|
|
582
|
+
return rb_str_new2((char *)buffer);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
static VALUE
|
|
586
|
+
rbAE_convertURLToPath(VALUE self, VALUE urlStr, VALUE pathStyle)
|
|
587
|
+
{
|
|
588
|
+
Boolean err;
|
|
589
|
+
CFURLRef url;
|
|
590
|
+
CFStringRef str;
|
|
591
|
+
char buffer[PATH_MAX];
|
|
592
|
+
|
|
593
|
+
url = CFURLCreateWithBytes(NULL,
|
|
594
|
+
(UInt8 *)(RSTRING_PTR(urlStr)),
|
|
595
|
+
(CFIndex)(RSTRING_LEN(urlStr)),
|
|
596
|
+
kCFStringEncodingUTF8,
|
|
597
|
+
NULL);
|
|
598
|
+
if (url == NULL) rb_raise(rb_eRuntimeError, "Bad URL string.");
|
|
599
|
+
str = CFURLCopyFileSystemPath(url, NUM2LONG(pathStyle));
|
|
600
|
+
CFRelease(url);
|
|
601
|
+
if (str == NULL) rb_raise(rb_eRuntimeError, "Can't get path.");
|
|
602
|
+
err = CFStringGetCString(str,
|
|
603
|
+
buffer,
|
|
604
|
+
PATH_MAX,
|
|
605
|
+
kCFStringEncodingUTF8);
|
|
606
|
+
CFRelease(str);
|
|
607
|
+
if (!err) rb_raise(rb_eRuntimeError, "Can't get path.");
|
|
608
|
+
return rb_str_new2(buffer);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
/**********************************************************************/
|
|
613
|
+
// Date conversion
|
|
614
|
+
|
|
615
|
+
static VALUE
|
|
616
|
+
rbAE_convertLongDateTimeToString(VALUE self, VALUE ldt)
|
|
617
|
+
{
|
|
618
|
+
Boolean bErr;
|
|
619
|
+
OSStatus err = 0;
|
|
620
|
+
CFAbsoluteTime cfTime;
|
|
621
|
+
CFDateFormatterRef formatter;
|
|
622
|
+
CFStringRef str;
|
|
623
|
+
char buffer[20]; // size of format string + nul
|
|
624
|
+
|
|
625
|
+
err = UCConvertLongDateTimeToCFAbsoluteTime(NUM2LL(ldt), &cfTime);
|
|
626
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't convert LongDateTime to seconds.", err);
|
|
627
|
+
formatter = CFDateFormatterCreate(NULL, NULL, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
|
|
628
|
+
if (!formatter) rbAE_raiseMacOSError("Can't create date formatter.", err);
|
|
629
|
+
CFDateFormatterSetFormat(formatter, CFSTR("yyyy-MM-dd HH:mm:ss"));
|
|
630
|
+
str = CFDateFormatterCreateStringWithAbsoluteTime(NULL, formatter, cfTime);
|
|
631
|
+
CFRelease(formatter);
|
|
632
|
+
if (!str) rbAE_raiseMacOSError("Can't create date string.", err);
|
|
633
|
+
bErr = CFStringGetCString(str,
|
|
634
|
+
buffer,
|
|
635
|
+
sizeof(buffer),
|
|
636
|
+
kCFStringEncodingUTF8);
|
|
637
|
+
CFRelease(str);
|
|
638
|
+
if (!bErr) rb_raise(rb_eRuntimeError, "Can't convert date string.");
|
|
639
|
+
return rb_str_new2(buffer);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
static VALUE
|
|
644
|
+
rbAE_convertStringToLongDateTime(VALUE self, VALUE datetime)
|
|
645
|
+
{
|
|
646
|
+
CFStringRef str;
|
|
647
|
+
CFAbsoluteTime cfTime;
|
|
648
|
+
CFDateFormatterRef formatter;
|
|
649
|
+
OSStatus err = 0;
|
|
650
|
+
Boolean bErr;
|
|
651
|
+
SInt64 ldt;
|
|
652
|
+
|
|
653
|
+
str = CFStringCreateWithBytes(NULL,
|
|
654
|
+
(UInt8 *)(RSTRING_PTR(datetime)),
|
|
655
|
+
(CFIndex)(RSTRING_LEN(datetime)),
|
|
656
|
+
kCFStringEncodingUTF8,
|
|
657
|
+
false);
|
|
658
|
+
if (str == NULL || CFStringGetLength(str) != 19) rb_raise(rb_eRuntimeError, "Bad datetime string.");
|
|
659
|
+
formatter = CFDateFormatterCreate(NULL, NULL, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
|
|
660
|
+
if (!formatter) rbAE_raiseMacOSError("Can't create date formatter.", err);
|
|
661
|
+
CFDateFormatterSetFormat(formatter, CFSTR("yyyy-MM-dd HH:mm:ss"));
|
|
662
|
+
bErr = CFDateFormatterGetAbsoluteTimeFromString(formatter, str, NULL, &cfTime);
|
|
663
|
+
CFRelease(formatter);
|
|
664
|
+
CFRelease(str);
|
|
665
|
+
if (!bErr) rb_raise(rb_eRuntimeError, "Can't convert date string.");
|
|
666
|
+
err = UCConvertCFAbsoluteTimeToLongDateTime(cfTime, &ldt);
|
|
667
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't convert seconds to LongDateTime.", err);
|
|
668
|
+
return LL2NUM(ldt);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
static VALUE
|
|
673
|
+
rbAE_convertLongDateTimeToUnixSeconds(VALUE self, VALUE ldt)
|
|
674
|
+
{
|
|
675
|
+
OSStatus err = 0;
|
|
676
|
+
CFAbsoluteTime cfTime;
|
|
677
|
+
|
|
678
|
+
err = UCConvertLongDateTimeToCFAbsoluteTime(NUM2LL(ldt), &cfTime);
|
|
679
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't convert LongDateTime to seconds.", err);
|
|
680
|
+
return rb_float_new(cfTime + kCFAbsoluteTimeIntervalSince1970);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
static VALUE
|
|
685
|
+
rbAE_convertUnixSecondsToLongDateTime(VALUE self, VALUE secs)
|
|
686
|
+
{
|
|
687
|
+
OSStatus err = 0;
|
|
688
|
+
SInt64 ldt;
|
|
689
|
+
|
|
690
|
+
err = UCConvertCFAbsoluteTimeToLongDateTime(NUM2DBL(secs) - kCFAbsoluteTimeIntervalSince1970, &ldt);
|
|
691
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't convert seconds to LongDateTime.", err);
|
|
692
|
+
return LL2NUM(ldt);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
/**********************************************************************/
|
|
697
|
+
// Get aete
|
|
698
|
+
|
|
699
|
+
static VALUE
|
|
700
|
+
rbAE_OSACopyScriptingDefinition(VALUE self, VALUE path)
|
|
701
|
+
{
|
|
702
|
+
FSRef fsRef;
|
|
703
|
+
CFDataRef sdef;
|
|
704
|
+
CFIndex dataSize;
|
|
705
|
+
char *data;
|
|
706
|
+
VALUE res;
|
|
707
|
+
OSErr err = noErr;
|
|
708
|
+
|
|
709
|
+
err = FSPathMakeRef((UInt8 *)StringValuePtr(path), &fsRef, NULL);
|
|
710
|
+
if (err != 0) rbAE_raiseMacOSError("Couldn't make FSRef for path.", err);
|
|
711
|
+
err = OSACopyScriptingDefinition(&fsRef, 0, &sdef);
|
|
712
|
+
if (err) rbAE_raiseMacOSError("Couldn't get sdef.", err);
|
|
713
|
+
dataSize = CFDataGetLength(sdef);
|
|
714
|
+
data = (char *)CFDataGetBytePtr(sdef);
|
|
715
|
+
if (data != NULL) {
|
|
716
|
+
res = rb_str_new(data, dataSize);
|
|
717
|
+
} else {
|
|
718
|
+
data = malloc(dataSize);
|
|
719
|
+
CFDataGetBytes(sdef, CFRangeMake(0, dataSize), (UInt8 *)data);
|
|
720
|
+
res = rb_str_new(data, dataSize);
|
|
721
|
+
free(data);
|
|
722
|
+
}
|
|
723
|
+
CFRelease(sdef);
|
|
724
|
+
return res;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
/**********************************************************************/
|
|
729
|
+
// Install event handlers
|
|
730
|
+
|
|
731
|
+
// Based on Python's CarbonX.AE extension
|
|
732
|
+
|
|
733
|
+
static pascal OSErr
|
|
734
|
+
rbAE_GenericEventHandler(const AppleEvent *request, AppleEvent *reply, SRefCon refcon)
|
|
735
|
+
{
|
|
736
|
+
VALUE err;
|
|
737
|
+
|
|
738
|
+
err = rb_funcall((VALUE)refcon,
|
|
739
|
+
rb_intern("handle_event"),
|
|
740
|
+
2,
|
|
741
|
+
rbAE_wrapBorrowedAEDesc(request),
|
|
742
|
+
rbAE_wrapBorrowedAEDesc(reply));
|
|
743
|
+
return NUM2INT(err);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/*******/
|
|
747
|
+
|
|
748
|
+
static VALUE
|
|
749
|
+
rbAE_AEInstallEventHandler(VALUE self, VALUE eventClass, VALUE eventID, SRefCon handler)
|
|
750
|
+
{
|
|
751
|
+
/*
|
|
752
|
+
* eventClass and eventID must be four-character code strings
|
|
753
|
+
*
|
|
754
|
+
* handler must be a Ruby object containing a method named 'handle_event' that takes two
|
|
755
|
+
* AppleEvent descriptors (request and reply) as arguments, and returns an integer.
|
|
756
|
+
* Note that this object is responsible for trapping any unhandled exceptions and returning
|
|
757
|
+
* an OS error number as appropriate (or 0 if no error), otherwise the program will exit.
|
|
758
|
+
*/
|
|
759
|
+
OSErr err = noErr;
|
|
760
|
+
|
|
761
|
+
err = AEInstallEventHandler(rbStringToDescType(eventClass),
|
|
762
|
+
rbStringToDescType(eventID),
|
|
763
|
+
upp_GenericEventHandler, handler,
|
|
764
|
+
0);
|
|
765
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't install event handler.", err);
|
|
766
|
+
return Qnil;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
static VALUE
|
|
771
|
+
rbAE_AERemoveEventHandler(VALUE self, VALUE eventClass, VALUE eventID)
|
|
772
|
+
{
|
|
773
|
+
OSErr err = noErr;
|
|
774
|
+
|
|
775
|
+
err = AERemoveEventHandler(rbStringToDescType(eventClass),
|
|
776
|
+
rbStringToDescType(eventID),
|
|
777
|
+
upp_GenericEventHandler,
|
|
778
|
+
0);
|
|
779
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't remove event handler.", err);
|
|
780
|
+
return Qnil;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
static VALUE
|
|
785
|
+
rbAE_AEGetEventHandler(VALUE self, VALUE eventClass, VALUE eventID)
|
|
786
|
+
{
|
|
787
|
+
OSErr err = noErr;
|
|
788
|
+
AEEventHandlerUPP handlerUPP;
|
|
789
|
+
SRefCon handler;
|
|
790
|
+
|
|
791
|
+
err = AEGetEventHandler(rbStringToDescType(eventClass),
|
|
792
|
+
rbStringToDescType(eventID),
|
|
793
|
+
&handlerUPP, &handler,
|
|
794
|
+
0);
|
|
795
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get event handler.", err);
|
|
796
|
+
return (VALUE)handler;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
/**********************************************************************/
|
|
801
|
+
// Install coercion handlers
|
|
802
|
+
|
|
803
|
+
static pascal OSErr
|
|
804
|
+
rbAE_GenericCoercionHandler(const AEDesc *fromDesc, DescType toType, SRefCon refcon, AEDesc *toDesc)
|
|
805
|
+
{
|
|
806
|
+
// handle_coercion method should return an AE::AEDesc, or nil if an error occurred
|
|
807
|
+
OSErr err = noErr;
|
|
808
|
+
VALUE res;
|
|
809
|
+
|
|
810
|
+
res = rb_funcall((VALUE)refcon,
|
|
811
|
+
rb_intern("handle_coercion"),
|
|
812
|
+
2,
|
|
813
|
+
rbAE_wrapBorrowedAEDesc(fromDesc),
|
|
814
|
+
rbDescTypeToString(toType));
|
|
815
|
+
if (rb_obj_is_instance_of(res, cAEDesc) != Qtrue) return errAECoercionFail;
|
|
816
|
+
err = AEDuplicateDesc(&AEDESC_OF(res), toDesc);
|
|
817
|
+
return err;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
/*******/
|
|
822
|
+
|
|
823
|
+
static VALUE
|
|
824
|
+
rbAE_AEInstallCoercionHandler(VALUE self, VALUE fromType, VALUE toType, SRefCon handler)
|
|
825
|
+
{
|
|
826
|
+
/*
|
|
827
|
+
* fromType and toType must be four-character code strings
|
|
828
|
+
*
|
|
829
|
+
* handler must be a Ruby object containing a method named 'handle_coercion' that takes an
|
|
830
|
+
* AEDesc and a four-character code (original value, desired type) as arguments, and returns an
|
|
831
|
+
* AEDesc of the desired type.Note that this object is responsible for trapping any unhandled
|
|
832
|
+
* exceptions and returning nil (or any other non-AEDesc value) as appropriate, otherwise the
|
|
833
|
+
* program will exit.
|
|
834
|
+
*/
|
|
835
|
+
OSErr err = noErr;
|
|
836
|
+
|
|
837
|
+
err = AEInstallCoercionHandler(rbStringToDescType(fromType),
|
|
838
|
+
rbStringToDescType(toType),
|
|
839
|
+
upp_GenericCoercionHandler, handler,
|
|
840
|
+
1, 0);
|
|
841
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't install coercion handler.", err);
|
|
842
|
+
return Qnil;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
static VALUE
|
|
847
|
+
rbAE_AERemoveCoercionHandler(VALUE self, VALUE fromType, VALUE toType)
|
|
848
|
+
{
|
|
849
|
+
OSErr err = noErr;
|
|
850
|
+
|
|
851
|
+
err = AERemoveCoercionHandler(rbStringToDescType(fromType),
|
|
852
|
+
rbStringToDescType(toType),
|
|
853
|
+
upp_GenericCoercionHandler,
|
|
854
|
+
0);
|
|
855
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't remove coercion handler.", err);
|
|
856
|
+
return Qnil;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
static VALUE
|
|
861
|
+
rbAE_AEGetCoercionHandler(VALUE self, VALUE fromType, VALUE toType)
|
|
862
|
+
{
|
|
863
|
+
OSErr err = noErr;
|
|
864
|
+
AECoercionHandlerUPP handlerUPP;
|
|
865
|
+
SRefCon handler;
|
|
866
|
+
Boolean fromTypeIsDesc;
|
|
867
|
+
|
|
868
|
+
err = AEGetCoercionHandler(rbStringToDescType(fromType),
|
|
869
|
+
rbStringToDescType(toType),
|
|
870
|
+
&handlerUPP, &handler,
|
|
871
|
+
&fromTypeIsDesc,
|
|
872
|
+
0);
|
|
873
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't get coercion handler.", err);
|
|
874
|
+
return rb_ary_new3(2, handler, fromTypeIsDesc ? Qtrue : Qfalse);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
/**********************************************************************/
|
|
881
|
+
// Process management
|
|
882
|
+
static VALUE
|
|
883
|
+
rbAE_transformProcessToForegroundApplication(VALUE self)
|
|
884
|
+
{
|
|
885
|
+
OSStatus err = 0;
|
|
886
|
+
ProcessSerialNumber psn = {0, kCurrentProcess};
|
|
887
|
+
|
|
888
|
+
err = TransformProcessType(& psn, kProcessTransformToForegroundApplication);
|
|
889
|
+
if( err != 0) rbAE_raiseMacOSError("Can't transform process.", err);
|
|
890
|
+
return Qnil;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
/**********************************************************************/
|
|
895
|
+
// Initialisation
|
|
896
|
+
|
|
897
|
+
void
|
|
898
|
+
Init_ae (void)
|
|
899
|
+
{
|
|
900
|
+
|
|
901
|
+
mAE = rb_define_module("AE");
|
|
902
|
+
|
|
903
|
+
// AE::AEDesc
|
|
904
|
+
|
|
905
|
+
cAEDesc = rb_define_class_under(mAE, "AEDesc", rb_cObject);
|
|
906
|
+
|
|
907
|
+
rb_define_singleton_method(cAEDesc, "new", rbAE_AEDesc_new, 2);
|
|
908
|
+
rb_define_singleton_method(cAEDesc, "new_list", rbAE_AEDesc_newList, 1);
|
|
909
|
+
rb_define_singleton_method(cAEDesc, "new_apple_event", rbAE_AEDesc_newAppleEvent, 5);
|
|
910
|
+
rb_define_singleton_method(cAEDesc, "unflatten", rbAE_AEDesc_newUnflatten, 1);
|
|
911
|
+
|
|
912
|
+
rb_define_method(cAEDesc, "to_s", rbAE_AEDesc_inspect, 0);
|
|
913
|
+
rb_define_method(cAEDesc, "inspect", rbAE_AEDesc_inspect, 0);
|
|
914
|
+
rb_define_method(cAEDesc, "type", rbAE_AEDesc_type, 0);
|
|
915
|
+
rb_define_method(cAEDesc, "data", rbAE_AEDesc_data, 0);
|
|
916
|
+
rb_define_method(cAEDesc, "flatten", rbAE_AEDesc_flatten, 0);
|
|
917
|
+
rb_define_method(cAEDesc, "is_record?", rbAE_AEDesc_isRecord, 0);
|
|
918
|
+
rb_define_method(cAEDesc, "coerce", rbAE_AEDesc_coerce, 1);
|
|
919
|
+
rb_define_method(cAEDesc, "length", rbAE_AEDesc_length, 0);
|
|
920
|
+
rb_define_method(cAEDesc, "put_item", rbAE_AEDesc_putItem, 2);
|
|
921
|
+
rb_define_method(cAEDesc, "put_param", rbAE_AEDesc_putParam, 2);
|
|
922
|
+
rb_define_method(cAEDesc, "put_attr", rbAE_AEDesc_putAttr, 2);
|
|
923
|
+
rb_define_method(cAEDesc, "get_item", rbAE_AEDesc_getItem, 2);
|
|
924
|
+
rb_define_method(cAEDesc, "get_param", rbAE_AEDesc_getParam, 2);
|
|
925
|
+
rb_define_method(cAEDesc, "get_attr", rbAE_AEDesc_getAttr, 2);
|
|
926
|
+
rb_define_method(cAEDesc, "send", rbAE_AEDesc_send, 2);
|
|
927
|
+
rb_define_method(cAEDesc, "send_thread_safe", rbAE_AEDesc_sendThreadSafe, 2);
|
|
928
|
+
|
|
929
|
+
// AE::MacOSError
|
|
930
|
+
|
|
931
|
+
cMacOSError = rb_define_class_under(mAE, "MacOSError", rb_eStandardError);
|
|
932
|
+
|
|
933
|
+
rb_define_attr(cMacOSError, "number", Qtrue, Qfalse);
|
|
934
|
+
rb_define_attr(cMacOSError, "description", Qtrue, Qfalse);
|
|
935
|
+
|
|
936
|
+
rb_define_alias(cMacOSError, "to_i", "number");
|
|
937
|
+
|
|
938
|
+
rb_define_method(cMacOSError, "to_s", rbAE_MacOSError_inspect, 0);
|
|
939
|
+
rb_define_method(cMacOSError, "inspect", rbAE_MacOSError_inspect, 0);
|
|
940
|
+
|
|
941
|
+
// Support functions
|
|
942
|
+
|
|
943
|
+
rb_define_module_function(mAE, "find_application", rbAE_findApplication, 3);
|
|
944
|
+
rb_define_module_function(mAE, "psn_for_application_path", rbAE_psnForApplicationPath, 1);
|
|
945
|
+
rb_define_module_function(mAE, "psn_for_process_id", rbAE_psnForPID, 1);
|
|
946
|
+
rb_define_module_function(mAE, "launch_application", rbAE_launchApplication, 3);
|
|
947
|
+
|
|
948
|
+
rb_define_module_function(mAE, "convert_path_to_url",
|
|
949
|
+
rbAE_convertPathToURL, 2);
|
|
950
|
+
rb_define_module_function(mAE, "convert_url_to_path",
|
|
951
|
+
rbAE_convertURLToPath, 2);
|
|
952
|
+
|
|
953
|
+
rb_define_module_function(mAE, "convert_long_date_time_to_string",
|
|
954
|
+
rbAE_convertLongDateTimeToString, 1);
|
|
955
|
+
rb_define_module_function(mAE, "convert_string_to_long_date_time",
|
|
956
|
+
rbAE_convertStringToLongDateTime, 1);
|
|
957
|
+
rb_define_module_function(mAE, "convert_long_date_time_to_unix_seconds",
|
|
958
|
+
rbAE_convertLongDateTimeToUnixSeconds, 1);
|
|
959
|
+
rb_define_module_function(mAE, "convert_unix_seconds_to_long_date_time",
|
|
960
|
+
rbAE_convertUnixSecondsToLongDateTime, 1);
|
|
961
|
+
|
|
962
|
+
rb_define_module_function(mAE, "copy_scripting_definition", rbAE_OSACopyScriptingDefinition, 1);
|
|
963
|
+
|
|
964
|
+
// Event handling
|
|
965
|
+
|
|
966
|
+
upp_GenericEventHandler = NewAEEventHandlerUPP(rbAE_GenericEventHandler);
|
|
967
|
+
upp_GenericCoercionHandler = NewAECoerceDescUPP(rbAE_GenericCoercionHandler);
|
|
968
|
+
|
|
969
|
+
rb_define_module_function(mAE, "install_event_handler", rbAE_AEInstallEventHandler, 3);
|
|
970
|
+
rb_define_module_function(mAE, "remove_event_handler", rbAE_AERemoveEventHandler, 2);
|
|
971
|
+
rb_define_module_function(mAE, "get_event_handler", rbAE_AEGetEventHandler, 2);
|
|
972
|
+
|
|
973
|
+
rb_define_module_function(mAE, "install_coercion_handler", rbAE_AEInstallCoercionHandler, 3);
|
|
974
|
+
rb_define_module_function(mAE, "remove_coercion_handler", rbAE_AERemoveCoercionHandler, 2);
|
|
975
|
+
rb_define_module_function(mAE, "get_coercion_handler", rbAE_AEGetCoercionHandler, 2);
|
|
976
|
+
|
|
977
|
+
rb_define_module_function(mAE, "transform_process_to_foreground_application",
|
|
978
|
+
rbAE_transformProcessToForegroundApplication, 0);
|
|
979
|
+
}
|