Fix warnings.
[ardour.git] / gtk2_ardour / au_pluginui.mm
1 #undef  Marker
2 #define Marker FuckYouAppleAndYourLackOfNameSpaces
3
4 #include <gtkmm/button.h>
5 #include <gdk/gdkquartz.h>
6
7 #include "pbd/convert.h"
8 #include "pbd/error.h"
9
10 #include "ardour/audio_unit.h"
11 #include "ardour/debug.h"
12 #include "ardour/plugin_insert.h"
13
14 #undef check // stupid gtk, stupid apple
15
16 #include <gtkmm2ext/utils.h>
17
18 #include "au_pluginui.h"
19 #include "gui_thread.h"
20
21 #include "appleutility/CAAudioUnit.h"
22 #include "appleutility/CAComponent.h"
23
24 #import <AudioUnit/AUCocoaUIView.h>
25 #import <CoreAudioKit/AUGenericView.h>
26
27 #undef Marker
28
29 #include "keyboard.h"
30 #include "utils.h"
31 #include "public_editor.h"
32 #include "i18n.h"
33
34 using namespace ARDOUR;
35 using namespace Gtk;
36 using namespace Gtkmm2ext;
37 using namespace std;
38 using namespace PBD;
39
40 vector<string> AUPluginUI::automation_mode_strings;
41
42 static const gchar* _automation_mode_strings[] = {
43         X_("Manual"),
44         X_("Play"),
45         X_("Write"),
46         X_("Touch"),
47         0
48 };
49
50 static void
51 dump_view_tree (NSView* view, int depth)
52 {
53         NSArray* subviews = [view subviews];
54         unsigned long cnt = [subviews count];
55
56         for (int d = 0; d < depth; d++) {
57                 cerr << '\t';
58         }
59         NSRect frame = [view frame];
60         cerr << " view @ " <<  frame.origin.x << ", " << frame.origin.y
61              << ' ' << frame.size.width << " x " << frame.size.height
62              << endl;
63         
64         for (unsigned long i = 0; i < cnt; ++i) {
65                 NSView* subview = [subviews objectAtIndex:i];
66                 dump_view_tree (subview, depth+1);
67         }
68 }
69
70 @implementation NotificationObject
71
72 - (NotificationObject*) initWithPluginUI: (AUPluginUI*) apluginui andCocoaParent: (NSWindow*) cp andTopLevelParent: (NSWindow*) tlp
73 {
74         self = [ super init ];
75
76         if (self) {
77                 plugin_ui = apluginui; 
78                 top_level_parent = tlp;
79                 
80                 if (cp) {
81                         cocoa_parent = cp;
82                         
83                         [[NSNotificationCenter defaultCenter] addObserver:self
84                          selector:@selector(cocoaParentActivationHandler:)
85                          name:NSWindowDidBecomeMainNotification
86                          object:NULL];
87                         
88                         [[NSNotificationCenter defaultCenter] addObserver:self
89                          selector:@selector(cocoaParentBecameKeyHandler:)
90                          name:NSWindowDidBecomeKeyNotification
91                          object:NULL];
92                 }
93         }
94
95         return self;
96 }
97                 
98 - (void)cocoaParentActivationHandler:(NSNotification *)notification
99 {
100         NSWindow* notification_window = (NSWindow *)[notification object];
101
102         if (top_level_parent == notification_window || cocoa_parent == notification_window) {
103                 if ([notification_window isMainWindow]) {
104                         plugin_ui->activate();
105                 } else {
106                         plugin_ui->deactivate();
107                 }
108         } 
109 }
110
111 - (void)cocoaParentBecameKeyHandler:(NSNotification *)notification
112 {
113         NSWindow* notification_window = (NSWindow *)[notification object];
114
115         if (top_level_parent == notification_window || cocoa_parent == notification_window) {
116                 if ([notification_window isKeyWindow]) {
117                         plugin_ui->activate();
118                 } else {
119                         plugin_ui->deactivate();
120                 }
121         } 
122 }
123
124 - (void)auViewResized:(NSNotification *)notification
125 {
126         (void) notification; // stop complaints about unusued argument
127         plugin_ui->cocoa_view_resized();
128 }
129
130 @end
131
132 AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
133         : PlugUIBase (insert)
134         , automation_mode_label (_("Automation"))
135         , preset_label (_("Presets"))
136         
137 {
138         if (automation_mode_strings.empty()) {
139                 automation_mode_strings = I18N (_automation_mode_strings);
140         }
141         
142         set_popdown_strings (automation_mode_selector, automation_mode_strings);
143         automation_mode_selector.set_active_text (automation_mode_strings.front());
144
145         if ((au = boost::dynamic_pointer_cast<AUPlugin> (insert->plugin())) == 0) {
146                 error << _("unknown type of editor-supplying plugin (note: no AudioUnit support in this version of ardour)") << endmsg;
147                 throw failed_constructor ();
148         }
149
150         /* stuff some stuff into the top of the window */
151
152         HBox* smaller_hbox = manage (new HBox);
153
154         smaller_hbox->set_spacing (6);
155         smaller_hbox->pack_start (preset_label, false, false, 4);
156         smaller_hbox->pack_start (_preset_combo, false, false);
157         smaller_hbox->pack_start (save_button, false, false);
158 #if 0
159         /* one day these might be useful with an AU plugin, but not yet */
160         smaller_hbox->pack_start (automation_mode_label, false, false);
161         smaller_hbox->pack_start (automation_mode_selector, false, false);
162 #endif
163         smaller_hbox->pack_start (bypass_button, false, true);
164
165         VBox* v1_box = manage (new VBox);
166         VBox* v2_box = manage (new VBox);
167
168         v1_box->pack_start (*smaller_hbox, false, true);
169         v2_box->pack_start (focus_button, false, true);
170
171         top_box.set_homogeneous (false);
172         top_box.set_spacing (6);
173         top_box.set_border_width (6);
174
175         top_box.pack_end (*v2_box, false, false);
176         top_box.pack_end (*v1_box, false, false);
177
178         set_spacing (6);
179         pack_start (top_box, false, false);
180         pack_start (low_box, false, false);
181
182         preset_label.show ();
183         _preset_combo.show ();
184         automation_mode_label.show ();
185         automation_mode_selector.show ();
186         bypass_button.show ();
187         top_box.show ();
188         low_box.show ();
189
190         cocoa_parent = 0;
191         cocoa_window = 0;
192
193 #ifdef WITH_CARBBON
194         _activating_from_app = false;
195         _notify = 0;
196         au_view = 0;
197         editView = 0;
198         carbon_window = 0;
199 #endif
200
201         /* prefer cocoa, fall back to cocoa, but use carbon if its there */
202
203         if (test_cocoa_view_support()) {
204                 create_cocoa_view ();
205 #ifdef WITH_CARBON
206         } else if (test_carbon_view_support()) {
207                 create_carbon_view ();
208 #endif
209         } else {
210                 create_cocoa_view ();
211         }
212
213         low_box.signal_realize().connect (mem_fun (this, &AUPluginUI::lower_box_realized));
214 }
215
216 AUPluginUI::~AUPluginUI ()
217 {
218         if (_notify) {
219                 [[NSNotificationCenter defaultCenter] removeObserver:_notify];
220         }
221
222         if (cocoa_parent) {
223                 NSWindow* win = get_nswindow();
224                 [win removeChildWindow:cocoa_parent];
225         } 
226
227 #ifdef WITH_CARBON
228         if (carbon_window) {
229                 /* not parented, just overlaid on top of our window */
230                 DisposeWindow (carbon_window);
231         }
232 #endif
233
234         if (editView) {
235                 CloseComponent (editView);
236         }
237
238         if (au_view) {
239                 /* remove whatever we packed into low_box so that GTK doesn't
240                    mess with it.
241                 */
242
243                 [au_view removeFromSuperview];
244         }
245 }
246
247 bool
248 AUPluginUI::test_carbon_view_support ()
249 {
250 #ifdef WITH_CARBON
251         bool ret = false;
252         
253         carbon_descriptor.componentType = kAudioUnitCarbonViewComponentType;
254         carbon_descriptor.componentSubType = 'gnrc';
255         carbon_descriptor.componentManufacturer = 'appl';
256         carbon_descriptor.componentFlags = 0;
257         carbon_descriptor.componentFlagsMask = 0;
258         
259         OSStatus err;
260
261         // ask the AU for its first editor component
262         UInt32 propertySize;
263         err = AudioUnitGetPropertyInfo(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, &propertySize, NULL);
264         if (!err) {
265                 int nEditors = propertySize / sizeof(ComponentDescription);
266                 ComponentDescription *editors = new ComponentDescription[nEditors];
267                 err = AudioUnitGetProperty(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, editors, &propertySize);
268                 if (!err) {
269                         // just pick the first one for now
270                         carbon_descriptor = editors[0];
271                         ret = true;
272                 }
273                 delete[] editors;
274         }
275
276         return ret;
277 #else
278         return false;
279 #endif
280 }
281         
282 bool
283 AUPluginUI::test_cocoa_view_support ()
284 {
285         UInt32 dataSize   = 0;
286         Boolean isWritable = 0;
287         OSStatus err = AudioUnitGetPropertyInfo(*au->get_au(),
288                                                 kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global,
289                                                 0, &dataSize, &isWritable);
290         
291         return dataSize > 0 && err == noErr;
292 }
293
294 bool
295 AUPluginUI::plugin_class_valid (Class pluginClass)
296 {
297         if([pluginClass conformsToProtocol: @protocol(AUCocoaUIBase)]) {
298                 if([pluginClass instancesRespondToSelector: @selector(interfaceVersion)] &&
299                    [pluginClass instancesRespondToSelector: @selector(uiViewForAudioUnit:withSize:)]) {
300                                 return true;
301                 }
302         }
303         return false;
304 }
305
306 int
307 AUPluginUI::create_cocoa_view ()
308 {
309         bool wasAbleToLoadCustomView = false;
310         AudioUnitCocoaViewInfo* cocoaViewInfo = NULL;
311         UInt32               numberOfClasses = 0;
312         UInt32     dataSize;
313         Boolean    isWritable;
314         NSString*           factoryClassName = 0;
315         NSURL*              CocoaViewBundlePath = NULL;
316
317         OSStatus result = AudioUnitGetPropertyInfo (*au->get_au(),
318                                                     kAudioUnitProperty_CocoaUI,
319                                                     kAudioUnitScope_Global, 
320                                                     0,
321                                                     &dataSize,
322                                                     &isWritable );
323
324         numberOfClasses = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef);
325
326         // Does view have custom Cocoa UI?
327         
328         if ((result == noErr) && (numberOfClasses > 0) ) {
329
330                 DEBUG_TRACE(DEBUG::AudioUnits,
331                             string_compose ( "based on %1, there are %2 cocoa UI classes\n", dataSize, numberOfClasses));
332
333                 cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
334
335                 if(AudioUnitGetProperty(*au->get_au(),
336                                         kAudioUnitProperty_CocoaUI,
337                                         kAudioUnitScope_Global,
338                                         0,
339                                         cocoaViewInfo,
340                                         &dataSize) == noErr) {
341
342                         CocoaViewBundlePath     = (NSURL *)cocoaViewInfo->mCocoaAUViewBundleLocation;
343                                 
344                         // we only take the first view in this example.
345                         factoryClassName        = (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
346                         
347                         DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("the factory name is %1 bundle is %2\n",
348                                                                         [factoryClassName UTF8String], CocoaViewBundlePath));
349                         
350                 } else {
351
352                         DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("No cocoaUI property cocoaViewInfo = %1\n", cocoaViewInfo));
353
354                         if (cocoaViewInfo != NULL) {
355                                 free (cocoaViewInfo);
356                                 cocoaViewInfo = NULL;
357                         }
358                 }
359         }
360
361         // [A] Show custom UI if view has it
362
363         if (CocoaViewBundlePath && factoryClassName) {
364                 NSBundle *viewBundle    = [NSBundle bundleWithPath:[CocoaViewBundlePath path]];
365
366                 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("tried to create bundle, result = %1\n", viewBundle));
367
368                 if (viewBundle == NULL) {
369                         error << _("AUPluginUI: error loading AU view's bundle") << endmsg;
370                         return -1;
371                 } else {
372                         Class factoryClass = [viewBundle classNamed:factoryClassName];
373                         DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("tried to create factory class, result = %1\n", factoryClass));
374                         if (!factoryClass) {
375                                 error << _("AUPluginUI: error getting AU view's factory class from bundle") << endmsg;
376                                 return -1;
377                         }
378                         
379                         // make sure 'factoryClass' implements the AUCocoaUIBase protocol
380                         if (!plugin_class_valid (factoryClass)) {
381                                 error << _("AUPluginUI: U view's factory class does not properly implement the AUCocoaUIBase protocol") << endmsg;
382                                 return -1;
383                         }
384                         // make a factory
385                         id factory = [[[factoryClass alloc] init] autorelease];
386                         if (factory == NULL) {
387                                 error << _("AUPluginUI: Could not create an instance of the AU view factory") << endmsg;
388                                 return -1;
389                         }
390
391                         DEBUG_TRACE (DEBUG::AudioUnits, "got a factory instance\n");
392
393                         // make a view
394                         au_view = [factory uiViewForAudioUnit:*au->get_au() withSize:NSZeroSize];
395
396                         DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("view created @ %1\n", au_view));
397                         
398                         // cleanup
399                         [CocoaViewBundlePath release];
400                         if (cocoaViewInfo) {
401                                 UInt32 i;
402                                 for (i = 0; i < numberOfClasses; i++)
403                                         CFRelease(cocoaViewInfo->mCocoaAUViewClass[i]);
404                                 
405                                 free (cocoaViewInfo);
406                         }
407                         wasAbleToLoadCustomView = true;
408                 }
409         }
410
411         if (!wasAbleToLoadCustomView) {
412                 // load generic Cocoa view
413                 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("Loading generic view using %1 -> %2\n", au,
414                                                                 au->get_au()));
415                 au_view = [[AUGenericView alloc] initWithAudioUnit:*au->get_au()];
416                 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("view created @ %1\n", au_view));
417                 [(AUGenericView *)au_view setShowsExpertParameters:1];
418         }
419
420         // Get the initial size of the new AU View's frame 
421         
422         NSRect rect = [au_view frame];
423         prefheight = rect.size.height;
424         prefwidth = rect.size.width;
425         low_box.set_size_request (rect.size.width, rect.size.height);
426
427         return 0;
428 }
429
430 void
431 AUPluginUI::cocoa_view_resized ()
432 {
433         NSWindow* window = get_nswindow ();
434         NSRect windowFrame= [window frame];
435         NSRect new_frame = [au_view frame];
436
437         float dy = last_au_frame.size.height - new_frame.size.height;
438         float dx = last_au_frame.size.width - new_frame.size.width;
439
440         windowFrame.origin.y    += dy;
441         windowFrame.origin.x    += dx;
442         windowFrame.size.height -= dy;
443         windowFrame.size.width  -= dx;
444         
445         [[NSNotificationCenter defaultCenter] removeObserver:_notify
446          name:NSViewFrameDidChangeNotification 
447          object:au_view];
448
449         NSUInteger old_auto_resize = [au_view autoresizingMask];
450
451         [au_view setAutoresizingMask:NSViewNotSizable];
452         [window setFrame:windowFrame display:1];
453
454         /* Some stupid AU Views change the origin of the original AU View
455            when they are resized (I'm looking at you AUSampler). If the origin
456            has been moved, move it back.
457         */
458
459         if (last_au_frame.origin.x != new_frame.origin.x ||
460             last_au_frame.origin.y != new_frame.origin.y) {
461                 new_frame.origin = last_au_frame.origin;
462                 [au_view setFrame:new_frame];
463                 /* also be sure to redraw the topbox because this can
464                    also go wrong.
465                  */
466                 top_box.queue_draw ();
467         }
468
469         [au_view setAutoresizingMask:old_auto_resize];
470
471         [[NSNotificationCenter defaultCenter] addObserver:_notify
472          selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
473          object:au_view];
474
475         last_au_frame = new_frame;
476 }
477
478 int
479 AUPluginUI::create_carbon_view ()
480 {
481 #ifdef WITH_CARBON
482         OSStatus err;
483         ControlRef root_control;
484
485         Component editComponent = FindNextComponent(NULL, &carbon_descriptor);
486         
487         OpenAComponent(editComponent, &editView);
488         if (!editView) {
489                 error << _("AU Carbon view: cannot open AU Component") << endmsg;
490                 return -1;
491         }
492         
493         Rect r = { 100, 100, 100, 100 };
494         WindowAttributes attr = WindowAttributes (kWindowStandardHandlerAttribute |
495                                                   kWindowCompositingAttribute|
496                                                   kWindowNoShadowAttribute|
497                                                   kWindowNoTitleBarAttribute);
498
499         if ((err = CreateNewWindow(kDocumentWindowClass, attr, &r, &carbon_window)) != noErr) {
500                 error << string_compose (_("AUPluginUI: cannot create carbon window (err: %1)"), err) << endmsg;
501                 CloseComponent (editView);
502                 return -1;
503         }
504         
505         if ((err = GetRootControl(carbon_window, &root_control)) != noErr) {
506                 error << string_compose (_("AUPlugin: cannot get root control of carbon window (err: %1)"), err) << endmsg;
507                 DisposeWindow (carbon_window);
508                 CloseComponent (editView);
509                 return -1;
510         }
511
512         ControlRef viewPane;
513         Float32Point location  = { 0.0, 0.0 };
514         Float32Point size = { 0.0, 0.0 } ;
515
516         if ((err = AudioUnitCarbonViewCreate (editView, *au->get_au(), carbon_window, root_control, &location, &size, &viewPane)) != noErr) {
517                 error << string_compose (_("AUPluginUI: cannot create carbon plugin view (err: %1)"), err) << endmsg;
518                 DisposeWindow (carbon_window);
519                 CloseComponent (editView);
520                 return -1;
521         }
522
523         // resize window
524
525         Rect bounds;
526         GetControlBounds(viewPane, &bounds);
527         size.x = bounds.right-bounds.left;
528         size.y = bounds.bottom-bounds.top;
529
530         prefwidth = (int) (size.x + 0.5);
531         prefheight = (int) (size.y + 0.5);
532
533         SizeWindow (carbon_window, prefwidth, prefheight,  true);
534         low_box.set_size_request (prefwidth, prefheight);
535
536         return 0;
537 #else
538         error << _("AU Carbon GUI is not supported.") << endmsg;
539         return -1;
540 #endif
541 }
542
543 NSWindow*
544 AUPluginUI::get_nswindow ()
545 {
546         Gtk::Container* toplevel = get_toplevel();
547
548         if (!toplevel || !toplevel->is_toplevel()) {
549                 error << _("AUPluginUI: no top level window!") << endmsg;
550                 return 0;
551         }
552
553         NSWindow* true_parent = gdk_quartz_window_get_nswindow (toplevel->get_window()->gobj());
554
555         if (!true_parent) {
556                 error << _("AUPluginUI: no top level window!") << endmsg;
557                 return 0;
558         }
559
560         return true_parent;
561 }
562
563 void
564 AUPluginUI::activate ()
565 {
566 #ifdef WITH_CARBON
567         ActivateWindow (carbon_window, TRUE);
568 #endif
569 }
570
571 void
572 AUPluginUI::deactivate ()
573 {
574 #ifdef WITH_CARBON
575         ActivateWindow (carbon_window, FALSE);
576 #endif
577 }
578
579 int
580 AUPluginUI::parent_carbon_window ()
581 {
582 #ifdef WITH_CARBON
583         NSWindow* win = get_nswindow ();
584         Rect windowStructureBoundsRect;
585
586         if (!win) {
587                 return -1;
588         }
589
590         Gtk::Container* toplevel = get_toplevel();
591
592         if (!toplevel || !toplevel->is_toplevel()) {
593                 error << _("AUPluginUI: no top level window!") << endmsg;
594                 return -1;
595         }
596         
597         /* figure out where the cocoa parent window is in carbon-coordinate space, which
598            differs from both cocoa-coordinate space and GTK-coordinate space
599         */
600
601         GetWindowBounds((WindowRef) [win windowRef], kWindowStructureRgn, &windowStructureBoundsRect);
602
603         /* compute how tall the title bar is, because we have to offset the position of the carbon window
604            by that much.
605         */
606
607         NSRect content_frame = [NSWindow contentRectForFrameRect:[win frame] styleMask:[win styleMask]];
608         NSRect wm_frame = [NSWindow frameRectForContentRect:content_frame styleMask:[win styleMask]];
609
610         int titlebar_height = wm_frame.size.height - content_frame.size.height;
611
612         int packing_extra = 6; // this is the total vertical packing in our top level window
613
614         /* move into position, based on parent window position */
615         MoveWindow (carbon_window, 
616                     windowStructureBoundsRect.left, 
617                     windowStructureBoundsRect.top + titlebar_height + top_box.get_height() + packing_extra, 
618                     false);
619         ShowWindow (carbon_window);
620
621         // create the cocoa window for the carbon one and make it visible
622         cocoa_parent = [[NSWindow alloc] initWithWindowRef: carbon_window];
623
624         SetWindowActivationScope (carbon_window, kWindowActivationScopeNone);
625
626         _notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:cocoa_parent andTopLevelParent:win ]; 
627
628         [win addChildWindow:cocoa_parent ordered:NSWindowAbove];
629
630         return 0;
631 #else
632         return -1;
633 #endif
634 }       
635
636 int
637 AUPluginUI::parent_cocoa_window ()
638 {
639         NSWindow* win = get_nswindow ();
640
641         if (!win) {
642                 return -1;
643         }
644
645         [win setAutodisplay:1]; // turn of GTK stuff for this window
646
647         Gtk::Container* toplevel = get_toplevel();
648
649         if (!toplevel || !toplevel->is_toplevel()) {
650                 error << _("AUPluginUI: no top level window!") << endmsg;
651                 return -1;
652         }
653
654         NSView* view = gdk_quartz_window_get_nsview (get_toplevel()->get_window()->gobj());
655         GtkRequisition a = top_box.size_request ();
656
657         /* move the au_view down so that it doesn't overlap the top_box contents */
658
659         const int spacing = 6;  // main vbox spacing
660         const int pad     = 4;  // box pad
661
662         NSPoint origin = { spacing + pad, static_cast<CGFloat> (a.height) + (2 * spacing) + pad };
663
664         [au_view setFrameOrigin:origin];
665         [view addSubview:au_view positioned:NSWindowBelow relativeTo:NULL];
666
667         last_au_frame = [au_view frame];
668
669         // watch for size changes of the view
670
671         _notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:NULL andTopLevelParent:win ];
672
673         [[NSNotificationCenter defaultCenter] addObserver:_notify
674          selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
675          object:au_view];
676
677         return 0;
678 }
679
680 void
681 AUPluginUI::forward_key_event (GdkEventKey* ev)
682 {
683         NSEvent* nsevent = gdk_quartz_event_get_nsevent ((GdkEvent*)ev);
684
685         if (au_view && nsevent) {
686
687                 /* filter on nsevent type here because GDK massages FlagsChanged
688                    messages into GDK_KEY_{PRESS,RELEASE} but Cocoa won't
689                    handle a FlagsChanged message as a keyDown or keyUp
690                 */
691
692                 if ([nsevent type] == NSKeyDown) {
693                         [[[au_view window] firstResponder] keyDown:nsevent];
694                 } else if ([nsevent type] == NSKeyUp) {
695                         [[[au_view window] firstResponder] keyUp:nsevent];
696                 } else if ([nsevent type] == NSFlagsChanged) {
697                         [[[au_view window] firstResponder] flagsChanged:nsevent];
698                 }
699         }
700 }
701
702 void
703 AUPluginUI::on_realize ()
704 {
705         VBox::on_realize ();
706
707         /* our windows should not have that resize indicator */
708
709         NSWindow* win = get_nswindow ();
710         if (win) {
711                 [win setShowsResizeIndicator:0];
712         }
713 }
714
715 void
716 AUPluginUI::lower_box_realized ()
717 {
718         if (au_view) {
719                 parent_cocoa_window ();
720         } else if (carbon_window) {
721                 parent_carbon_window ();
722         }
723 }
724
725 void
726 AUPluginUI::on_window_hide ()
727 {
728 #ifdef WITH_CARBON
729         if (carbon_window) {
730                 HideWindow (carbon_window);
731                 ActivateWindow (carbon_window, FALSE);
732         }
733 #endif
734         hide_all ();
735         
736 #if 0
737         NSArray* wins = [NSApp windows];
738         for (uint32_t i = 0; i < [wins count]; i++) {
739                 id win = [wins objectAtIndex:i];
740         }
741 #endif
742 }
743
744 bool
745 AUPluginUI::on_window_show (const string& /*title*/)
746 {
747         /* this is idempotent so just call it every time we show the window */
748
749         gtk_widget_realize (GTK_WIDGET(low_box.gobj()));
750
751         show_all ();
752
753 #ifdef WITH_CARBON
754         if (carbon_window) {
755                 ShowWindow (carbon_window);
756                 ActivateWindow (carbon_window, TRUE);
757         }
758 #endif
759
760         return true;
761 }
762
763 bool
764 AUPluginUI::start_updating (GdkEventAny*)
765 {
766         return false;
767 }
768
769 bool
770 AUPluginUI::stop_updating (GdkEventAny*)
771 {
772         return false;
773 }
774
775 PlugUIBase*
776 create_au_gui (boost::shared_ptr<PluginInsert> plugin_insert, VBox** box)
777 {
778         AUPluginUI* aup = new AUPluginUI (plugin_insert);
779         (*box) = aup;
780         return aup;
781 }
782
783