2 #define Marker FuckYouAppleAndYourLackOfNameSpaces
4 #include <gtkmm/button.h>
5 #include <gdk/gdkquartz.h>
11 #include "ardour/debug.h"
14 #undef check // stupid gtk, stupid apple
21 #include "appleutility/CAAudioUnit.h"
22 #include "appleutility/CAComponent.h"
24 #import <AudioUnit/AUCocoaUIView.h>
25 #import <CoreAudioKit/AUGenericView.h>
53 NSArray* subviews = [view subviews];
54 unsigned long cnt = [subviews count];
56 for (
int d = 0; d < depth; d++) {
59 NSRect frame = [view frame];
60 cerr <<
" view @ " << frame.origin.x <<
", " << frame.origin.y
61 <<
' ' << frame.size.width <<
" x " << frame.size.height
64 for (
unsigned long i = 0; i < cnt; ++i) {
65 NSView* subview = [subviews objectAtIndex:i];
74 self = [
super init ];
83 [[NSNotificationCenter defaultCenter] addObserver:self
84 selector:@selector(cocoaParentActivationHandler:)
85 name:NSWindowDidBecomeMainNotification
88 [[NSNotificationCenter defaultCenter] addObserver:self
89 selector:@selector(cocoaParentBecameKeyHandler:)
90 name:NSWindowDidBecomeKeyNotification
98 - (void)cocoaParentActivationHandler:(NSNotification *)notification
100 NSWindow* notification_window = (NSWindow *)[notification
object];
103 if ([notification_window isMainWindow]) {
111 - (void)cocoaParentBecameKeyHandler:(NSNotification *)notification
113 NSWindow* notification_window = (NSWindow *)[notification
object];
116 if ([notification_window isKeyWindow]) {
124 - (void)auViewResized:(NSNotification *)notification
134 , automation_mode_label (
_(
"Automation"))
135 , preset_label (
_(
"Presets"))
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;
152 HBox* smaller_hbox = manage (
new HBox);
154 smaller_hbox->set_spacing (6);
155 smaller_hbox->pack_start (
preset_label,
false,
false, 4);
158 smaller_hbox->pack_start (
add_button,
false,
false);
163 smaller_hbox->pack_start (
save_button,
false,
false);
173 VBox* v1_box = manage (
new VBox);
174 VBox* v2_box = manage (
new VBox);
176 v1_box->pack_start (*smaller_hbox,
false,
true);
179 top_box.set_homogeneous (
false);
183 top_box.pack_end (*v2_box,
false,
false);
184 top_box.pack_end (*v1_box,
false,
false);
187 pack_start (
top_box,
false,
false);
188 pack_start (
low_box,
false,
false);
221 low_box.add_events(Gdk::VISIBILITY_NOTIFY_MASK);
230 [[NSNotificationCenter defaultCenter] removeObserver:_notify];
235 [win removeChildWindow:cocoa_parent];
274 err = AudioUnitGetPropertyInfo(*
au->
get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, &propertySize, NULL);
276 int nEditors = propertySize /
sizeof(ComponentDescription);
277 ComponentDescription *editors =
new ComponentDescription[nEditors];
278 err = AudioUnitGetProperty(*
au->
get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, editors, &propertySize);
297 Boolean isWritable = 0;
298 OSStatus err = AudioUnitGetPropertyInfo(*
au->
get_au(),
299 kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global,
300 0, &dataSize, &isWritable);
302 return dataSize > 0 && err == noErr;
308 if([pluginClass conformsToProtocol:
@protocol(AUCocoaUIBase)]) {
309 if([pluginClass instancesRespondToSelector:
@selector(interfaceVersion)] &&
310 [pluginClass instancesRespondToSelector:
@selector(uiViewForAudioUnit:withSize:)]) {
320 bool wasAbleToLoadCustomView =
false;
321 AudioUnitCocoaViewInfo* cocoaViewInfo = NULL;
322 UInt32 numberOfClasses = 0;
325 NSString* factoryClassName = 0;
326 NSURL* CocoaViewBundlePath = NULL;
328 OSStatus result = AudioUnitGetPropertyInfo (*
au->
get_au(),
329 kAudioUnitProperty_CocoaUI,
330 kAudioUnitScope_Global,
335 numberOfClasses = (dataSize -
sizeof(CFURLRef)) /
sizeof(CFStringRef);
339 if ((result == noErr) && (numberOfClasses > 0) ) {
342 string_compose (
"based on %1, there are %2 cocoa UI classes\n", dataSize, numberOfClasses));
344 cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
346 if(AudioUnitGetProperty(*
au->
get_au(),
347 kAudioUnitProperty_CocoaUI,
348 kAudioUnitScope_Global,
351 &dataSize) == noErr) {
353 CocoaViewBundlePath = (NSURL *)cocoaViewInfo->mCocoaAUViewBundleLocation;
356 factoryClassName = (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
359 [factoryClassName UTF8String], CocoaViewBundlePath));
365 if (cocoaViewInfo != NULL) {
366 free (cocoaViewInfo);
367 cocoaViewInfo = NULL;
374 if (CocoaViewBundlePath && factoryClassName) {
375 NSBundle *viewBundle = [NSBundle bundleWithPath:[CocoaViewBundlePath path]];
379 if (viewBundle == NULL) {
380 error <<
_(
"AUPluginUI: error loading AU view's bundle") <<
endmsg;
383 Class factoryClass = [viewBundle classNamed:factoryClassName];
386 error <<
_(
"AUPluginUI: error getting AU view's factory class from bundle") <<
endmsg;
392 error <<
_(
"AUPluginUI: U view's factory class does not properly implement the AUCocoaUIBase protocol") <<
endmsg;
396 id factory = [[[factoryClass alloc] init] autorelease];
397 if (factory == NULL) {
398 error <<
_(
"AUPluginUI: Could not create an instance of the AU view factory") <<
endmsg;
405 au_view = [factory uiViewForAudioUnit:*au->get_au() withSize:NSZeroSize];
410 [CocoaViewBundlePath release];
413 for (i = 0; i < numberOfClasses; i++)
414 CFRelease(cocoaViewInfo->mCocoaAUViewClass[i]);
416 free (cocoaViewInfo);
418 wasAbleToLoadCustomView =
true;
422 if (!wasAbleToLoadCustomView) {
426 au_view = [[AUGenericView alloc] initWithAudioUnit:*au->get_au()];
436 low_box.set_size_request (rect.size.width, rect.size.height);
445 NSRect windowFrame= [window frame];
446 NSRect new_frame = [
au_view frame];
448 float dy =
last_au_frame.size.height - new_frame.size.height;
451 windowFrame.origin.y += dy;
452 windowFrame.origin.x += dx;
453 windowFrame.size.height -= dy;
454 windowFrame.size.width -= dx;
456 [[NSNotificationCenter defaultCenter] removeObserver:_notify
457 name:NSViewFrameDidChangeNotification
460 NSUInteger old_auto_resize = [
au_view autoresizingMask];
462 [
au_view setAutoresizingMask:NSViewNotSizable];
463 [window setFrame:windowFrame display:1];
480 [
au_view setAutoresizingMask:old_auto_resize];
482 [[NSNotificationCenter defaultCenter] addObserver:_notify
483 selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
494 ControlRef root_control;
498 OpenAComponent(editComponent, &
editView);
500 error <<
_(
"AU Carbon view: cannot open AU Component") <<
endmsg;
504 Rect r = { 100, 100, 100, 100 };
505 WindowAttributes attr = WindowAttributes (kWindowStandardHandlerAttribute |
506 kWindowCompositingAttribute|
507 kWindowNoShadowAttribute|
508 kWindowNoTitleBarAttribute);
510 if ((err = CreateNewWindow(kUtilityWindowClass, attr, &r, &
carbon_window)) != noErr) {
516 if ((err = GetRootControl(
carbon_window, &root_control)) != noErr) {
524 Float32Point location = { 0.0, 0.0 };
525 Float32Point size = { 0.0, 0.0 } ;
537 GetControlBounds(viewPane, &bounds);
538 size.x = bounds.right-bounds.left;
539 size.y = bounds.bottom-bounds.top;
549 error <<
_(
"AU Carbon GUI is not supported.") <<
endmsg;
557 Gtk::Container* toplevel = get_toplevel();
559 if (!toplevel || !toplevel->is_toplevel()) {
560 error <<
_(
"AUPluginUI: no top level window!") <<
endmsg;
564 NSWindow* true_parent = gdk_quartz_window_get_nswindow (toplevel->get_window()->gobj());
567 error <<
_(
"AUPluginUI: no top level window!") <<
endmsg;
595 Rect windowStructureBoundsRect;
601 Gtk::Container* toplevel = get_toplevel();
603 if (!toplevel || !toplevel->is_toplevel()) {
604 error <<
_(
"AUPluginUI: no top level window!") <<
endmsg;
612 GetWindowBounds((WindowRef) [win windowRef], kWindowStructureRgn, &windowStructureBoundsRect);
618 NSRect content_frame = [NSWindow contentRectForFrameRect:[win frame] styleMask:[win styleMask]];
619 NSRect wm_frame = [NSWindow frameRectForContentRect:content_frame styleMask:[win styleMask]];
621 int titlebar_height = wm_frame.size.height - content_frame.size.height;
623 int packing_extra = 6;
627 windowStructureBoundsRect.left,
628 windowStructureBoundsRect.top + titlebar_height +
top_box.get_height() + packing_extra,
633 cocoa_parent = [[NSWindow alloc] initWithWindowRef: carbon_window];
635 SetWindowActivationScope (
carbon_window, kWindowActivationScopeNone);
639 [win addChildWindow:cocoa_parent ordered:NSWindowAbove];
640 [win setAutodisplay:1];
657 [win setAutodisplay:1];
659 Gtk::Container* toplevel = get_toplevel();
661 if (!toplevel || !toplevel->is_toplevel()) {
662 error <<
_(
"AUPluginUI: no top level window!") <<
endmsg;
666 NSView* view = gdk_quartz_window_get_nsview (get_toplevel()->get_window()->gobj());
667 GtkRequisition a =
top_box.size_request ();
671 const int spacing = 6;
674 NSPoint
origin = { spacing + pad,
static_cast<CGFloat
> (a.height) + (2 * spacing) + pad };
676 [
au_view setFrameOrigin:origin];
677 [view addSubview:au_view positioned:NSWindowBelow relativeTo:NULL];
685 [[NSNotificationCenter defaultCenter] addObserver:_notify
686 selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
696 [
au_view becomeFirstResponder];
702 NSEvent* nsevent = gdk_quartz_event_get_nsevent ((GdkEvent*)ev);
711 if ([nsevent type] == NSKeyDown) {
712 [[[
au_view window] firstResponder] keyDown:nsevent];
713 }
else if ([nsevent type] == NSKeyUp) {
714 [[[
au_view window] firstResponder] keyUp:nsevent];
715 }
else if ([nsevent type] == NSFlagsChanged) {
716 [[[
au_view window] firstResponder] flagsChanged:nsevent];
730 [win setShowsResizeIndicator:0];
748 if (
carbon_window && ev->state != GDK_VISIBILITY_UNOBSCURED) {
769 NSArray* wins = [NSApp windows];
770 for (uint32_t i = 0; i < [wins count]; i++) {
771 id win = [wins objectAtIndex:i];
781 gtk_widget_realize (GTK_WIDGET(
low_box.gobj()));
AudioUnitCarbonView editView
void cocoa_view_resized()
PlugUIBase * create_au_gui(boost::shared_ptr< PluginInsert > plugin_insert, VBox **box)
NotificationObject * _notify
static void dump_view_tree(NSView *view, int depth)
AUPluginUI(boost::shared_ptr< ARDOUR::PluginInsert >)
ArdourDropdown _preset_combo
int parent_cocoa_window()
LIBPBD_API Transmitter error
NSWindow * get_nswindow()
NSWindow * top_level_parent
std::ostream & endmsg(std::ostream &ostr)
LIBGTKMM2EXT_API void set_popdown_strings(Gtk::ComboBoxText &, const std::vector< std::string > &)
boost::shared_ptr< Plugin > plugin(uint32_t num=0) const
bool test_cocoa_view_support()
ArdourButton bypass_button
static std::vector< std::string > automation_mode_strings
Gtk::EventBox focus_button
bool _activating_from_app
boost::shared_ptr< ARDOUR::AUPlugin > au
ComponentDescription carbon_descriptor
#define DEBUG_TRACE(bits, str)
Gtk::Label automation_mode_label
bool start_updating(GdkEventAny *)
bool lower_box_visibility_notify(GdkEventVisibility *)
static const gchar * _automation_mode_strings[]
bool stop_updating(GdkEventAny *)
boost::shared_ptr< CAAudioUnit > get_au()
void forward_key_event(GdkEventKey *)
bool plugin_class_valid(Class pluginClass)
int parent_carbon_window()
LIBARDOUR_API uint64_t AudioUnits
Gtk::ComboBoxText automation_mode_selector
Gtk::Label _preset_modified
bool on_window_show(const std::string &)
ArdourButton reset_button
std::string string_compose(const std::string &fmt, const T1 &o1)
bool test_carbon_view_support()
void lower_box_realized()