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