Fixed a lot of memory leaks. The new array stuff has a better chance of working now
[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)] copy];
99             }
100         }
101         free(result);
102     }
103
104     AEDisposeDesc(&sendEvent);
105     AEDisposeDesc(&replyEvent);
106
107     return _finalString;
108 }
109
110 - (long)sendAEWithRequestedKeyForNumber:(NSString*)key 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 = [[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [key UTF8String]] UTF8String];
117     long result = 0;
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         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
151
152         if (err2) {
153             NSLog(@"Error After AESizeOfParam: %i", err2);
154         } else {
155             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
156
157             if (err3) {
158                 NSLog(@"Error After AEGetParamPtr: %i", err3);
159             } else {
160                 NSLog(@"%i", result);
161             }
162         }
163     }
164
165     AEDisposeDesc(&sendEvent);
166     AEDisposeDesc(&replyEvent);
167
168     return result;
169 }
170
171 - (NSString*)sendTwoTierAEWithRequestedKey:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
172 {
173     //Add error checking...
174     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
175     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
176
177     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];
178     NSString  *_finalString = nil;
179
180     AppleEvent sendEvent, replyEvent;
181
182     DescType resultType;
183     Size resultSize, charResultSize;
184
185     AEBuildError buildError;
186     OSStatus err;
187     OSErr err2, err3;
188     /*
189         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
190             NSLog(@"Error getting PID of application! Exiting.");
191             return nil;
192         }*/
193
194     //NSLog(@"_sendString: %s", sendString);
195
196     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
197
198     //[self printCarbonDesc:&sendEvent];
199
200     if (err) {
201         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
202     }
203
204     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
205
206     //[self printCarbonDesc:&replyEvent];
207
208     if (err) {
209         NSLog(@"Send Error: %i",err);
210     } else {
211         unichar *result = 0;
212
213         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
214         result = malloc(resultSize);
215
216         if (err2) {
217             NSLog(@"Error After AESizeOfParam: %i", err2);
218         } else {
219             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
220
221             if (err3) {
222                 NSLog(@"Error After AEGetParamPtr: %i", err3);
223             } else {
224                 _finalString = [[NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)] copy];
225             }
226         }
227         free(result);
228     }
229
230     AEDisposeDesc(&sendEvent);
231     AEDisposeDesc(&replyEvent);
232
233     return _finalString;
234 }
235
236 - (long)sendTwoTierAEWithRequestedKeyForNumber:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
237 {
238     //Add error checking...
239     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
240     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
241
242     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];
243     long result = 0;
244
245     AppleEvent sendEvent, replyEvent;
246
247     DescType resultType;
248     Size resultSize, charResultSize;
249
250     AEBuildError buildError;
251     OSStatus err;
252     OSErr err2, err3;
253     /*
254         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
255             NSLog(@"Error getting PID of application! Exiting.");
256             return nil;
257         }
258         */
259     // NSLog(@"_sendString: %s", sendString);
260
261     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
262
263     //[self printCarbonDesc:&sendEvent];
264
265     if (err) {
266         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
267     }
268
269     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
270
271     [self printCarbonDesc:&replyEvent];
272
273     if (err) {
274         NSLog(@"Send Error: %i",err);
275     } else {
276         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
277
278         if (err2) {
279             NSLog(@"Error After AESizeOfParam: %i", err2);
280         } else {
281             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
282
283             if (err3) {
284                 NSLog(@"Error After AEGetParamPtr: %i", err3);
285             } else {
286                 NSLog(@"%i", result);
287             }
288         }
289     }
290
291     AEDisposeDesc(&sendEvent);
292     AEDisposeDesc(&replyEvent);
293
294     return result;
295 }
296
297 - (NSString *)sendAEWithRequestedArray:(NSArray *)array eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
298 {
299     NSString *buildString = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [[array objectAtIndex:0] UTF8String]];
300     const char *sendString;
301     int i;
302     NSString  *_finalString = nil;
303
304     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
305     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
306
307     AppleEvent sendEvent, replyEvent;
308
309     DescType resultType;
310     Size resultSize, charResultSize;
311
312     AEBuildError buildError;
313     OSStatus err;
314     OSErr err2, err3;
315
316     for (i = 1; i < [array count]; i++) {
317         NSString *from = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:obj %@ }",
318                   [[array objectAtIndex:i] UTF8String], buildString];
319         buildString = from;
320     }
321     buildString = [@"'----':obj " stringByAppendingString:buildString];
322     sendString = [buildString UTF8String];
323     /*
324         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
325             NSLog(@"Error getting PID of application! Exiting.");
326             return nil;
327         }
328         */
329     //NSLog(@"_sendString: %s", sendString);
330
331     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
332
333     //[self printCarbonDesc:&sendEvent];
334
335     if (err) {
336         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
337     }
338
339     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
340
341     //[self printCarbonDesc:&replyEvent];
342
343     if (err) {
344         NSLog(@"Send Error: %i",err);
345     } else {
346         unichar *result = 0;
347
348         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
349         result=malloc(resultSize);
350
351         if (err2) {
352             NSLog(@"Error After AESizeOfParam: %i", err2);
353         } else {
354             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
355             if (err3) {
356                 NSLog(@"Error After AEGetParamPtr: %i", err3);
357             } else {
358                 _finalString = [[NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)] copy];
359             }
360         }
361         free(result);
362     }
363     return _finalString;
364 }
365
366 - (void)sendAEWithEventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
367 {
368     //Add error checking...
369     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
370     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
371     AEDesc dest;
372     AppleEvent event, reply;
373
374     //AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, kAnyTransactionID, &event, nil, "");
375     AECreateDesc(typeProcessSerialNumber,(ProcessSerialNumber*)&psn,sizeof(ProcessSerialNumber),&dest);
376     AECreateAppleEvent(eClass,eID,&dest,kAutoGenerateReturnID,kAnyTransactionID,&event);
377     AESend(&event, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, idleUPP, nil);
378
379     AEDisposeDesc(&dest);
380     AEDisposeDesc(&event);
381     AEDisposeDesc(&reply);
382 }
383
384 - (void)printCarbonDesc:(AEDesc*)desc {
385     Handle xx;
386     AEPrintDescToHandle(desc,&xx);
387     NSLog(@"Handle: %s", *xx);
388     DisposeHandle(xx);
389 }
390
391
392 - (AEArrayDataPointer)sendAEWithRequestedKeyForArray:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
393 {
394     //Add error checking...
395     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
396     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
397
398     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'indx', want:'%s', seld:abso($616C6C20$), from:'null'() }", [key UTF8String]] UTF8String];
399     AEArrayDataPointer result = nil;
400
401     AppleEvent sendEvent, replyEvent;
402
403     DescType resultType;
404     Size resultSize, charResultSize;
405
406     AEBuildError buildError;
407     OSStatus err;
408     OSErr err2, err3;
409
410     //NSLog(@"_sendString: %s", sendString);
411
412     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
413
414     //[self printCarbonDesc:&sendEvent];
415
416     if (err) {
417         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
418     }
419
420     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
421
422     //[self printCarbonDesc:&replyEvent];
423
424     if (err) {
425         NSLog(@"Send Error: %i",err);
426     } else {
427            SInt32 count, resultCount;
428
429            AECountItems(&replyEvent,&count);
430            result=malloc(sizeof(AEDesc)*count);
431            AEGetArray(&replyEvent, kAEDescArray, result, sizeof(AEDesc)*count, NULL, NULL, &resultCount);
432
433         free(result);
434     }
435
436     AEDisposeDesc(&sendEvent);
437     AEDisposeDesc(&replyEvent);
438
439     return result;
440 }
441
442 @end