Now all ITInetServerSockets share one runloop timer. Had to rewrite the entire API...
[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 - (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             }
160         }
161     }
162
163     AEDisposeDesc(&sendEvent);
164     AEDisposeDesc(&replyEvent);
165
166     return result;
167 }
168
169 - (NSString*)sendTwoTierAEWithRequestedKey:(NSString*)key fromObjectByKey:(NSString*)object eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
170 {
171     //Add error checking...
172     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
173     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
174
175     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];
176     NSString  *_finalString = nil;
177
178     AppleEvent sendEvent, replyEvent;
179
180     DescType resultType;
181     Size resultSize, charResultSize;
182
183     AEBuildError buildError;
184     OSStatus err;
185     OSErr err2, err3;
186     /*
187         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
188             NSLog(@"Error getting PID of application! Exiting.");
189             return nil;
190         }*/
191
192     //NSLog(@"_sendString: %s", sendString);
193
194     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
195
196     //[self printCarbonDesc:&sendEvent];
197
198     if (err) {
199         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
200     }
201
202     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
203
204     //[self printCarbonDesc:&replyEvent];
205
206     if (err) {
207         NSLog(@"Send Error: %i",err);
208     } else {
209         unichar *result = 0;
210
211         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
212         result = malloc(resultSize);
213
214         if (err2) {
215             NSLog(@"Error After AESizeOfParam: %i", err2);
216         } else {
217             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
218
219             if (err3) {
220                 NSLog(@"Error After AEGetParamPtr: %i", err3);
221             } else {
222                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
223             }
224         }
225         free(result);
226     }
227
228     AEDisposeDesc(&sendEvent);
229     AEDisposeDesc(&replyEvent);
230
231     return _finalString;
232 }
233
234 - (long)sendTwoTierAEWithRequestedKeyForNumber:(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     long result = 0;
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         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
275
276         if (err2) {
277             NSLog(@"Error After AESizeOfParam: %i", err2);
278         } else {
279             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
280
281             if (err3) {
282                 NSLog(@"Error After AEGetParamPtr: %i", err3);
283             }
284         }
285     }
286
287     AEDisposeDesc(&sendEvent);
288     AEDisposeDesc(&replyEvent);
289
290     return result;
291 }
292
293 - (NSString *)sendAEWithRequestedArray:(NSArray *)array eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
294 {
295     NSString *buildString = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:'null'() }", [[array objectAtIndex:0] UTF8String]];
296     const char *sendString;
297     int i;
298     NSString  *_finalString = nil;
299
300     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
301     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
302
303     AppleEvent sendEvent, replyEvent;
304
305     DescType resultType;
306     Size resultSize, charResultSize;
307
308     AEBuildError buildError;
309     OSStatus err;
310     OSErr err2, err3;
311
312     for (i = 1; i < [array count]; i++) {
313         NSString *from = [NSString stringWithFormat:@"{ form:'prop', want:type('prop'), seld:type('%s'), from:obj %@ }",
314                   [[array objectAtIndex:i] UTF8String], buildString];
315         buildString = from;
316     }
317     buildString = [@"'----':obj " stringByAppendingString:buildString];
318     sendString = [buildString UTF8String];
319     /*
320         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
321             NSLog(@"Error getting PID of application! Exiting.");
322             return nil;
323         }
324         */
325     //NSLog(@"_sendString: %s", sendString);
326
327     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
328
329     //[self printCarbonDesc:&sendEvent];
330
331     if (err) {
332         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
333     }
334
335     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
336
337     //[self printCarbonDesc:&replyEvent];
338
339     if (err) {
340         NSLog(@"Send Error: %i",err);
341     } else {
342         unichar *result = 0;
343
344         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
345         result=malloc(resultSize);
346
347         if (err2) {
348             NSLog(@"Error After AESizeOfParam: %i", err2);
349         } else {
350             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, result, resultSize, &charResultSize);
351             if (err3) {
352                 NSLog(@"Error After AEGetParamPtr: %i", err3);
353             } else {
354                 _finalString = [NSString stringWithCharacters:result length:charResultSize/sizeof(unichar)];
355             }
356         }
357         free(result);
358     }
359     return _finalString;
360 }
361
362 - (void)sendAEWithEventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
363 {
364     //Add error checking...
365     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
366     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
367     AEDesc dest;
368     AppleEvent event, reply;
369
370     //AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, kAnyTransactionID, &event, nil, "");
371     AECreateDesc(typeProcessSerialNumber,(ProcessSerialNumber*)&psn,sizeof(ProcessSerialNumber),&dest);
372     AECreateAppleEvent(eClass,eID,&dest,kAutoGenerateReturnID,kAnyTransactionID,&event);
373     AESend(&event, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, idleUPP, nil);
374
375     AEDisposeDesc(&dest);
376     AEDisposeDesc(&event);
377     AEDisposeDesc(&reply);
378 }
379
380 - (void)printCarbonDesc:(AEDesc*)desc {
381     /*Handle xx;
382     AEPrintDescToHandle(desc,&xx);
383     NSLog(@"Handle: %s", *xx);
384     DisposeHandle(xx);*/
385 }
386
387
388 - (AEArrayDataPointer)sendAEWithRequestedKeyForArray:(NSString*)key eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
389 {
390     //Add error checking...
391     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
392     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
393
394     const char *sendString = [[NSString stringWithFormat:@"'----':obj { form:'indx', want:'%s', seld:abso($616C6C20$), from:'null'() }", [key UTF8String]] UTF8String];
395     AEArrayDataPointer result = nil;
396
397     AppleEvent sendEvent, replyEvent;
398
399     DescType resultType;
400     Size resultSize, charResultSize;
401
402     AEBuildError buildError;
403     OSStatus err;
404     OSErr err2, err3;
405
406     //NSLog(@"_sendString: %s", sendString);
407
408     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
409
410     //[self printCarbonDesc:&sendEvent];
411
412     if (err) {
413         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
414     }
415
416     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
417
418     //[self printCarbonDesc:&replyEvent];
419
420     if (err) {
421         NSLog(@"Send Error: %i",err);
422     } else {
423            SInt32 count, resultCount;
424
425            AECountItems(&replyEvent,&count);
426            result=malloc(sizeof(AEDesc)*count);
427            AEGetArray(&replyEvent, kAEDescArray, result, sizeof(AEDesc)*count, NULL, NULL, &resultCount);
428
429         free(result);
430     }
431
432     AEDisposeDesc(&sendEvent);
433     AEDisposeDesc(&replyEvent);
434
435     return result;
436 }
437
438 - (long)sendAEWithSendStringForNumber:(NSString*)string eventClass:(NSString*)eventClass eventID:(NSString*)eventID appPSN:(ProcessSerialNumber)psn
439 {
440     //Add error checking...
441     AEEventClass eClass = *((unsigned long*)[eventClass UTF8String]);
442     AEEventID    eID    = *((unsigned long*)[eventID UTF8String]);
443
444     const char *sendString = [string UTF8String];
445     long result = 0;
446
447     AppleEvent sendEvent, replyEvent;
448
449     DescType resultType;
450     Size resultSize, charResultSize;
451     
452     AEBuildError buildError;
453     OSStatus err;
454     OSErr err2, err3;
455     /*
456         if ((GetProcessPID(&psn, &pid) == noErr) && (pid == 0)) {
457             NSLog(@"Error getting PID of application! Exiting.");
458             return nil;
459         }
460         */
461     //NSLog(@"_sendString: %s", sendString);
462
463     err = AEBuildAppleEvent(eClass, eID, typeProcessSerialNumber,(ProcessSerialNumber*)&psn, sizeof(ProcessSerialNumber), kAutoGenerateReturnID, 0, &sendEvent, &buildError, sendString);
464
465     //[self printCarbonDesc:&sendEvent];
466
467     if (err) {
468         NSLog(@"%d:%d at \"%@\"",(int)buildError.fError,buildError.fErrorPos,[sendString substringToIndex:buildError.fErrorPos]);
469     }
470
471     err = AESend(&sendEvent, &replyEvent, kAEWaitReply, kAENormalPriority, kNoTimeOut, idleUPP, NULL);
472
473     [self printCarbonDesc:&replyEvent];
474
475     if (err) {
476         NSLog(@"Send Error: %i",err);
477     } else {
478         err2 = AESizeOfParam(&replyEvent, keyDirectObject, &resultType, &resultSize);
479
480         if (err2) {
481             NSLog(@"Error After AESizeOfParam: %i", err2);
482         } else {
483             err3 = AEGetParamPtr(&replyEvent, keyDirectObject, resultType, NULL, &result, resultSize, &charResultSize);
484
485             if (err3) {
486                 NSLog(@"Error After AEGetParamPtr: %i", err3);
487             }
488         }
489     }
490
491     AEDisposeDesc(&sendEvent);
492     AEDisposeDesc(&replyEvent);
493
494     return result;
495 }
496
497 @end