2 #define Marker FuckYouAppleAndYourLackOfNameSpaces
4 #include <gtkmm/button.h>
5 #include <gdk/gdkquartz.h>
7 #include "pbd/convert.h"
10 #include "ardour/audio_unit.h"
11 #include "ardour/debug.h"
12 #include "ardour/plugin_insert.h"
14 #undef check // stupid gtk, stupid apple
16 #include <gtkmm2ext/utils.h>
17 #include <gtkmm2ext/window_proxy.h>
19 #include "au_pluginui.h"
20 #include "gui_thread.h"
21 #include "processor_box.h"
23 #include "CAAudioUnit.h"
24 #include "CAComponent.h"
26 #import <AudioUnit/AUCocoaUIView.h>
27 #import <CoreAudioKit/AUGenericView.h>
33 #include "public_editor.h"
36 #include "gtk2ardour-config.h"
39 #define ArdourCloseComponent CloseComponent
41 #define ArdourCloseComponent AudioComponentInstanceDispose
43 using namespace ARDOUR;
45 using namespace Gtkmm2ext;
49 vector<string> AUPluginUI::automation_mode_strings;
51 static const gchar* _automation_mode_strings[] = {
60 dump_view_tree (NSView* view, int depth, int maxdepth)
62 NSArray* subviews = [view subviews];
63 unsigned long cnt = [subviews count];
65 for (int d = 0; d < depth; d++) {
68 NSRect frame = [view frame];
69 cerr << " view @ " << frame.origin.x << ", " << frame.origin.y
70 << ' ' << frame.size.width << " x " << frame.size.height
73 if (depth >= maxdepth) {
76 for (unsigned long i = 0; i < cnt; ++i) {
77 NSView* subview = [subviews objectAtIndex:i];
78 dump_view_tree (subview, depth+1, maxdepth);
82 @implementation NotificationObject
84 - (NotificationObject*) initWithPluginUI: (AUPluginUI*) apluginui andCocoaParent: (NSWindow*) cp andTopLevelParent: (NSWindow*) tlp
86 self = [ super init ];
89 plugin_ui = apluginui;
90 top_level_parent = tlp;
95 [[NSNotificationCenter defaultCenter]
97 selector:@selector(cocoaParentActivationHandler:)
98 name:NSWindowDidBecomeMainNotification
101 [[NSNotificationCenter defaultCenter]
103 selector:@selector(cocoaParentBecameKeyHandler:)
104 name:NSWindowDidBecomeKeyNotification
112 - (void)cocoaParentActivationHandler:(NSNotification *)notification
114 NSWindow* notification_window = (NSWindow *)[notification object];
116 if (top_level_parent == notification_window || cocoa_parent == notification_window) {
117 if ([notification_window isMainWindow]) {
118 plugin_ui->activate();
120 plugin_ui->deactivate();
125 - (void)cocoaParentBecameKeyHandler:(NSNotification *)notification
127 NSWindow* notification_window = (NSWindow *)[notification object];
129 if (top_level_parent == notification_window || cocoa_parent == notification_window) {
130 if ([notification_window isKeyWindow]) {
131 plugin_ui->activate();
133 plugin_ui->deactivate();
138 - (void)auViewResized:(NSNotification *)notification
140 (void) notification; // stop complaints about unusued argument
141 plugin_ui->cocoa_view_resized();
146 @implementation LiveResizeNotificationObject
148 - (LiveResizeNotificationObject*) initWithPluginUI: (AUPluginUI*) apluginui
150 self = [ super init ];
152 plugin_ui = apluginui;
158 - (void)windowWillStartLiveResizeHandler:(NSNotification*)notification
160 plugin_ui->start_live_resize ();
163 - (void)windowWillEndLiveResizeHandler:(NSNotification*)notification
165 plugin_ui->end_live_resize ();
169 AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
170 : PlugUIBase (insert)
171 , automation_mode_label (_("Automation"))
172 , preset_label (_("Presets"))
183 , in_live_resize (false)
184 , plugin_requested_resize (0)
190 if (automation_mode_strings.empty()) {
191 automation_mode_strings = I18N (_automation_mode_strings);
194 set_popdown_strings (automation_mode_selector, automation_mode_strings);
195 automation_mode_selector.set_active_text (automation_mode_strings.front());
197 if ((au = boost::dynamic_pointer_cast<AUPlugin> (insert->plugin())) == 0) {
198 error << _("unknown type of editor-supplying plugin (note: no AudioUnit support in this version of ardour)") << endmsg;
199 throw failed_constructor ();
202 /* stuff some stuff into the top of the window */
204 HBox* smaller_hbox = manage (new HBox);
206 smaller_hbox->set_spacing (6);
207 smaller_hbox->pack_start (preset_label, false, false, 4);
208 smaller_hbox->pack_start (_preset_modified, false, false);
209 smaller_hbox->pack_start (_preset_combo, false, false);
210 smaller_hbox->pack_start (add_button, false, false);
212 /* Ardour does not currently allow to overwrite existing presets
213 * see save_property_list() in audio_unit.cc
215 smaller_hbox->pack_start (save_button, false, false);
218 /* one day these might be useful with an AU plugin, but not yet */
219 smaller_hbox->pack_start (automation_mode_label, false, false);
220 smaller_hbox->pack_start (automation_mode_selector, false, false);
222 smaller_hbox->pack_start (reset_button, false, false);
223 smaller_hbox->pack_start (bypass_button, false, true);
225 VBox* v1_box = manage (new VBox);
226 VBox* v2_box = manage (new VBox);
228 v1_box->pack_start (*smaller_hbox, false, true);
229 v2_box->pack_start (focus_button, false, true);
231 top_box.set_homogeneous (false);
232 top_box.set_spacing (6);
233 top_box.set_border_width (6);
235 top_box.pack_end (*v2_box, false, false);
236 top_box.pack_end (*v1_box, false, false);
239 pack_start (top_box, false, false);
240 pack_start (low_box, true, true);
242 preset_label.show ();
243 _preset_combo.show ();
244 automation_mode_label.show ();
245 automation_mode_selector.show ();
246 bypass_button.show ();
254 _activating_from_app = false;
261 /* prefer cocoa, fall back to cocoa, but use carbon if its there */
263 if (test_cocoa_view_support()) {
264 create_cocoa_view ();
266 } else if (test_carbon_view_support()) {
267 create_carbon_view ();
270 create_cocoa_view ();
273 low_box.add_events (Gdk::VISIBILITY_NOTIFY_MASK | Gdk::EXPOSURE_MASK);
275 low_box.signal_realize().connect (mem_fun (this, &AUPluginUI::lower_box_realized));
276 low_box.signal_visibility_notify_event ().connect (mem_fun (this, &AUPluginUI::lower_box_visibility_notify));
278 low_box.signal_size_request ().connect (mem_fun (this, &AUPluginUI::lower_box_size_request));
279 low_box.signal_size_allocate ().connect (mem_fun (this, &AUPluginUI::lower_box_size_allocate));
280 low_box.signal_map ().connect (mem_fun (this, &AUPluginUI::lower_box_map));
281 low_box.signal_unmap ().connect (mem_fun (this, &AUPluginUI::lower_box_unmap));
282 low_box.signal_expose_event ().connect (mem_fun (this, &AUPluginUI::lower_box_expose));
286 AUPluginUI::~AUPluginUI ()
289 [[NSNotificationCenter defaultCenter] removeObserver:_notify];
292 if (_resize_notify) {
293 [[NSNotificationCenter defaultCenter] removeObserver:_resize_notify];
297 NSWindow* win = get_nswindow();
298 [win removeChildWindow:cocoa_parent];
303 /* not parented, just overlaid on top of our window */
304 DisposeWindow (carbon_window);
309 ArdourCloseComponent (editView);
313 /* remove whatever we packed into low_box so that GTK doesn't
317 [au_view removeFromSuperview];
322 AUPluginUI::test_carbon_view_support ()
327 carbon_descriptor.componentType = kAudioUnitCarbonViewComponentType;
328 carbon_descriptor.componentSubType = 'gnrc';
329 carbon_descriptor.componentManufacturer = 'appl';
330 carbon_descriptor.componentFlags = 0;
331 carbon_descriptor.componentFlagsMask = 0;
335 // ask the AU for its first editor component
337 err = AudioUnitGetPropertyInfo(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, &propertySize, NULL);
339 int nEditors = propertySize / sizeof(ComponentDescription);
340 ComponentDescription *editors = new ComponentDescription[nEditors];
341 err = AudioUnitGetProperty(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, editors, &propertySize);
343 // just pick the first one for now
344 carbon_descriptor = editors[0];
357 AUPluginUI::test_cocoa_view_support ()
360 Boolean isWritable = 0;
361 OSStatus err = AudioUnitGetPropertyInfo(*au->get_au(),
362 kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global,
363 0, &dataSize, &isWritable);
365 return dataSize > 0 && err == noErr;
369 AUPluginUI::plugin_class_valid (Class pluginClass)
371 if([pluginClass conformsToProtocol: @protocol(AUCocoaUIBase)]) {
372 if([pluginClass instancesRespondToSelector: @selector(interfaceVersion)] &&
373 [pluginClass instancesRespondToSelector: @selector(uiViewForAudioUnit:withSize:)]) {
381 AUPluginUI::create_cocoa_view ()
383 bool wasAbleToLoadCustomView = false;
384 AudioUnitCocoaViewInfo* cocoaViewInfo = NULL;
385 UInt32 numberOfClasses = 0;
388 NSString* factoryClassName = 0;
389 NSURL* CocoaViewBundlePath = NULL;
391 OSStatus result = AudioUnitGetPropertyInfo (*au->get_au(),
392 kAudioUnitProperty_CocoaUI,
393 kAudioUnitScope_Global,
398 numberOfClasses = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef);
400 // Does view have custom Cocoa UI?
402 if ((result == noErr) && (numberOfClasses > 0) ) {
404 DEBUG_TRACE(DEBUG::AudioUnits,
405 string_compose ( "based on %1, there are %2 cocoa UI classes\n", dataSize, numberOfClasses));
407 cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
409 if(AudioUnitGetProperty(*au->get_au(),
410 kAudioUnitProperty_CocoaUI,
411 kAudioUnitScope_Global,
414 &dataSize) == noErr) {
416 CocoaViewBundlePath = (NSURL *)cocoaViewInfo->mCocoaAUViewBundleLocation;
418 // we only take the first view in this example.
419 factoryClassName = (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
421 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("the factory name is %1 bundle is %2\n",
422 [factoryClassName UTF8String], CocoaViewBundlePath));
426 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("No cocoaUI property cocoaViewInfo = %1\n", cocoaViewInfo));
428 if (cocoaViewInfo != NULL) {
429 free (cocoaViewInfo);
430 cocoaViewInfo = NULL;
435 // [A] Show custom UI if view has it
437 if (CocoaViewBundlePath && factoryClassName) {
438 NSBundle *viewBundle = [NSBundle bundleWithPath:[CocoaViewBundlePath path]];
440 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("tried to create bundle, result = %1\n", viewBundle));
442 if (viewBundle == NULL) {
443 error << _("AUPluginUI: error loading AU view's bundle") << endmsg;
446 Class factoryClass = [viewBundle classNamed:factoryClassName];
447 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("tried to create factory class, result = %1\n", factoryClass));
449 error << _("AUPluginUI: error getting AU view's factory class from bundle") << endmsg;
453 // make sure 'factoryClass' implements the AUCocoaUIBase protocol
454 if (!plugin_class_valid (factoryClass)) {
455 error << _("AUPluginUI: U view's factory class does not properly implement the AUCocoaUIBase protocol") << endmsg;
459 id factory = [[[factoryClass alloc] init] autorelease];
460 if (factory == NULL) {
461 error << _("AUPluginUI: Could not create an instance of the AU view factory") << endmsg;
465 DEBUG_TRACE (DEBUG::AudioUnits, "got a factory instance\n");
468 au_view = [factory uiViewForAudioUnit:*au->get_au() withSize:NSZeroSize];
470 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("view created @ %1\n", au_view));
473 [CocoaViewBundlePath release];
476 for (i = 0; i < numberOfClasses; i++)
477 CFRelease(cocoaViewInfo->mCocoaAUViewClass[i]);
479 free (cocoaViewInfo);
481 wasAbleToLoadCustomView = true;
485 if (!wasAbleToLoadCustomView) {
486 // load generic Cocoa view
487 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("Loading generic view using %1 -> %2\n", au,
489 au_view = [[AUGenericView alloc] initWithAudioUnit:*au->get_au()];
490 DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("view created @ %1\n", au_view));
491 [(AUGenericView *)au_view setShowsExpertParameters:1];
494 // Get the initial size of the new AU View's frame
495 NSRect frame = [au_view frame];
496 min_width = req_width = frame.size.width;
497 min_height = req_height = frame.size.height;
499 resizable = [au_view autoresizingMask];
500 std::cerr << plugin->name() << " initial frame = " << [NSStringFromRect (frame) UTF8String] << " resizable ? " << resizable << std::endl;
502 low_box.queue_resize ();
508 AUPluginUI::update_view_size ()
510 last_au_frame = [au_view frame];
514 AUPluginUI::cocoa_view_resized ()
516 /* we can get here for two reasons:
518 1) the plugin window was resized by the user, a new size was
519 allocated to the window, ::update_view_size() was called, and we
520 explicitly/manually resized the AU NSView.
522 2) the plugin decided to resize itself (probably in response to user
523 action, but not in response to an actual window resize)
525 We only want to proceed with a window resizing in the second case.
528 if (in_live_resize) {
529 /* ::update_view_size() will be called at the right times and
530 * will update the view size. We don't need to anything while a
531 * live resize in underway.
536 if (plugin_requested_resize) {
537 /* we tried to change the plugin frame from inside this method
538 * (to adjust the origin), and the plugin changed its size
539 * again. Ignore this second call.
541 std::cerr << plugin->name() << " re-entrant call to cocoa_view_resized, ignored\n";
545 plugin_requested_resize = 1;
547 ProcessorWindowProxy* wp = insert->window_proxy();
549 /* Once a plugin has requested a resize of its own window, do
550 * NOT save the window. The user may save state with the plugin
551 * editor expanded to show "extra detail" - the plugin will not
552 * refill this space when the editor is first
553 * instantiated. Leaving the window in the "too big" state
554 * cannot be recovered from.
556 * The window will be sized to fit the plugin's own request. Done.
558 wp->set_state_mask (WindowProxy::Position);
561 NSRect new_frame = [au_view frame];
563 std::cerr << "Plugin " << plugin->name() << " requested update (prs now = " << plugin_requested_resize << ")\n";
564 std::cerr << "\tAU NSView frame : " << [ NSStringFromRect (new_frame) UTF8String] << std::endl;
565 std::cerr << "\tlast au frame : " << [ NSStringFromRect (last_au_frame) UTF8String] << std::endl;
567 /* from here on, we know that we've been called because the plugin
568 * decided to change the NSView frame itself.
571 /* step one: compute the change in the frame size.
574 float dy = new_frame.size.height - last_au_frame.size.height;
575 float dx = new_frame.size.width - last_au_frame.size.width;
577 NSWindow* window = get_nswindow ();
578 NSRect windowFrame= [window frame];
580 /* we want the top edge of the window to remain in the same place,
581 but the Cocoa/Quartz origin is at the lower left. So, when we make
582 the window larger, we will move it down, which means shifting the
583 origin toward (x,0). This will leave the top edge in the same place.
586 windowFrame.origin.y -= dy;
587 windowFrame.origin.x -= dx;
588 windowFrame.size.height += dy;
589 windowFrame.size.width += dx;
591 std::cerr << "\tChange size by " << dx << " x " << dy << std::endl;
593 NSUInteger old_auto_resize = [au_view autoresizingMask];
595 /* Stop the AU NSView from resizing itself *again* in response to
596 us changing the window size.
600 [au_view setAutoresizingMask:NSViewNotSizable];
602 /* Some stupid AU Views change the origin of the original AU View when
603 they are resized (I'm looking at you AUSampler). If the origin has
604 been moved, move it back.
607 if (last_au_frame.origin.x != new_frame.origin.x ||
608 last_au_frame.origin.y != new_frame.origin.y) {
609 new_frame.origin = last_au_frame.origin;
610 std::cerr << "Move AU NSView origin back to "
611 << new_frame.origin.x << ", " << new_frame.origin.y
613 [au_view setFrame:new_frame];
614 /* also be sure to redraw the topbox because this can
617 top_box.queue_draw ();
619 std::cerr << "No need to move origin, last au origin " << [NSStringFromPoint(last_au_frame.origin) UTF8String]
620 << " == new au origin " << [NSStringFromPoint(new_frame.origin) UTF8String]
624 /* this resizes the window. it will eventually trigger a new
625 * size_allocate event/callback, and we'll end up in
626 * ::update_view_size(). We want to stop that from doing anything,
627 * because we've already resized the window to fit the new new view,
628 * so there's no need to actually update the view size again.
631 [window setFrame:windowFrame display:1];
633 [au_view setAutoresizingMask:old_auto_resize];
635 /* keep a copy of the size of the AU NSView. We didn't set - the plugin did */
636 last_au_frame = new_frame;
637 min_width = req_width = new_frame.size.width;
638 min_height = req_height = new_frame.size.height;
640 plugin_requested_resize = 0;
644 AUPluginUI::create_carbon_view ()
648 ControlRef root_control;
650 Component editComponent = FindNextComponent(NULL, &carbon_descriptor);
652 OpenAComponent(editComponent, &editView);
654 error << _("AU Carbon view: cannot open AU Component") << endmsg;
658 Rect r = { 100, 100, 100, 100 };
659 WindowAttributes attr = WindowAttributes (kWindowStandardHandlerAttribute |
660 kWindowCompositingAttribute|
661 kWindowNoShadowAttribute|
662 kWindowNoTitleBarAttribute);
664 if ((err = CreateNewWindow(kUtilityWindowClass, attr, &r, &carbon_window)) != noErr) {
665 error << string_compose (_("AUPluginUI: cannot create carbon window (err: %1)"), err) << endmsg;
666 ArdourCloseComponent (editView);
670 if ((err = GetRootControl(carbon_window, &root_control)) != noErr) {
671 error << string_compose (_("AUPlugin: cannot get root control of carbon window (err: %1)"), err) << endmsg;
672 DisposeWindow (carbon_window);
673 ArdourCloseComponent (editView);
678 Float32Point location = { 0.0, 0.0 };
679 Float32Point size = { 0.0, 0.0 } ;
681 if ((err = AudioUnitCarbonViewCreate (editView, *au->get_au(), carbon_window, root_control, &location, &size, &viewPane)) != noErr) {
682 error << string_compose (_("AUPluginUI: cannot create carbon plugin view (err: %1)"), err) << endmsg;
683 DisposeWindow (carbon_window);
684 ArdourCloseComponent (editView);
691 GetControlBounds(viewPane, &bounds);
692 size.x = bounds.right-bounds.left;
693 size.y = bounds.bottom-bounds.top;
695 req_width = (int) (size.x + 0.5);
696 req_height = (int) (size.y + 0.5);
698 SizeWindow (carbon_window, req_width, req_height, true);
699 low_box.set_size_request (req_width, req_height);
703 error << _("AU Carbon GUI is not supported.") << endmsg;
709 AUPluginUI::get_nswindow ()
711 Gtk::Container* toplevel = get_toplevel();
713 if (!toplevel || !toplevel->is_toplevel()) {
714 error << _("AUPluginUI: no top level window!") << endmsg;
718 NSWindow* true_parent = gdk_quartz_window_get_nswindow (toplevel->get_window()->gobj());
721 error << _("AUPluginUI: no top level window!") << endmsg;
729 AUPluginUI::activate ()
732 ActivateWindow (carbon_window, TRUE);
737 AUPluginUI::deactivate ()
740 ActivateWindow (carbon_window, FALSE);
745 AUPluginUI::parent_carbon_window ()
748 NSWindow* win = get_nswindow ();
749 Rect windowStructureBoundsRect;
755 /* figure out where the cocoa parent window is in carbon-coordinate space, which
756 differs from both cocoa-coordinate space and GTK-coordinate space
759 GetWindowBounds((WindowRef) [win windowRef], kWindowStructureRgn, &windowStructureBoundsRect);
761 /* compute how tall the title bar is, because we have to offset the position of the carbon window
765 NSRect content_frame = [NSWindow contentRectForFrameRect:[win frame] styleMask:[win styleMask]];
766 NSRect wm_frame = [NSWindow frameRectForContentRect:content_frame styleMask:[win styleMask]];
768 int titlebar_height = wm_frame.size.height - content_frame.size.height;
770 int packing_extra = 6; // this is the total vertical packing in our top level window
772 /* move into position, based on parent window position */
773 MoveWindow (carbon_window,
774 windowStructureBoundsRect.left,
775 windowStructureBoundsRect.top + titlebar_height + top_box.get_height() + packing_extra,
777 ShowWindow (carbon_window);
779 // create the cocoa window for the carbon one and make it visible
780 cocoa_parent = [[NSWindow alloc] initWithWindowRef: carbon_window];
782 SetWindowActivationScope (carbon_window, kWindowActivationScopeNone);
784 _notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:cocoa_parent andTopLevelParent:win ];
786 [win addChildWindow:cocoa_parent ordered:NSWindowAbove];
787 [win setAutodisplay:1]; // turn of GTK stuff for this window
796 AUPluginUI::parent_cocoa_window ()
798 NSWindow* win = get_nswindow ();
804 //[win setAutodisplay:1]; // turn off GTK stuff for this window
806 NSView* view = gdk_quartz_window_get_nsview (low_box.get_window()->gobj());
807 [view addSubview:au_view];
809 /* this moves the AU NSView down and over to provide a left-hand margin
810 * and to clear the Ardour "task bar" (with plugin preset mgmt buttons,
811 * keyboard focus control, bypass etc).
815 gtk_widget_translate_coordinates(
816 GTK_WIDGET(low_box.gobj()),
817 GTK_WIDGET(low_box.get_parent()->gobj()),
819 [au_view setFrame:NSMakeRect(xx, yy, req_width, req_height)];
821 last_au_frame = [au_view frame];
822 // watch for size changes of the view
823 _notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:NULL andTopLevelParent:win ];
825 [[NSNotificationCenter defaultCenter] addObserver:_notify
826 selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
829 // catch notifications that live resizing is about to start
831 #if HAVE_COCOA_LIVE_RESIZING
832 _resize_notify = [ [ LiveResizeNotificationObject alloc] initWithPluginUI:this ];
834 [[NSNotificationCenter defaultCenter] addObserver:_resize_notify
835 selector:@selector(windowWillStartLiveResizeHandler:) name:NSWindowWillStartLiveResizeNotification
838 [[NSNotificationCenter defaultCenter] addObserver:_resize_notify
839 selector:@selector(windowWillEndLiveResizeHandler:) name:NSWindowDidEndLiveResizeNotification
842 /* No way before 10.6 to identify the start of a live resize (drag
843 * resize) without subclassing NSView and overriding two of its
844 * methods. Instead of that, we make the window non-resizable, thus
845 * ending confusion about whether or not resizes are plugin or user
846 * driven (they are always plugin-driven).
849 Gtk::Container* toplevel = get_toplevel();
854 if (toplevel && toplevel->is_toplevel()) {
855 toplevel->size_request (req);
856 toplevel->set_size_request (req.width, req.height);
857 dynamic_cast<Gtk::Window*>(toplevel)->set_resizable (false);
865 AUPluginUI::grab_focus()
868 [au_view becomeFirstResponder];
872 AUPluginUI::forward_key_event (GdkEventKey* ev)
874 NSEvent* nsevent = gdk_quartz_event_get_nsevent ((GdkEvent*)ev);
876 if (au_view && nsevent) {
878 /* filter on nsevent type here because GDK massages FlagsChanged
879 messages into GDK_KEY_{PRESS,RELEASE} but Cocoa won't
880 handle a FlagsChanged message as a keyDown or keyUp
883 if ([nsevent type] == NSKeyDown) {
884 [[[au_view window] firstResponder] keyDown:nsevent];
885 } else if ([nsevent type] == NSKeyUp) {
886 [[[au_view window] firstResponder] keyUp:nsevent];
887 } else if ([nsevent type] == NSFlagsChanged) {
888 [[[au_view window] firstResponder] flagsChanged:nsevent];
894 AUPluginUI::on_realize ()
898 /* our windows should not have that resize indicator */
900 NSWindow* win = get_nswindow ();
902 [win setShowsResizeIndicator:0];
907 AUPluginUI::lower_box_realized ()
910 parent_cocoa_window ();
911 } else if (carbon_window) {
912 parent_carbon_window ();
917 AUPluginUI::lower_box_visibility_notify (GdkEventVisibility* ev)
920 if (carbon_window && ev->state != GDK_VISIBILITY_UNOBSCURED) {
921 ShowWindow (carbon_window);
922 ActivateWindow (carbon_window, TRUE);
930 AUPluginUI::lower_box_map ()
933 [au_view setHidden:0];
938 AUPluginUI::lower_box_unmap ()
941 [au_view setHidden:1];
945 AUPluginUI::lower_box_size_request (GtkRequisition* requisition)
947 requisition->width = req_width;
948 requisition->height = req_height;
952 AUPluginUI::lower_box_size_allocate (Gtk::Allocation& allocation)
954 alo_width = allocation.get_width ();
955 alo_height = allocation.get_height ();
956 std::cerr << "lower box size reallocated to " << alo_width << " x " << alo_height << std::endl;
958 std::cerr << "low box draw (0, 0, " << alo_width << " x " << alo_height << ")\n";
959 low_box.queue_draw_area (0, 0, alo_width, alo_height);
963 AUPluginUI::lower_box_expose (GdkEventExpose* event)
965 std::cerr << "lower box expose: " << event->area.x << ", " << event->area.y
967 << event->area.width << " x " << event->area.height
969 << get_allocation().get_width() << " x " << get_allocation().get_height()
972 /* hack to keep ardour responsive
973 * some UIs (e.g Addictive Drums) completely hog the CPU
981 AUPluginUI::on_window_hide ()
985 HideWindow (carbon_window);
986 ActivateWindow (carbon_window, FALSE);
992 NSArray* wins = [NSApp windows];
993 for (uint32_t i = 0; i < [wins count]; i++) {
994 id win = [wins objectAtIndex:i];
1000 AUPluginUI::on_window_show (const string& /*title*/)
1002 /* this is idempotent so just call it every time we show the window */
1004 gtk_widget_realize (GTK_WIDGET(low_box.gobj()));
1009 if (carbon_window) {
1010 ShowWindow (carbon_window);
1011 ActivateWindow (carbon_window, TRUE);
1019 AUPluginUI::start_updating (GdkEventAny*)
1025 AUPluginUI::stop_updating (GdkEventAny*)
1031 create_au_gui (boost::shared_ptr<PluginInsert> plugin_insert, VBox** box)
1033 AUPluginUI* aup = new AUPluginUI (plugin_insert);
1039 AUPluginUI::start_live_resize ()
1041 std::cerr << "\n\n\n++++ Entering Live Resize\n";
1042 in_live_resize = true;
1046 AUPluginUI::end_live_resize ()
1048 std::cerr << "\n\n\n ----Leaving Live Resize\n";
1049 in_live_resize = false;