b2c1d4640e294055c0a9f778811f8e5a700fa1b9
[ITFoundation.git] / ITAppleEventCenter.m
1 #import "ITAppleEventCenter.h"
2
3 Boolean MyAEIdleCallback (
4                                          EventRecord * theEvent,
5                                          SInt32 * sleepTime,
6                                          RgnHandle * mouseRgn
7                                          );
8
9 Boolean MyAEIdleCallback (
10                                          EventRecord * theEvent,
11                                          SInt32 * sleepTime,
12                                          RgnHandle * mouseRgn
13                                          )
14 {
15     return FALSE;
16 }
17
18 @implementation ITAppleEventCenter
19
20 static ITAppleEventCenter *_sharedAECenter = nil;
21
22 + (id)sharedCenter
23 {
24     if( _sharedAECenter ) {
25         return _sharedAECenter;
26     } else {
27         return _sharedAECenter = [[ITAppleEventCenter alloc] init];
28     }
29 }
30
31 - (id)init
32 {
33     if (self = [super init])
34            {
35            idleUPP = NewAEIdleUPP(MyAEIdleCallback);
36            }
37     return self;
38 }
39
40 - (void)dealloc
41 {
42     DisposeAEIdleUPP(idleUPP);
43 }
44
45 - (NSString*)sendAEWithRequestedKey:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
46 {
47     //Add error checking...
48     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
49     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
50
51     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [key UTF8String]] UTF8String];
52     NSString  *_finalString = nil;
53
54     AppleEvent sendEvent, replyEvent;
55
56     DescType resultType;
57     Size resultSize, charResultSize;
58
59     AEBuildError buildError;
60     OSStatus err;
61     OSErr err2, err3;
62     /*
63         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
64             NSLog(@"Error getting PID of application! Exiting.");
65             return nil;
66         }
67         */
68     //NSLog(@"_sendString: %s", sendString);
69
70     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
71
72     //[self printCarbonDesc:&sendEvent];
73
74     if (err) {
75         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
76     }
77
78     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
79
80     //[self printCarbonDesc:&replyEvent];
81
82     if (err) {
83         NSLog(@"Send Error: %i",err);
84     } else {
85         unichar *result = 0;
86
87         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
88         result = malloc(resultSize);
89
90         if (err2) {
91             NSLog(@"Error After AESizeOfParam: %i", err2);
92         } else {
93             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
94
95             if (err3) {
96                 NSLog(@"Error After AEGetParamPtr: %i", err3);
97             } else {
98                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
99             }
100         }
101         free(result);
102     }
103
104     AEDisposeDesc(&sendEvent);
105     AEDisposeDesc(&replyEvent);
106
107     return _finalString;
108 }
109
110 - (NSString*)sendAEWithSendString:(NSString*)nssendString eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
111 {
112     //Add error checking...
113     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
114     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
115
116     const char *sendString = [nssendString UTF8String];
117     NSString  *_finalString = nil;
118
119     AppleEvent sendEvent, replyEvent;
120
121     DescType resultType;
122     Size resultSize, charResultSize;
123
124     AEBuildError buildError;
125     OSStatus err;
126     OSErr err2, err3;
127     /*
128         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
129             NSLog(@"Error getting PID of application! Exiting.");
130             return nil;
131         }
132         */
133     //NSLog(@"_sendString: %s", sendString);
134
135     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
136
137     //[self printCarbonDesc:&sendEvent];
138
139     if (err) {
140         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
141     }
142
143     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
144
145     //[self printCarbonDesc:&replyEvent];
146
147     if (err) {
148         NSLog(@"Send Error: %i",err);
149     } else {
150         unichar *result = 0;
151
152         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
153         result = malloc(resultSize);
154
155         if (err2) {
156             NSLog(@"Error After AESizeOfParam: %i", err2);
157         } else {
158             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
159
160             if (err3) {
161                 NSLog(@"Error After AEGetParamPtr: %i", err3);
162             } else {
163                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
164             }
165         }
166         free(result);
167     }
168
169     AEDisposeDesc(&sendEvent);
170     AEDisposeDesc(&replyEvent);
171
172     return _finalString;
173 }
174
175 - (long)sendAEWithRequestedKeyForNumber:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
176 {
177     //Add error checking...
178     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
179     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
180
181     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [key UTF8String]] UTF8String];
182     long result = 0;
183
184     AppleEvent sendEvent, replyEvent;
185
186     DescType resultType;
187     Size resultSize, charResultSize;
188
189     AEBuildError buildError;
190     OSStatus err;
191     OSErr err2, err3;
192     /*
193         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
194             NSLog(@"Error getting PID of application! Exiting.");
195             return nil;
196         }
197         */
198     //NSLog(@"_sendString: %s", sendString);
199
200     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
201
202     //[self printCarbonDesc:&sendEvent];
203
204     if (err) {
205         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
206     }
207
208     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
209
210     [self printCarbonDesc:&replyEvent];
211
212     if (err) {
213         NSLog(@"Send Error: %i",err);
214     } else {
215         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
216
217         if (err2) {
218             NSLog(@"Error After AESizeOfParam: %i", err2);
219         } else {
220             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
221
222             if (err3) {
223                 NSLog(@"Error After AEGetParamPtr: %i", err3);
224             }
225         }
226     }
227
228     AEDisposeDesc(&sendEvent);
229     AEDisposeDesc(&replyEvent);
230
231     return result;
232 }
233
234 - (NSString*)sendTwoTierAEWithRequestedKey:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
235 {
236     //Add error checking...
237     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
238     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
239
240     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() } }", [key UTF8String], [object UTF8String]] UTF8String];
241     NSString  *_finalString = nil;
242
243     AppleEvent sendEvent, replyEvent;
244
245     DescType resultType;
246     Size resultSize, charResultSize;
247
248     AEBuildError buildError;
249     OSStatus err;
250     OSErr err2, err3;
251     /*
252         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
253             NSLog(@"Error getting PID of application! Exiting.");
254             return nil;
255         }*/
256
257     //NSLog(@"_sendString: %s", sendString);
258
259     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
260
261     //[self printCarbonDesc:&sendEvent];
262
263     if (err) {
264         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
265     }
266
267     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
268
269     //[self printCarbonDesc:&replyEvent];
270
271     if (err) {
272         NSLog(@"Send Error: %i",err);
273     } else {
274         unichar *result = 0;
275
276         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
277         result = malloc(resultSize);
278
279         if (err2) {
280             NSLog(@"Error After AESizeOfParam: %i", err2);
281         } else {
282             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
283
284             if (err3) {
285                 NSLog(@"Error After AEGetParamPtr: %i", err3);
286             } else {
287                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
288             }
289         }
290         free(result);
291     }
292
293     AEDisposeDesc(&sendEvent);
294     AEDisposeDesc(&replyEvent);
295
296     return _finalString;
297 }
298
299 - (long)sendTwoTierAEWithRequestedKeyForNumber:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
300 {
301     //Add error checking...
302     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
303     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
304
305     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() } }", [key UTF8String], [object UTF8String]] UTF8String];
306     long result = 0;
307
308     AppleEvent sendEvent, replyEvent;
309
310     DescType resultType;
311     Size resultSize, charResultSize;
312
313     AEBuildError buildError;
314     OSStatus err;
315     OSErr err2, err3;
316     /*
317         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
318             NSLog(@"Error getting PID of application! Exiting.");
319             return nil;
320         }
321         */
322     // NSLog(@"_sendString: %s", sendString);
323
324     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
325
326     //[self printCarbonDesc:&sendEvent];
327
328     if (err) {
329         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
330     }
331
332     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
333
334     [self printCarbonDesc:&replyEvent];
335
336     if (err) {
337         NSLog(@"Send Error: %i",err);
338     } else {
339         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
340
341         if (err2) {
342             NSLog(@"Error After AESizeOfParam: %i", err2);
343         } else {
344             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
345
346             if (err3) {
347                 NSLog(@"Error After AEGetParamPtr: %i", err3);
348             }
349         }
350     }
351
352     AEDisposeDesc(&sendEvent);
353     AEDisposeDesc(&replyEvent);
354
355     return result;
356 }
357
358 - (NSString *)sendAEWithRequestedArray:(NSArray *)array eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
359 {
360     NSString *buildString = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [[array objectAtIndex:0] UTF8String]];
361     const char *sendString;
362     int i;
363     NSString  *_finalString = nil;
364
365     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
366     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
367
368     AppleEvent sendEvent, replyEvent;
369
370     DescType resultType;
371     Size resultSize, charResultSize;
372
373     AEBuildError buildError;
374     OSStatus err;
375     OSErr err2, err3;
376
377     for (i = 1; i < [array count]; i++) {
378         NSString *from = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:obj %@ }",
379                   [[array objectAtIndex:i] UTF8String], buildString];
380         buildString = from;
381     }
382     buildString = [@"'----':obj " stringByAppendingString:buildString];
383     sendString = [buildString UTF8String];
384     /*
385         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
386             NSLog(@"Error getting PID of application! Exiting.");
387             return nil;
388         }
389         */
390     //NSLog(@"_sendString: %s", sendString);
391
392     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
393
394     //[self printCarbonDesc:&sendEvent];
395
396     if (err) {
397         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
398     }
399
400     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
401
402     //[self printCarbonDesc:&replyEvent];
403
404     if (err) {
405         NSLog(@"Send Error: %i",err);
406     } else {
407         unichar *result = 0;
408
409         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
410         result=malloc(resultSize);
411
412         if (err2) {
413             NSLog(@"Error After AESizeOfParam: %i", err2);
414         } else {
415             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
416             if (err3) {
417                 NSLog(@"Error After AEGetParamPtr: %i", err3);
418             } else {
419                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
420             }
421         }
422         free(result);
423     }
424     return _finalString;
425 }
426
427 - (void)sendAEWithEventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
428 {
429     //Add error checking...
430     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
431     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
432     AEDesc dest;
433     AppleEvent event, reply;
434
435     //AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, kAnyTransactionID, &event, nil, "");
436     AECreateDesc(typeProcessSerialNumber,(ProcessSerialNumber*)&psn,sizeof(ProcessSerialNumber),&dest);
437     AECreateAppleEvent(eClass,eID,&dest,kAutoGenerateReturnID,kAnyTransactionID,&event);
438     AESend(&event, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, idleUPP, nil);
439
440     AEDisposeDesc(&dest);
441     AEDisposeDesc(&event);
442     AEDisposeDesc(&reply);
443 }
444
445 - (void)printCarbonDesc:(AEDesc*)desc {
446     /*Handle xx;
447     AEPrintDescToHandle(desc,&xx);
448     NSLog(@"Handle: %s", *xx);
449     DisposeHandle(xx);*/
450 }
451
452
453 - (AEArrayDataPointer)sendAEWithRequestedKeyForArray:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
454 {
455     //Add error checking...
456     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
457     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
458
459     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'indx', want:'%s', seld:abso($616C6C20$), from:'null'() }", [key UTF8String]] UTF8String];
460     AEArrayDataPointer result = nil;
461
462     AppleEvent sendEvent, replyEvent;
463
464     DescType resultType;
465     Size resultSize, charResultSize;
466
467     AEBuildError buildError;
468     OSStatus err;
469     OSErr err2, err3;
470
471     //NSLog(@"_sendString: %s", sendString);
472
473     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
474
475     //[self printCarbonDesc:&sendEvent];
476
477     if (err) {
478         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
479     }
480
481     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
482
483     //[self printCarbonDesc:&replyEvent];
484
485     if (err) {
486         NSLog(@"Send Error: %i",err);
487     } else {
488            SInt32 count, resultCount;
489
490            AECountItems(&replyEvent,&count);
491            result=malloc(sizeof(AEDesc)*count);
492            AEGetArray(&replyEvent, kAEDescArray, result, sizeof(AEDesc)*count, NULL, NULL, &resultCount);
493
494         free(result);
495     }
496
497     AEDisposeDesc(&sendEvent);
498     AEDisposeDesc(&replyEvent);
499
500     return result;
501 }
502
503 - (long)sendAEWithSendStringForNumber:(NSString*)string eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
504 {
505     //Add error checking...
506     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
507     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
508
509     const char *sendString = [string UTF8String];
510     long result = 0;
511
512     AppleEvent sendEvent, replyEvent;
513
514     DescType resultType;
515     Size resultSize, charResultSize;
516     
517     AEBuildError buildError;
518     OSStatus err;
519     OSErr err2, err3;
520     /*
521         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
522             NSLog(@"Error getting PID of application! Exiting.");
523             return nil;
524         }
525         */
526     //NSLog(@"_sendString: %s", sendString);
527
528     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
529
530     //[self printCarbonDesc:&sendEvent];
531
532     if (err) {
533         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
534     }
535
536     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
537
538     [self printCarbonDesc:&replyEvent];
539
540     if (err) {
541         NSLog(@"Send Error: %i",err);
542     } else {
543         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
544
545         if (err2) {
546             NSLog(@"Error After AESizeOfParam: %i", err2);
547         } else {
548             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
549
550             if (err3) {
551                 NSLog(@"Error After AEGetParamPtr: %i", err3);
552             }
553         }
554     }
555
556     AEDisposeDesc(&sendEvent);
557     AEDisposeDesc(&replyEvent);
558
559     return result;
560 }
561
562 @end