Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Classes/MyAppController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 169 - (show annotations) (download)
Sun Oct 27 01:45:31 2019 UTC (4 years, 5 months ago) by toshinagata1964
File size: 21653 byte(s)
Behavior of the split view of the graphic window is fixed
1 //
2 // MyAppController.m
3 //
4 // Created by Toshi Nagata.
5 /*
6 Copyright (c) 2000-2017 Toshi Nagata. All rights reserved.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 */
17
18 #import "MyAppController.h"
19 #import "MyDocument.h"
20 #import "LoadingPanelController.h"
21 #import "GraphicWindowController.h"
22 #import "RubyConsoleWindowController.h"
23 #import "AudioSettingsPanelController.h"
24 #import "AudioSettingsPrefPanelController.h"
25 #import "MetronomeSettingsPanelController.h"
26 #import "AboutWindowController.h"
27
28 #include "MDHeaders.h"
29 #include "MDRubyExtern.h"
30
31 NSString *MyAppScriptMenuModifiedNotification = @"Script menu modified";
32 NSString *MyAppControllerMIDISetupDidChangeNotification = @"MIDI setup changed";
33 NSString *MyAppControllerModalPanelTimerNotification = @"Modal Panel timer fired";
34
35 static int sScriptMenuCount = 0;
36 static BOOL sStartupCompleted = NO; // If NO, then Ruby interrupt check is disabled
37
38 @implementation MyAppController
39
40 // ���������������������������������������������������������������
41 //- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender {
42 // return NO;
43 //}
44
45 - (void)dealloc
46 {
47 [[NSNotificationCenter defaultCenter]
48 removeObserver:self];
49 [super dealloc];
50 }
51
52 - (void)applicationWillFinishLaunching:(NSNotification *)aNotification
53 {
54 [AboutWindowController showSplashWindow];
55
56 // Initialize Audio/MIDI devices
57 MDAudioInitialize();
58
59 [[NSNotificationCenter defaultCenter]
60 addObserver:self
61 selector:@selector(updateScriptMenu:)
62 name:MyAppScriptMenuModifiedNotification
63 object:self];
64
65 scriptMenuInfos = [[NSMutableArray array] retain];
66 sScriptMenuCount = (int)[scriptMenu numberOfItems];
67
68 {
69 int i;
70
71 // Load Ruby console window (initially invisible)
72 [[[RubyConsoleWindowController sharedRubyConsoleWindowController] window] orderOut: self];
73
74 // Initialize MDRuby
75 Ruby_startup();
76
77 // MDRuby startup scripts
78 // (Executed in alphabetical order)
79 NSFileManager *manager = [NSFileManager defaultManager];
80 int status = 0;
81 NSString *pluginDir = [[[NSBundle mainBundle] builtInPlugInsPath] stringByAppendingPathComponent: @"Ruby_Scripts"];
82 NSString *cwd = [manager currentDirectoryPath];
83 NSArray *scriptArray = [[manager contentsOfDirectoryAtPath:pluginDir error:NULL] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
84 [manager changeCurrentDirectoryPath: pluginDir];
85 for (i = 0; i < [scriptArray count]; i++) {
86 const char *s = [[scriptArray objectAtIndex: i] UTF8String];
87 if (s == NULL)
88 continue;
89 MyAppCallback_showScriptMessage("Loading %s...\n", s);
90 MyAppCallback_executeScriptFromFile(s, &status);
91 if (status != 0) {
92 Ruby_showError(status);
93 break;
94 }
95 }
96 if (status == 0)
97 MyAppCallback_showScriptMessage("Done.\n");
98 MyAppCallback_showRubyPrompt();
99 [manager changeCurrentDirectoryPath: cwd];
100 }
101
102 [MetronomeSettingsPanelController initializeMetronomeSettings];
103
104 [AboutWindowController hideSplashWindow];
105
106 sStartupCompleted = YES;
107 }
108
109 - (void)applicationWillTerminate:(NSNotification *)aNotification
110 {
111 MDAudioDispose();
112 MyAppCallback_saveGlobalSettings();
113 }
114
115 static id
116 findMenuItemWithTitle(NSMenu *menu, NSString *title)
117 {
118 int i, n;
119 n = (int)[menu numberOfItems];
120 for (i = 0; i < n; i++) {
121 id item = [menu itemAtIndex:i];
122 if ([title isEqualToString:[item title]])
123 return item;
124 if ([item hasSubmenu]) {
125 item = findMenuItemWithTitle([item submenu], title);
126 if (item != nil)
127 return item;
128 }
129 }
130 return nil;
131 }
132
133 static void
134 appendScriptMenuItems(NSMenu *menu, NSArray *infos, SEL action, id target)
135 {
136 int i, n, added;
137 NSMenu *mainMenu = [NSApp mainMenu];
138 n = (int)[infos count];
139 added = 0;
140 for (i = 0; i < n; i++) {
141 id obj = [infos objectAtIndex: i];
142 NSString *title = (NSString *)[obj valueForKey:@"title"];
143 id item;
144 item = findMenuItemWithTitle(mainMenu, title);
145 if (item != nil) {
146 [item setAction:action];
147 } else {
148 if (added == 0)
149 [menu addItem:[NSMenuItem separatorItem]];
150 item = [menu insertItemWithTitle: @"X" action: action keyEquivalent: @"" atIndex: added + sScriptMenuCount + 1];
151 [item setTitle:title];
152 added++;
153 }
154 [item setTag: i];
155 [item setTarget: target];
156 }
157 }
158
159 - (void)registerScriptMenu: (NSString *)commandName withTitle: (NSString *)menuTitle validator:(int32_t)rubyValue
160 {
161 int i, n;
162 n = (int)[scriptMenuInfos count];
163 for (i = 0; i < n; i++) {
164 id obj = [scriptMenuInfos objectAtIndex: i];
165 if ([commandName isEqualToString: [obj valueForKey: @"command"]]) {
166 [obj setValue: menuTitle forKey: @"title"];
167 break;
168 } else if ([menuTitle isEqualToString: [obj valueForKey: @"title"]]) {
169 [obj setValue: commandName forKey: @"command"];
170 break;
171 }
172 }
173 if (i >= n) {
174 [scriptMenuInfos addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:
175 commandName, @"command", menuTitle, @"title",
176 [NSNumber numberWithLong:rubyValue], @"validator",
177 nil]];
178 }
179
180 // Post notification (processed only once per event loop)
181 [[NSNotificationQueue defaultQueue]
182 enqueueNotification:
183 [NSNotification notificationWithName: MyAppScriptMenuModifiedNotification object: self]
184 postingStyle: NSPostWhenIdle
185 coalesceMask: NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender
186 forModes: nil];
187 }
188
189 - (void)updateScriptMenu: (NSNotification *)aNotification
190 {
191 while ([scriptMenu numberOfItems] > sScriptMenuCount) {
192 [scriptMenu removeItemAtIndex: sScriptMenuCount];
193 }
194 if ([scriptMenuInfos count] > 0) {
195 appendScriptMenuItems(scriptMenu, scriptMenuInfos, @selector(doScriptCommand:), self);
196 }
197 }
198
199 - (IBAction)executeRubyScriptFromFile: (id)sender
200 {
201 NSOpenPanel *panel = [NSOpenPanel openPanel];
202 int status;
203 NSArray *URLs;
204 NSString *filename;
205 NSMutableString *script;
206 [panel setMessage: @"Choose Ruby script file"];
207 [panel setAllowedFileTypes:[NSArray arrayWithObjects: @"rb", nil]];
208 status = (int)[panel runModal];
209 URLs = [panel URLs];
210 [panel close];
211 if (status != NSOKButton)
212 return;
213 filename = [[URLs objectAtIndex: 0] path];
214
215 // Show command line in the Ruby console
216 script = [NSMutableString stringWithString: filename];
217 [script replaceOccurrencesOfString: @"\\" withString: @"\\\\" options: 0 range: NSMakeRange(0, [script length])]; // backslash
218 [script replaceOccurrencesOfString: @"'" withString: @"\\'" options: 0 range: NSMakeRange(0, [script length])]; // single quote
219 MyAppCallback_setConsoleColor(1);
220 MyAppCallback_showScriptMessage("execute_script('%s')\n", [script UTF8String]);
221 MyAppCallback_setConsoleColor(0);
222
223 // Execute file
224 MyAppCallback_executeScriptFromFile([filename UTF8String], &status);
225 if (status != 0)
226 Ruby_showError(status);
227 }
228
229 - (IBAction)openRubyConsole: (id)sender
230 {
231 [[[RubyConsoleWindowController sharedRubyConsoleWindowController] window] makeKeyAndOrderFront: self];
232 }
233
234 // Invoke Ruby command. If the command is a singleton method of the Sequence class, then
235 // the command is invoked with the document as the single argument (if document == nil, then
236 // with Qnil as the argument). Otherwise, the command should be a method of Sequence class,
237 // and the method is invoked with the document as self.
238 - (void)performScriptCommand: (NSString *)command forDocument: (MyDocument *)document
239 {
240 int kind, status;
241 const char *cmd = [command UTF8String];
242 kind = Ruby_methodType("Sequence", cmd);
243 if (kind != 1 && kind != 2) {
244 [[NSAlert alertWithMessageText: @"Undefined Command" defaultButton: nil alternateButton: nil otherButton: nil informativeTextWithFormat: @"The requested command %s is not defined.", cmd] runModal];
245 return;
246 }
247 status = Ruby_callMethodOfDocument(cmd, document, kind == 2, NULL);
248 if (status != 0) {
249 Ruby_showError(status);
250 return;
251 }
252 }
253
254 // Check if the command is valid as the script menu command.
255 // If the validator object is supplied, then the validator is called with the active document
256 // as the single argument. The menu is validated if the return value is 'true' as a Ruby value.
257 // Otherwise, if the method is a Sequence class method, the menu is always validated.
258 // Otherwise, the menu is validated if there is an active document.
259 - (BOOL)validateScriptCommand: (id)menuInfo forDocument: (MyDocument *)document
260 {
261 int kind;
262 int32_t validator = [[menuInfo valueForKey:@"validator"] intValue];
263 if (validator != (int32_t)RubyNil) {
264 return Ruby_callValidatorForDocument(validator, document);
265 } else {
266 const char *cmd;
267 id command = [menuInfo valueForKey:@"command"];
268 cmd = [command UTF8String];
269 kind = Ruby_methodType("Sequence", cmd);
270 if (kind == 2)
271 return YES;
272 if (kind == 1 && document != nil)
273 return YES;
274 return NO;
275 }
276 }
277
278 - (void)doScriptCommand: (id)sender
279 {
280 int i, n;
281 NSString *title = [sender title];
282 n = (int)[scriptMenuInfos count];
283 for (i = 0; i < n; i++) {
284 id obj = [scriptMenuInfos objectAtIndex: i];
285 if ([title isEqualToString: [obj valueForKey: @"title"]]) {
286 // Menu command found
287 [self performScriptCommand: [obj valueForKey: @"command"] forDocument: (MyDocument *)[self documentAtIndex: 0]];
288 return;
289 }
290 }
291 }
292
293 - (IBAction)openAudioSettingsPanel: (id)sender
294 {
295 [AudioSettingsPanelController openAudioSettingsPanel];
296 }
297
298 - (IBAction)exportAudioSettings: (id)sender
299 {
300 [[AudioSettingsPanelController sharedAudioSettingsPanelController] exportAudioSettings];
301 }
302
303 - (IBAction)importAudioSettings: (id)sender
304 {
305 [[AudioSettingsPanelController sharedAudioSettingsPanelController] importAudioSettings];
306 }
307
308 - (IBAction)openAudioSettingsPrefPanel: (id)sender
309 {
310 [AudioSettingsPrefPanelController openAudioSettingsPrefPanel];
311 }
312
313 - (IBAction)openMetronomeSettingsPanel: (id)sender
314 {
315 [MetronomeSettingsPanelController openMetronomeSettingsPanel];
316 }
317
318 - (IBAction)openAboutWindow:(id)sender
319 {
320 [AboutWindowController showModalAboutWindow];
321 }
322
323 - (IBAction)updateAudioAndMIDISettings:(id)sender
324 {
325 MDAudioUpdateDeviceInfo();
326 MDPlayerReloadDeviceInformation();
327 }
328
329 - (IBAction)tryTrackColorForCurrentDocument:(id)sender
330 {
331 // Pass the message to the current document
332 id doc = [[NSDocumentController sharedDocumentController] currentDocument];
333 if (doc != nil) {
334 GraphicWindowController *cont = [(MyDocument *)doc mainWindowController];
335 if (cont != nil)
336 [cont tryTrackColor:sender];
337 }
338 }
339
340 - (BOOL)validateUserInterfaceItem: (id)anItem
341 {
342 SEL sel = [anItem action];
343 if (sel == @selector(doScriptCommand:)) {
344 int i, n;
345 NSString *title = [anItem title];
346 n = (int)[scriptMenuInfos count];
347 for (i = 0; i < n; i++) {
348 id obj = [scriptMenuInfos objectAtIndex: i];
349 if ([title isEqualToString: [obj valueForKey: @"title"]]) {
350 // Menu command found
351 return [self validateScriptCommand: obj forDocument: (MyDocument *)[self documentAtIndex: 0]];
352 }
353 }
354 return NO;
355 }
356 return YES;
357 }
358
359 - (id)documentAtIndex: (int)idx
360 {
361 id documents = [NSApp orderedDocuments];
362 if (documents == nil || idx < 0 || idx >= [documents count])
363 return nil;
364 return [documents objectAtIndex: idx];
365 }
366
367 #pragma mark ====== Ruby Progress Panel Support ======
368
369 - (BOOL)showProgressPanel: (NSString *)caption
370 {
371 if (rubyProgressPanelController != nil)
372 return NO; /* Nested call */
373 rubyProgressPanelController = [[LoadingPanelController alloc] initWithTitle: @"MDRuby Progress" andCaption: caption];
374 [rubyProgressPanelController beginSession];
375 return YES;
376 }
377
378 - (void)hideProgressPanel
379 {
380 if (rubyProgressPanelController == nil)
381 return;
382 [rubyProgressPanelController endSession];
383 [rubyProgressPanelController close];
384 [rubyProgressPanelController autorelease];
385 rubyProgressPanelController = nil;
386 }
387
388 - (void)setProgressValue: (double)dval
389 {
390 [rubyProgressPanelController setProgressValue: dval * 100.0];
391 }
392
393 - (void)setProgressMessage: (NSString *)caption
394 {
395 [rubyProgressPanelController setCaption: caption];
396 }
397
398 - (BOOL)checkInterrupt
399 {
400 NSEvent *event;
401 NSString *s;
402 NSUInteger flags;
403 if (!sStartupCompleted)
404 return NO;
405 if (rubyProgressPanelController != nil) {
406 if (![rubyProgressPanelController runSession] || [rubyProgressPanelController canceled])
407 return YES;
408 else return NO;
409 } else {
410 while (nil != (event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil inMode: NSEventTrackingRunLoopMode dequeue: YES])) {
411 if ([event type] == NSKeyDown) {
412 s = [event charactersIgnoringModifiers];
413 flags = [event modifierFlags];
414 if ([s isEqualToString: @"."] && (flags & NSCommandKeyMask) != 0) {
415 return YES;
416 } else {
417 NSBeep();
418 return NO;
419 }
420 }
421 }
422 return NO;
423 }
424 }
425
426 - (void)getRubyVersion:(NSString **)outVersion copyright:(NSString **)outCopyright
427 {
428 const char *version, *copyright;
429 Ruby_getVersionStrings(&version, &copyright);
430 if (outVersion != NULL)
431 *outVersion = [NSString stringWithUTF8String:version];
432 if (outCopyright != NULL)
433 *outCopyright = [NSString stringWithUTF8String:copyright];
434 }
435
436 - (void)getVersion:(NSString **)outVersion copyright:(NSString **)outCopyright lastBuild:(NSString **)outLastBuild revision:(int *)outRevision
437 {
438 NSMutableData *data = [NSMutableData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource: @"Version" ofType: nil]];
439 char *p1, *p2;
440 char *p;
441 NSString *version, *copyright, *lastBuild;
442 version = copyright = lastBuild = nil;
443 if (data != nil) {
444 p = [data mutableBytes];
445 if ((p1 = strstr(p, "version")) != NULL) {
446 p1 = strchr(p1, '\"');
447 if (p1 != NULL) {
448 p1++;
449 p2 = strchr(p1, '\"');
450 if (p2 != NULL) {
451 *p2 = 0;
452 version = [NSString stringWithUTF8String:p1];
453 *p2 = '\"';
454 }
455 }
456 }
457 if ((p1 = strstr(p, "date")) != NULL) {
458 /* Release date */
459 p1 = strchr(p1, '\"');
460 if (p1 != NULL) {
461 p1++;
462 p2 = strchr(p1, '\"');
463 if (p2 != NULL) {
464 *p2 = 0;
465 if (strlen(p1) > 4) {
466 copyright = [NSString stringWithFormat:@"2000-%.4s", p1];
467 }
468 *p2 = '\"';
469 }
470 }
471 }
472 }
473 data = [NSMutableData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource: @"lastBuild.txt" ofType: nil]];
474 if (data != nil) {
475 p = [data mutableBytes];
476 if ((p1 = strstr(p, "last_build")) != NULL) {
477 p1 = strchr(p1, '\"');
478 if (p1 != NULL) {
479 p1++;
480 p2 = strchr(p1, '\"');
481 if (p2 != NULL) {
482 *p2 = 0;
483 lastBuild = [NSString stringWithUTF8String:p1];
484 copyright = [NSString stringWithFormat:@"2000-%.4s", p1];
485 *p2 = '\"';
486 }
487 }
488 }
489 if ((p1 = strstr(p, "svn_revision =")) != NULL) {
490 p1 = p1 + 14;
491 if (outRevision != NULL)
492 *outRevision = (int)strtol(p1, NULL, 0);
493 }
494 }
495 if (outVersion != NULL)
496 *outVersion = version;
497 if (outCopyright != NULL)
498 *outCopyright = copyright;
499 if (outLastBuild != NULL)
500 *outLastBuild = lastBuild;
501 }
502
503 - (int)getOSXVersion
504 {
505 static BOOL s_first_call = YES;
506 static int s_version;
507 if (s_first_call) {
508 int i[3];
509 NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
510 NSString *version = [dict objectForKey:@"ProductVersion"];
511 sscanf([version UTF8String], "%d.%d.%d", i, i + 1, i + 2);
512 s_version = i[0] * 10000 + i[1] * 100 + i[2];
513 }
514 return s_version;
515 }
516
517 @end
518
519 #pragma mark ====== Plain-C interface ======
520
521 static NSMutableDictionary *sGlobalSettings = nil;
522
523 void
524 MyAppCallback_loadGlobalSettings(void)
525 {
526 /* Do nothing */
527 }
528
529 void
530 MyAppCallback_saveGlobalSettings(void)
531 {
532 if (sGlobalSettings != nil) {
533 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
534 [defaults setValue:sGlobalSettings forKey:@"settings"];
535 [defaults synchronize];
536 }
537 }
538
539 id
540 MyAppCallback_getObjectGlobalSettings(id keyPath)
541 {
542 if (sGlobalSettings == nil) {
543 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
544 sGlobalSettings = [defaults valueForKey:@"settings"];
545 if (sGlobalSettings == nil) {
546 sGlobalSettings = [[NSMutableDictionary alloc] init];
547 [defaults setValue:sGlobalSettings forKey:@"settings"];
548 } else {
549 /* Make it mutable recursively */
550 sGlobalSettings = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)sGlobalSettings, kCFPropertyListMutableContainers);
551 }
552 }
553 if (keyPath != nil)
554 return [sGlobalSettings valueForKeyPath:keyPath];
555 else return nil;
556 }
557
558 void
559 MyAppCallback_setObjectGlobalSettings(id keyPath, id value)
560 {
561 id dic, obj, key;
562 const char *p, *pp;
563 p = [keyPath UTF8String];
564 if (sGlobalSettings == nil)
565 obj = MyAppCallback_getObjectGlobalSettings(nil); /* Initialize sGlobalSettings */
566 dic = key = nil;
567 obj = sGlobalSettings;
568 while ((pp = strchr(p, '.')) != NULL) {
569 key = [NSString stringWithFormat:@"%.*s", (int)(pp - p), p];
570 dic = obj;
571 obj = [dic valueForKey:key];
572 if (obj == nil) {
573 obj = [NSMutableDictionary dictionary];
574 [dic setValue:obj forKey:key];
575 }
576 p = pp + 1;
577 }
578 /* Set the given object */
579 /* If the container (= obj) is not mutable, then make it mutable */
580 if (dic != nil && ![obj isKindOfClass:[NSMutableDictionary class]]) {
581 obj = [NSMutableDictionary dictionaryWithDictionary:obj];
582 [dic setValue:obj forKey:key];
583 }
584 key = [NSString stringWithUTF8String:p];
585 [obj setValue:value forKey:key];
586 }
587
588 const char *
589 MyAppCallback_getGlobalSettings(const char *key)
590 {
591 id obj = MyAppCallback_getObjectGlobalSettings([NSString stringWithUTF8String:key]);
592 if (obj != nil) {
593 if (![obj isKindOfClass:[NSString class]])
594 obj = [obj description];
595 return [obj UTF8String];
596 }
597 else return NULL;
598 }
599
600 void
601 MyAppCallback_setGlobalSettings(const char *key, const char *value)
602 {
603 MyAppCallback_setObjectGlobalSettings([NSString stringWithUTF8String:key], [NSString stringWithUTF8String:value]);
604 }
605
606 void
607 MyAppCallback_registerScriptMenu(const char *cmd, const char *title, int32_t validator)
608 {
609 MyAppController *cont = (MyAppController *)[NSApp delegate];
610 [cont registerScriptMenu: [NSString stringWithUTF8String: cmd]
611 withTitle: [NSString stringWithUTF8String: title]
612 validator: validator];
613 }
614
615 RubyValue
616 MyAppCallback_executeScriptFromFile(const char *cpath, int *status)
617 {
618 RubyValue retval;
619 NSString *fullpath, *cwd, *dir;
620 NSString *contents;
621 NSFileManager *manager = [NSFileManager defaultManager];
622
623 /* Standardizing the path */
624 fullpath = [NSString stringWithUTF8String: cpath];
625 cwd = [manager currentDirectoryPath];
626 if (cpath[0] != '/' && cpath[0] != '~')
627 fullpath = [NSString stringWithFormat: @"%@/%@", cwd, fullpath];
628 fullpath = [fullpath stringByStandardizingPath];
629
630 /* Move to the directory */
631 dir = [fullpath stringByDeletingLastPathComponent];
632 [manager changeCurrentDirectoryPath: dir];
633
634 /* Read the contents of the file */
635 contents = [NSString stringWithContentsOfFile: fullpath encoding: NSUTF8StringEncoding error: NULL];
636
637 /* Execute as a ruby script */
638 retval = Ruby_evalRubyScriptOnDocument([contents UTF8String], [(MyAppController *)[NSApp delegate] documentAtIndex: 0], status);
639
640 /* Restore the current directory */
641 [manager changeCurrentDirectoryPath: cwd];
642
643 return retval;
644 }
645
646 int
647 MyAppCallback_checkInterrupt(void)
648 {
649 MyAppController *cont = (MyAppController *)[NSApp delegate];
650 if (cont == nil)
651 return 0;
652 return [cont checkInterrupt];
653 }
654
655 int
656 MyAppCallback_showProgressPanel(const char *msg)
657 {
658 MyAppController *cont = (MyAppController *)[NSApp delegate];
659 if (cont == nil)
660 return 0;
661 if (msg == NULL)
662 msg = "Processing...";
663 return [cont showProgressPanel: [NSString stringWithUTF8String: msg]];
664 }
665
666 void
667 MyAppCallback_hideProgressPanel(void)
668 {
669 MyAppController *cont = (MyAppController *)[NSApp delegate];
670 [cont hideProgressPanel];
671 }
672
673 void
674 MyAppCallback_setProgressValue(double dval)
675 {
676 MyAppController *cont = (MyAppController *)[NSApp delegate];
677 [cont setProgressValue: dval];
678 }
679
680 void
681 MyAppCallback_setProgressMessage(const char *msg)
682 {
683 MyAppController *cont = (MyAppController *)[NSApp delegate];
684 [cont setProgressMessage: [NSString stringWithUTF8String: msg]];
685 }
686
687 int
688 MyAppCallback_messageBox(const char *message, const char *title, int flags, int icon)
689 {
690 NSString *btn1, *btn2;
691 NSAlert *alert;
692 int retval;
693 switch (flags & 3) {
694 case 0: case 1: btn1 = btn2 = nil; break;
695 case 2: btn1 = @"Cancel"; btn2 = nil; break;
696 case 3: btn1 = nil; btn2 = @"Cancel"; break;
697 }
698 alert = [NSAlert alertWithMessageText:[NSString stringWithUTF8String:title] defaultButton:btn1 alternateButton:btn2 otherButton:nil informativeTextWithFormat:@"%s", message];
699 retval = (int)[alert runModal];
700 if ((flags & 3) == 3)
701 return (retval == NSAlertDefaultReturn);
702 else return 1; /* Always OK, even if the message is "Cancel" */
703 }
704
705 void
706 MyAppCallback_startupMessage(const char *message, ...)
707 {
708 char *msg;
709 va_list ap;
710 va_start(ap, message);
711 if (message != NULL)
712 vasprintf(&msg, message, ap);
713 else msg = NULL;
714 [AboutWindowController setMessage:(msg == NULL ? nil : [NSString stringWithUTF8String:msg])];
715 if (msg != NULL)
716 free(msg);
717 }
718
719 #pragma mark ====== MIDI setup change notification ======
720
721 void
722 MDPlayerNotificationCallback(void)
723 {
724 MDPlayerReloadDeviceInformation();
725 [[NSNotificationCenter defaultCenter]
726 postNotificationName: MyAppControllerMIDISetupDidChangeNotification
727 object: [NSApp delegate] userInfo: nil];
728 }
729

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26