Alex's memory leak fixes and timeout changes.
[ITFoundation.git] / ITAppleEventCenter.m
1 #import "ITAppleEventCenter.h"
2 #import "ITDebug.h"
3
4 static Boolean MyAEIdleCallback (
5                                          EventRecord * theEvent,
6                                          SInt32 * sleepTime,
7                                          RgnHandle * mouseRgn
8                                          )
9 {
10     return FALSE;
11 }
12
13 @implementation ITAppleEventCenter
14
15 static ITAppleEventCenter *_sharedAECenter = nil;
16
17 + (id)sharedCenter
18 {
19     if( _sharedAECenter ) {
20         return _sharedAECenter;
21     } else {
22         return _sharedAECenter = [[ITAppleEventCenter alloc] init];
23     }
24 }
25
26 - (id)init
27 {
28     if ( ( self = [super init] ) ) {
29         idleUPP = NewAEIdleUPP(MyAEIdleCallback);
30     }
31     return self;
32 }
33
34 - (void)dealloc
35 {
36     DisposeAEIdleUPP(idleUPP);
37 }
38
39 - (NSString*)sendAEWithRequestedKey:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
40 {
41     //Add error checking...
42     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
43     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
44     int pid;
45     NSString *nssendString = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [key UTF8String]];
46     const char *sendString = [nssendString UTF8String];
47     NSString  *_finalString = nil;
48
49     AppleEvent sendEvent, replyEvent;
50
51     DescType resultType;
52     Size resultSize, charResultSize;
53
54     AEBuildError buildError;
55     OSStatus err;
56     OSErr berr, err2, err3;
57     
58         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
59             ITDebugLog(@"Error getting PID of application.");
60             return nil;
61         }
62
63     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
64     [self printCarbonDesc:&sendEvent];
65
66     if (berr) {
67         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
68     }
69
70     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
71
72     [self printCarbonDesc:&replyEvent];
73
74     if (err) {
75         ITDebugLog(@"Send Error: %i",err);
76     } else {
77         unichar *result = 0;
78
79         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
80         if (resultSize != 0) {
81             result = malloc(resultSize);
82         } else {
83             return nil;
84         }
85
86         if (err2) {
87             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
88         } else {
89             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
90
91             if (err3) {
92                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
93             } else {
94                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
95             }
96         }
97         free(result);
98     }
99
100     if (!berr) AEDisposeDesc(&sendEvent);
101     if (!err) AEDisposeDesc(&replyEvent);
102
103     return _finalString;
104 }
105
106 - (NSString*)sendAEWithSendString:(NSString*)nssendString eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
107 {
108     //Add error checking...
109     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
110     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
111     int pid;
112
113     const char *sendString = [nssendString UTF8String];
114     NSString  *_finalString = nil;
115
116     AppleEvent sendEvent, replyEvent;
117
118     DescType resultType;
119     Size resultSize, charResultSize;
120
121     AEBuildError buildError;
122     OSStatus berr,err;
123     OSErr err2, err3;
124     
125         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
126             ITDebugLog(@"Error getting PID of application.");
127             return nil;
128         }
129
130     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
131     if (!berr) [self printCarbonDesc:&sendEvent];
132
133     if (berr) {
134         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
135     }
136
137     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
138     if (!err) [self printCarbonDesc:&replyEvent];
139
140     if (err) {
141         ITDebugLog(@"Send Error: %i",err);
142     } else {
143         unichar *result = 0;
144
145         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
146         if (resultSize != 0) {
147             result = malloc(resultSize);
148         } else {
149             return nil;
150         }
151
152         if (err2) {
153             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
154         } else {
155             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
156
157             if (err3) {
158                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
159             } else {
160                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
161             }
162         }
163         free(result);
164     }
165
166     if (!berr) AEDisposeDesc(&sendEvent);
167     if (!err) AEDisposeDesc(&replyEvent);
168
169     return _finalString;
170 }
171
172 - (long)sendAEWithRequestedKeyForNumber:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
173 {
174     //Add error checking...
175     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
176     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
177     int pid;
178
179     NSString *nssendString = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [key UTF8String]];
180     const char *sendString = [nssendString UTF8String];
181     long result = 0;
182
183     AppleEvent sendEvent, replyEvent;
184
185     DescType resultType;
186     Size resultSize, charResultSize;
187
188     AEBuildError buildError;
189     OSStatus err;
190     OSErr berr, err2, err3;
191     
192         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
193             ITDebugLog(@"Error getting PID of application.");
194             return nil;
195         }
196
197     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
198
199     [self printCarbonDesc:&sendEvent];
200
201     if (berr) {
202         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
203     }
204
205     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
206
207     [self printCarbonDesc:&replyEvent];
208
209     if (err) {
210         ITDebugLog(@"Send Error: %i",err);
211     } else {
212         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
213
214         if (err2) {
215             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
216         } else {
217             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
218
219             if (err3) {
220                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
221             }
222         }
223     }
224
225     if (!berr) AEDisposeDesc(&sendEvent);
226     if (!err) AEDisposeDesc(&replyEvent);
227
228     return result;
229 }
230
231 - (NSString*)sendTwoTierAEWithRequestedKey:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
232 {
233     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
234     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
235     int pid;
236
237     NSString *nssendString = [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]];
238     const char *sendString = [nssendString UTF8String];
239     NSString  *_finalString = nil;
240
241     AppleEvent sendEvent, replyEvent;
242
243     DescType resultType;
244     Size resultSize, charResultSize;
245
246     AEBuildError buildError;
247     OSStatus berr,err;
248     OSErr err2, err3;
249     
250         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
251             ITDebugLog(@"Error getting PID of application.");
252             return nil;
253         }
254
255     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
256
257     [self printCarbonDesc:&sendEvent];
258
259     if (berr) {
260         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
261     }
262
263     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
264
265     [self printCarbonDesc:&replyEvent];
266
267     if (err) {
268         ITDebugLog(@"Send Error: %i",err);
269     } else {
270         unichar *result = 0;
271
272         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
273         if (resultSize != 0) {
274             result = malloc(resultSize);
275         } else {
276             return nil;
277         }
278         
279         if (err2) {
280             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
281         } else {
282             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
283
284             if (err3) {
285                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
286             } else {
287                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
288             }
289         }
290         free(result);
291     }
292
293     if (!berr) AEDisposeDesc(&sendEvent);
294     if (!err) 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     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
302     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
303
304     NSString *nssendString = [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]];
305     const char *sendString = [nssendString UTF8String];
306     long result = 0;
307
308     AppleEvent sendEvent, replyEvent;
309     int pid;
310
311     DescType resultType;
312     Size resultSize, charResultSize;
313
314     AEBuildError buildError;
315     OSStatus berr, err;
316     OSErr err2, err3;
317     
318         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
319             ITDebugLog(@"Error getting PID of application.");
320             return nil;
321         }
322
323     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
324
325     [self printCarbonDesc:&sendEvent];
326
327     if (berr) {
328         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
329     }
330
331     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
332
333     [self printCarbonDesc:&replyEvent];
334
335     if (err) {
336         ITDebugLog(@"Send Error: %i",err);
337     } else {
338         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
339
340         if (err2) {
341             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
342         } else {
343             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
344
345             if (err3) {
346                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
347             }
348         }
349     }
350
351     if (!berr) AEDisposeDesc(&sendEvent);
352     if (!err) AEDisposeDesc(&replyEvent);
353
354     return result;
355 }
356
357 - (NSString *)sendAEWithRequestedArray:(NSArray *)array eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
358 {
359     NSString *buildString = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [[array objectAtIndex:0] UTF8String]];
360     const char *sendString;
361     int i;
362     NSString  *_finalString = nil;
363     int pid;
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 berr, 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             ITDebugLog(@"Error getting PID of application.");
387             return nil;
388         }
389
390     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
391
392     [self printCarbonDesc:&sendEvent];
393
394     if (berr) {
395         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[buildString substringToIndex:buildError.fErrorPos]);
396     }
397
398     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
399
400     [self printCarbonDesc:&replyEvent];
401
402     if (err) {
403         ITDebugLog(@"Send Error: %i",err);
404     } else {
405         unichar *result = 0;
406
407         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
408         if (resultSize != 0) {
409             result = malloc(resultSize);
410         } else {
411             return nil;
412         }
413         if (err2) {
414             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
415         } else {
416             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
417             if (err3) {
418                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
419             } else {
420                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
421             }
422         }
423         free(result);
424     }
425     if (!berr) AEDisposeDesc(&sendEvent);
426     if (!err) AEDisposeDesc(&replyEvent);
427     return _finalString;
428 }
429
430 - (void)sendAEWithEventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
431 {
432     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
433     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
434     AEDesc dest;
435     int pid;
436
437     AppleEvent event, reply;
438     OSStatus cerr,cerr2,err;
439     //AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, kAnyTransactionID, &event, nil, "");
440     if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
441         ITDebugLog(@"Error getting PID of application.");
442         return;
443     }
444     cerr = AECreateDesc(typeProcessSerialNumber,(ProcessSerialNumber*)&psn,sizeof(ProcessSerialNumber),&dest);
445     cerr2 = AECreateAppleEvent(eClass,eID,&dest,kAutoGenerateReturnID,kAnyTransactionID,&event);
446     [self printCarbonDesc:&event];
447     err = AESend(&event, &reply, kAENoReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, nil);
448     [self printCarbonDesc:&reply];
449     if (!cerr2) AEDisposeDesc(&dest);
450     if (!cerr) AEDisposeDesc(&event);
451     if (!err) AEDisposeDesc(&reply);
452 }
453
454 - (void)printCarbonDesc:(AEDesc*)desc {
455     Handle xx;
456     AEPrintDescToHandle(desc,&xx);
457     ITDebugLog(@"AE Descriptor: %s", *xx);
458     DisposeHandle(xx);
459 }
460
461
462 - (AEArrayDataPointer)sendAEWithRequestedKeyForArray:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
463 {
464     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
465     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
466
467     NSString *nssendString = [NSString stringWithFormat:@"'----':obj { form:'indx', want:'%s', seld:type('all '), from:'null'() }", [key UTF8String]];
468     const char *sendString = [nssendString UTF8String];
469     AEArrayDataPointer result = nil;
470     int pid;
471
472     AppleEvent sendEvent, replyEvent;
473
474
475     AEBuildError buildError;
476     OSStatus err;
477
478 if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
479             ITDebugLog(@"Error getting PID of application.");
480             return nil;
481         }
482     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
483
484     [self printCarbonDesc:&sendEvent];
485
486     if (err) {
487         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
488     }
489
490
491     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
492
493     [self printCarbonDesc:&replyEvent];
494
495     if (err) {
496         ITDebugLog(@"Send Error: %i",err);
497     } else {
498            SInt32 count, resultCount;
499
500            AECountItems(&replyEvent,&count);
501            if ((sizeof(AEDesc)*count) != 0) {
502                result=malloc(sizeof(AEDesc)*count);
503            } else {
504                return nil;
505            }
506            AEGetArray(&replyEvent, kAEDescArray, result, sizeof(AEDesc)*count, NULL, NULL, &resultCount);
507
508         free(result);
509     }
510
511     AEDisposeDesc(&sendEvent);
512     AEDisposeDesc(&replyEvent);
513
514     return result;
515 }
516
517 - (long)sendAEWithSendStringForNumber:(NSString*)string eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
518 {
519     //Add error checking...
520     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
521     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
522
523     const char *sendString = [string UTF8String];
524     SInt32 result = 0;
525     int pid;
526
527     AppleEvent sendEvent, replyEvent;
528
529     DescType resultType;
530     Size resultSize, charResultSize;
531
532     AEBuildError buildError;
533     OSStatus berr, err;
534     OSErr err2, err3;
535     
536         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
537             ITDebugLog(@"Error getting PID of application.");
538             return nil;
539         }
540
541     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
542
543     [self printCarbonDesc:&sendEvent];
544
545     if (berr) {
546         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[string substringToIndex:buildError.fErrorPos]);
547     }
548
549     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
550
551     [self printCarbonDesc:&replyEvent];
552
553     if (err) {
554         ITDebugLog(@"Send Error: %i",err);
555     } else {
556         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
557
558         if (err2) {
559             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
560         } else {
561             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
562
563             if (err3) {
564                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
565             }
566         }
567     }
568
569
570 if (!berr) AEDisposeDesc(&sendEvent);
571 if (!err) AEDisposeDesc(&replyEvent);
572 ITDebugLog(@"waffles say %d",result);
573 return result;
574 }
575
576 - (AEArrayDataPointer)sendAEWithSendStringForArray:(NSString*)string eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
577 {
578     //Add error checking...
579     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
580     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
581     int pid;
582
583     const char *sendString = [string UTF8String];
584     AEArrayDataPointer result = NULL;
585
586     AppleEvent sendEvent, replyEvent;
587
588     AEBuildError buildError;
589     OSStatus berr, err;
590     
591         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
592             ITDebugLog(@"Error getting PID of application.");
593             return nil;
594         }
595
596     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
597
598     [self printCarbonDesc:&sendEvent];
599
600     if (berr) {
601         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[string substringToIndex:buildError.fErrorPos]);
602     }
603
604     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
605
606     [self printCarbonDesc:&replyEvent];
607
608     if (err) {
609         ITDebugLog(@"Send Error: %i",err);
610     } else {
611         SInt32 count, resultCount;
612         
613         AECountItems(&replyEvent,&count);
614         if ((sizeof(AEDesc)*count) != 0) {
615                result=malloc(sizeof(AEDesc)*count);
616         } else {
617                return nil;
618         }
619         AEGetArray(&replyEvent, kAEDescArray, result, sizeof(AEDesc)*count, NULL, NULL, &resultCount);
620         
621         free(result);
622     }
623
624     if (!berr) AEDisposeDesc(&sendEvent);
625     if (!err) AEDisposeDesc(&replyEvent);
626
627     return result;
628 }
629
630 - (NSData*)sendAEWithSendStringForData:(NSString*)nssendString eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
631 {
632     //Add error checking...
633     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
634     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
635     int pid;
636     
637     const char *sendString = [nssendString UTF8String];
638     NSData  *_finalData = nil;
639     
640     AppleEvent sendEvent, replyEvent;
641     
642     DescType resultType;
643     Size resultSize, charResultSize;
644     
645     AEBuildError buildError;
646     OSStatus berr,err;
647     OSErr err2, err3;
648     
649     if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
650         ITDebugLog(@"Error getting PID of application.");
651         return nil;
652     }
653     
654     berr = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
655     if (!berr) [self printCarbonDesc:&sendEvent];
656     
657     if (berr) {
658         ITDebugLog(@"Error: %d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[nssendString substringToIndex:buildError.fErrorPos]);
659     }
660     
661     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, /*kAEDefaultTimeout*/30, idleUPP, NULL);
662     if (!err) [self printCarbonDesc:&replyEvent];
663     
664     if (err) {
665         ITDebugLog(@"Send Error: %i",err);
666     } else {
667         unichar *result = 0;
668         
669         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
670         if (resultSize != 0) {
671             result = malloc(resultSize);
672         } else {
673             return nil;
674         }
675         
676         if (err2) {
677             ITDebugLog(@"Error After AESizeOfParam: %i", err2);
678         } else {
679             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
680             
681             if (err3) {
682                 ITDebugLog(@"Error After AEGetParamPtr: %i", err3);
683             } else {
684                 _finalData = [NSData dataWithBytesNoCopy:result length:charResultSize freeWhenDone:YES];
685             }
686         }
687     }
688     
689     if (!berr) AEDisposeDesc(&sendEvent);
690     if (!err) AEDisposeDesc(&replyEvent);
691     
692     return _finalData;
693 }
694
695 @end