From 80fa696564a2b261b6cf751ff61e4d885d3a2dc0 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 13 Nov 2016 16:32:30 +0100 Subject: basic Mac VST Cocoa UI support --- gtk2_ardour/instrument_selector.cc | 3 + gtk2_ardour/mac_vst_plugin_ui.h | 59 +++++++++++++++ gtk2_ardour/mac_vst_plugin_ui.mm | 151 +++++++++++++++++++++++++++++++++++++ gtk2_ardour/mixer_ui.cc | 3 + gtk2_ardour/plugin_selector.cc | 19 +++++ gtk2_ardour/plugin_selector.h | 1 + gtk2_ardour/plugin_ui.cc | 37 +++++++++ gtk2_ardour/plugin_ui.h | 9 +++ gtk2_ardour/rc_option_editor.cc | 12 +-- gtk2_ardour/wscript | 6 +- 10 files changed, 293 insertions(+), 7 deletions(-) create mode 100644 gtk2_ardour/mac_vst_plugin_ui.h create mode 100644 gtk2_ardour/mac_vst_plugin_ui.mm diff --git a/gtk2_ardour/instrument_selector.cc b/gtk2_ardour/instrument_selector.cc index 618facd42a..6b0590964b 100644 --- a/gtk2_ardour/instrument_selector.cc +++ b/gtk2_ardour/instrument_selector.cc @@ -85,6 +85,9 @@ InstrumentSelector::build_instrument_list() #ifdef LXVST_SUPPORT all_plugs.insert(all_plugs.end(), manager.lxvst_plugin_info().begin(), manager.lxvst_plugin_info().end()); #endif +#ifdef MACVST_SUPPORT + all_plugs.insert(all_plugs.end(), manager.mac_vst_plugin_info().begin(), manager.mac_vst_plugin_info().end()); +#endif #ifdef AUDIOUNIT_SUPPORT all_plugs.insert(all_plugs.end(), manager.au_plugin_info().begin(), manager.au_plugin_info().end()); #endif diff --git a/gtk2_ardour/mac_vst_plugin_ui.h b/gtk2_ardour/mac_vst_plugin_ui.h new file mode 100644 index 0000000000..87639526e9 --- /dev/null +++ b/gtk2_ardour/mac_vst_plugin_ui.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2000-2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include + +/* fix up stupid apple macros */ +#undef check +#undef require +#undef verify + +#ifdef YES +#undef YES +#endif +#ifdef NO +#undef NO +#endif + +#include "vst_plugin_ui.h" + +class MacVSTPluginUI : public VSTPluginUI +{ +public: + MacVSTPluginUI (boost::shared_ptr, boost::shared_ptr); + ~MacVSTPluginUI (); + + bool start_updating (GdkEventAny*) { return false; } + bool stop_updating (GdkEventAny*) { return false; } + + int package (Gtk::Window &); + + void forward_key_event (GdkEventKey *); + +private: + int get_XID (); + bool idle (); + void lower_box_realized (); + NSWindow* get_nswindow(); + + Gtk::EventBox low_box; + NSView* _ns_view; + sigc::connection _idle_connection; +}; diff --git a/gtk2_ardour/mac_vst_plugin_ui.mm b/gtk2_ardour/mac_vst_plugin_ui.mm new file mode 100644 index 0000000000..fe52a01e13 --- /dev/null +++ b/gtk2_ardour/mac_vst_plugin_ui.mm @@ -0,0 +1,151 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include + +#include "ardour/plugin_insert.h" +#include "ardour/mac_vst_plugin.h" +#include "ardour/vst_types.h" +#include "mac_vst_plugin_ui.h" + +#include "pbd/i18n.h" + +using namespace Gtk; +using namespace ARDOUR; +using namespace PBD; + +struct ERect{ + short top; + short left; + short bottom; + short right; +}; + +VSTPluginUI* +create_mac_vst_gui (boost::shared_ptr insert) +{ + /* PluginUIWindow::create_mac_vst_editor assures this cast works */ + boost::shared_ptr mvst = boost::dynamic_pointer_cast (insert->plugin()); + return new MacVSTPluginUI (insert, mvst); +} + + +MacVSTPluginUI::MacVSTPluginUI (boost::shared_ptr pi, boost::shared_ptr vst) + : VSTPluginUI (pi, vst) + , _ns_view (0) +{ + low_box.add_events (Gdk::VISIBILITY_NOTIFY_MASK | Gdk::EXPOSURE_MASK); + low_box.signal_realize().connect (mem_fun (this, &MacVSTPluginUI::lower_box_realized)); + pack_start (low_box, true, true); + low_box.show (); +} + +MacVSTPluginUI::~MacVSTPluginUI () +{ + if (_ns_view) { + [_ns_view removeFromSuperview]; + [_ns_view release]; + } + + AEffect* plugin = _vst->state()->plugin; + plugin->dispatcher (plugin, effEditClose, 0, 0, 0, 0.0f); + _idle_connection.disconnect(); +} + +NSWindow* +MacVSTPluginUI::get_nswindow () +{ + Gtk::Container* toplevel = get_toplevel(); + if (!toplevel || !toplevel->is_toplevel()) { + error << _("MacVSTPluginUI: no top level window!") << endmsg; + return 0; + } + NSWindow* true_parent = gdk_quartz_window_get_nswindow (toplevel->get_window()->gobj()); + + if (!true_parent) { + error << _("MacVSTPluginUI: no top level window!") << endmsg; + return 0; + } + + return true_parent; +} + +int +MacVSTPluginUI::package (Gtk::Window& win) +{ + VSTPluginUI::package (win); + return 0; +} + +void +MacVSTPluginUI::forward_key_event (GdkEventKey* ev) +{ +} + +void +MacVSTPluginUI::lower_box_realized () +{ + NSWindow* win = get_nswindow (); + if (!win) { + return; + } + + [win setAutodisplay:1]; // turn off GTK stuff for this window + + NSView* view = gdk_quartz_window_get_nsview (low_box.get_window()->gobj()); + _ns_view = [[NSView new] retain]; + [view addSubview:_ns_view]; + + AEffect* plugin = _vst->state()->plugin; + plugin->dispatcher (plugin, effEditOpen, 0, 0, _ns_view, 0.0f); + + struct ERect* er = NULL; + plugin->dispatcher (plugin, effEditGetRect, 0, 0, &er, 0 ); + if (er) { + int req_width = er->right - er->left; + int req_height = er->bottom - er->top; + + low_box.set_size_request (req_width, req_height); + + gint xx, yy; + gtk_widget_translate_coordinates( + GTK_WIDGET(low_box.gobj()), + GTK_WIDGET(low_box.get_parent()->gobj()), + 8, 6, &xx, &yy); + [_ns_view setFrame:NSMakeRect(xx, yy, req_width, req_height)]; + } + + _idle_connection = Glib::signal_idle().connect (sigc::mem_fun (*this, &MacVSTPluginUI::idle)); +} + +int +MacVSTPluginUI::get_XID () +{ + return _vst->state()->xid; +} + +bool +MacVSTPluginUI::idle () +{ + AEffect* plugin = _vst->state()->plugin; + _vst->state()->wantIdle = plugin->dispatcher (plugin, effIdle, 0, 0, NULL, 0); + return true; // _vst->state()->wantIdle; +} diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 95a619fdba..ee4b616adf 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -2484,6 +2484,9 @@ Mixer_UI::refill_favorite_plugins () #ifdef LXVST_SUPPORT refiller (plugs, mgr.lxvst_plugin_info ()); #endif +#ifdef MACVST_SUPPORT + refiller (plugs, mgr.mac_vst_plugin_info ()); +#endif #ifdef AUDIOUNIT_SUPPORT refiller (plugs, mgr.au_plugin_info ()); #endif diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index 3a0fed0d67..dd3a3a908d 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -341,6 +341,9 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& case LXVST: compstr = X_("LXVST"); break; + case MacVST: + compstr = X_("MacVST"); + break; case Lua: compstr = X_("Lua"); break; @@ -390,6 +393,7 @@ PluginSelector::refill () lv2_refiller (filterstr); vst_refiller (filterstr); lxvst_refiller (filterstr); + mac_vst_refiller (filterstr); au_refiller (filterstr); lua_refiller (filterstr); @@ -501,6 +505,18 @@ PluginSelector::lxvst_refiller (const std::string&) #endif } +void +#ifdef MACVST_SUPPORT +PluginSelector::mac_vst_refiller (const std::string& filterstr) +#else +PluginSelector::mac_vst_refiller (const std::string&) +#endif +{ +#ifdef MACVST_SUPPORT + refiller (manager.mac_vst_plugin_info(), filterstr, "MacVST"); +#endif +} + void #ifdef AUDIOUNIT_SUPPORT PluginSelector::au_refiller (const std::string& filterstr) @@ -736,6 +752,9 @@ PluginSelector::build_plugin_menu () #ifdef LXVST_SUPPORT all_plugs.insert (all_plugs.end(), manager.lxvst_plugin_info().begin(), manager.lxvst_plugin_info().end()); #endif +#ifdef MACVST_SUPPORT + all_plugs.insert (all_plugs.end(), manager.mac_vst_plugin_info().begin(), manager.mac_vst_plugin_info().end()); +#endif #ifdef AUDIOUNIT_SUPPORT all_plugs.insert (all_plugs.end(), manager.au_plugin_info().begin(), manager.au_plugin_info().end()); #endif diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h index 1a7e11be8c..14780758b4 100644 --- a/gtk2_ardour/plugin_selector.h +++ b/gtk2_ardour/plugin_selector.h @@ -122,6 +122,7 @@ class PluginSelector : public ArdourDialog void lv2_refiller (const std::string&); void vst_refiller (const std::string&); void lxvst_refiller (const std::string&); + void mac_vst_refiller (const std::string&); void au_refiller (const std::string&); void lua_refiller (const std::string&); diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index 03c5ef301d..15600772e2 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -52,6 +52,10 @@ #include "ardour/lxvst_plugin.h" #include "lxvst_plugin_ui.h" #endif +#ifdef MACVST_SUPPORT +#include "ardour/mac_vst_plugin.h" +#include "vst_plugin_ui.h" +#endif #ifdef LV2_SUPPORT #include "ardour/lv2_plugin.h" #include "lv2_plugin_ui.h" @@ -107,6 +111,10 @@ PluginUIWindow::PluginUIWindow ( have_gui = create_lxvst_editor (insert); break; + case ARDOUR::MacVST: + have_gui = create_mac_vst_editor (insert); + break; + case ARDOUR::AudioUnit: have_gui = create_audiounit_editor (insert); break; @@ -272,6 +280,35 @@ PluginUIWindow::create_lxvst_editor(boost::shared_ptr) #endif } +bool +#ifdef MACVST_SUPPORT +PluginUIWindow::create_mac_vst_editor (boost::shared_ptr insert) +#else +PluginUIWindow::create_mac_vst_editor (boost::shared_ptr) +#endif +{ +#ifndef MACVST_SUPPORT + return false; +#else + boost::shared_ptr mvst; + if ((mvst = boost::dynamic_pointer_cast (insert->plugin())) == 0) { + error << string_compose (_("unknown type of editor-supplying plugin (note: no MacVST support in this version of %1)"), PROGRAM_NAME) + << endmsg; + throw failed_constructor (); + } + VSTPluginUI* vpu = create_mac_vst_gui (insert); + _pluginui = vpu; + _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused)); + add (*vpu); + vpu->package (*this); + + Application::instance()->ActivationChanged.connect (mem_fun (*this, &PluginUIWindow::app_activated)); + + return true; +#endif +} + + bool #ifdef AUDIOUNIT_SUPPORT PluginUIWindow::create_audiounit_editor (boost::shared_ptr insert) diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h index 4fb052b5f5..ad800e284d 100644 --- a/gtk2_ardour/plugin_ui.h +++ b/gtk2_ardour/plugin_ui.h @@ -79,6 +79,7 @@ namespace Gtkmm2ext { class LatencyGUI; class ArdourWindow; class PluginEqGui; +class VSTPluginUI; class PlugUIBase : public virtual sigc::trackable, public PBD::ScopedConnectionList { @@ -347,10 +348,18 @@ class PluginUIWindow : public ArdourWindow bool create_windows_vst_editor (boost::shared_ptr); bool create_lxvst_editor(boost::shared_ptr); + bool create_mac_vst_editor(boost::shared_ptr); bool create_audiounit_editor (boost::shared_ptr); bool create_lv2_editor (boost::shared_ptr); }; +#ifdef MACVST_SUPPORT +/* this function has to be in a .mm file + * because MacVSTPluginUI has Cocoa members + */ +extern VSTPluginUI* create_mac_vst_gui (boost::shared_ptr); +#endif + #ifdef AUDIOUNIT_SUPPORT /* this function has to be in a .mm file */ extern PlugUIBase* create_au_gui (boost::shared_ptr, Gtk::VBox**); diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index 0c15c1ee66..1c1783bd37 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -3147,7 +3147,7 @@ if (!ARDOUR::Profile->get_mixbus()) { /* VIDEO Timeline */ add_option (_("Video"), new VideoTimelineOptions (_rc_config)); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT) add_option (_("Plugins"), new RcActionButton (_("Scan for Plugins"), sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh))); @@ -3156,7 +3156,7 @@ if (!ARDOUR::Profile->get_mixbus()) { add_option (_("Plugins"), new OptionEditorHeading (_("General"))); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT) bo = new BoolOption ( "show-plugin-scan-window", _("Always Display Plugin Scan Progress"), @@ -3188,7 +3188,7 @@ if (!ARDOUR::Profile->get_mixbus()) { Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("When enabled plugins will be activated when they are added to tracks/busses. When disabled plugins will be left inactive when they are added to tracks/busses")); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST"))); add_option (_("Plugins/VST"), new RcActionButton (_("Scan for Plugins"), @@ -3266,11 +3266,11 @@ if (!ARDOUR::Profile->get_mixbus()) { bo = new BoolOption ( "discover-audio-units", - _("Scan for AudioUnit Plugins on Application Start"), + _("Scan for [new] AudioUnit Plugins on Application Start"), sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units), sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units) ); - add_option (_("Plugins"), bo); + add_option (_("Plugins/Audio Unit"), bo); Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("When enabled Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it.")); @@ -3285,7 +3285,7 @@ if (!ARDOUR::Profile->get_mixbus()) { _("AU Blacklist:"))); #endif -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2) add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI"))); add_option (_("Plugins"), new BoolOption ( diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 3fb77ce6d4..eefe772b96 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -606,7 +606,11 @@ def build(bld): obj.defines += [ 'LXVST_SUPPORT' ] obj.use += [ 'X11' ] - if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT'): + if bld.is_defined('MACVST_SUPPORT'): + obj.source += [ 'mac_vst_plugin_ui.mm' ] + obj.defines += [ 'MACVST_SUPPORT' ] + + if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT') or bld.is_defined ('MACVST_SUPPORT'): obj.source += [ 'vst_plugin_ui.cc' ] if bld.is_defined('PHONE_HOME'): -- cgit v1.2.3