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