diff --git a/gtk2_ardour/vst3_x11_plugin_ui.cc b/gtk2_ardour/vst3_x11_plugin_ui.cc index 2b79d85583..ee54c2d0d6 100644 --- a/gtk2_ardour/vst3_x11_plugin_ui.cc +++ b/gtk2_ardour/vst3_x11_plugin_ui.cc @@ -20,11 +20,6 @@ #include "gtk2ardour-config.h" #endif -#include - -#include -#include - #include #include "pbd/unwind.h" @@ -41,149 +36,9 @@ using namespace ARDOUR; using namespace Steinberg; -class VST3X11Runloop : public Linux::IRunLoop -{ -private: - struct EventHandler - { - EventHandler (Linux::IEventHandler* handler = 0, GIOChannel* gio_channel = 0, guint source_id = 0) - : _handler (handler) - , _gio_channel (gio_channel) - , _source_id (source_id) - {} - - bool operator== (EventHandler const& other) { - return other._handler == _handler && other._gio_channel == _gio_channel && other._source_id == _source_id; - } - Linux::IEventHandler* _handler; - GIOChannel* _gio_channel; - guint _source_id; - }; - - boost::unordered_map _event_handlers; - boost::unordered_map _timer_handlers; - - static gboolean event (GIOChannel* source, GIOCondition condition, gpointer data) - { - Linux::IEventHandler* handler = reinterpret_cast (data); - handler->onFDIsSet (g_io_channel_unix_get_fd (source)); - if (condition & ~G_IO_IN) { - /* remove on error */ - return false; - } else { - return true; - } - } - - static gboolean timeout (gpointer data) - { - Linux::ITimerHandler* handler = reinterpret_cast (data); - handler->onTimer (); - return true; - } - -public: - ~VST3X11Runloop () - { - clear (); - } - - void clear () { - Glib::Threads::Mutex::Lock lm (_lock); - for (boost::unordered_map::const_iterator it = _event_handlers.begin (); it != _event_handlers.end (); ++it) { - g_source_remove (it->second._source_id); - g_io_channel_unref (it->second._gio_channel); - } - for (boost::unordered_map::const_iterator it = _timer_handlers.begin (); it != _timer_handlers.end (); ++it) { - g_source_remove (it->first); - } - _event_handlers.clear (); - _timer_handlers.clear (); - } - - /* VST3 IRunLoop interface */ - tresult registerEventHandler (Linux::IEventHandler* handler, FileDescriptor fd) SMTG_OVERRIDE - { - if (!handler || _event_handlers.find(fd) != _event_handlers.end()) { - return kInvalidArgument; - } - - Glib::Threads::Mutex::Lock lm (_lock); - GIOChannel* gio_channel = g_io_channel_unix_new (fd); - guint id = g_io_add_watch (gio_channel, (GIOCondition) (G_IO_IN /*| G_IO_OUT*/ | G_IO_ERR | G_IO_HUP), event, handler); - _event_handlers[fd] = EventHandler (handler, gio_channel, id); - return kResultTrue; - } - - tresult unregisterEventHandler (Linux::IEventHandler* handler) SMTG_OVERRIDE - { - if (!handler) { - return kInvalidArgument; - } - - tresult rv = false; - Glib::Threads::Mutex::Lock lm (_lock); - for (boost::unordered_map::const_iterator it = _event_handlers.begin (); it != _event_handlers.end ();) { - if (it->second._handler == handler) { - g_source_remove (it->second._source_id); - g_io_channel_unref (it->second._gio_channel); - it = _event_handlers.erase (it); - rv = kResultTrue; - } else { - ++it; - } - } - return rv; - } - - tresult registerTimer (Linux::ITimerHandler* handler, TimerInterval milliseconds) SMTG_OVERRIDE - { - if (!handler || milliseconds == 0) { - return kInvalidArgument; - } - Glib::Threads::Mutex::Lock lm (_lock); - guint id = g_timeout_add_full (G_PRIORITY_HIGH_IDLE, milliseconds, timeout, handler, NULL); - _timer_handlers[id] = handler; - return kResultTrue; - - } - - tresult unregisterTimer (Linux::ITimerHandler* handler) SMTG_OVERRIDE - { - if (!handler) { - return kInvalidArgument; - } - - tresult rv = false; - Glib::Threads::Mutex::Lock lm (_lock); - for (boost::unordered_map::const_iterator it = _timer_handlers.begin (); it != _timer_handlers.end ();) { - if (it->second == handler) { - g_source_remove (it->first); - it = _timer_handlers.erase (it); - rv = kResultTrue; - } else { - ++it; - } - } - return rv; - } - - uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return 1; } - uint32 PLUGIN_API release () SMTG_OVERRIDE { return 1; } - tresult queryInterface (const TUID, void**) SMTG_OVERRIDE { return kNoInterface; } - -private: - Glib::Threads::Mutex _lock; -}; - -VST3X11Runloop static_runloop; - VST3X11PluginUI::VST3X11PluginUI (std::shared_ptr pib, std::shared_ptr vst3) : VST3PluginUI (pib, vst3) - //, _runloop (new VST3X11Runloop) { - _vst3->set_runloop (&static_runloop); - pack_start (_gui_widget, true, true); _gui_widget.signal_realize().connect (mem_fun (this, &VST3X11PluginUI::view_realized)); diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc index 6d71c6c85a..c0259d814e 100644 --- a/libs/ardour/amp.cc +++ b/libs/ardour/amp.cc @@ -168,10 +168,14 @@ Amp::apply_gain (BufferSet& bufs, samplecnt_t sample_rate, samplecnt_t nframes, return target; } - /* Apply Audio Gain first, calculate target LFP'ed gain coefficient + /* Apply Audio Gain first, calculate 1 pole IIR time constant * - * Low pass filter coefficient: 1.0 - e^(-2.0 * π * f / 48000) f in Hz. - * for f << SR, approx a ~= 6.2 * f / SR; + * H(z) = a / (1 - (1 - a) z^-1) + * a = -y + sqrt (y^2 + 2y); y = 1 - cos (w) ; w = 2 * π f/SR + * a ~= 1.0 - e^(-2.0 * π * f / SR) + * + * and for very small w (f << SR) + * a ~= 6.2 * f / SR; */ const gain_t a = 156.825f / (gain_t)sample_rate; // 25 Hz LPF diff --git a/libs/ardour/ardour/vst3_plugin.h b/libs/ardour/ardour/vst3_plugin.h index 6f1de4792a..fa8dfb6cbc 100644 --- a/libs/ardour/ardour/vst3_plugin.h +++ b/libs/ardour/ardour/vst3_plugin.h @@ -100,9 +100,6 @@ public: IPlugView* view (); void close_view (); void update_contoller_param (); -#if SMTG_OS_LINUX - void set_runloop (Linux::IRunLoop*); -#endif PBD::Signal2 OnResizeView; tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) SMTG_OVERRIDE; @@ -279,10 +276,6 @@ private: Vst::IEditController* _controller; IPlugView* _view; -#if SMTG_OS_LINUX - Linux::IRunLoop* _run_loop; -#endif - IPtr _processor; Vst::ProcessContext _context; Glib::Threads::Mutex _process_lock; @@ -442,9 +435,6 @@ public: Steinberg::IPlugView* view (); void close_view (); void update_contoller_param (); -#if SMTG_OS_LINUX - void set_runloop (Steinberg::Linux::IRunLoop*); -#endif PBD::Signal2 OnResizeView; diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 2f5ac62651..941da0cea9 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -916,6 +916,10 @@ Session::request_stop (bool abort, bool clear_state, TransportRequestSource orig void Session::request_locate (samplepos_t target_sample, bool force, LocateTransportDisposition ltd, TransportRequestSource origin) { + if (actively_recording ()) { + return; + } + if (synced_to_engine()) { _engine.transport_locate (target_sample); return; diff --git a/libs/ardour/vst3_host.cc b/libs/ardour/vst3_host.cc index 748832e241..0ba39bc82f 100644 --- a/libs/ardour/vst3_host.cc +++ b/libs/ardour/vst3_host.cc @@ -36,6 +36,7 @@ DEF_CLASS_IID (IBStream) DEF_CLASS_IID (IPluginBase) DEF_CLASS_IID (IPluginFactory) DEF_CLASS_IID (IPluginFactory2) +DEF_CLASS_IID (IPluginFactory3) DEF_CLASS_IID (IPlugFrame) DEF_CLASS_IID (IPlugView) DEF_CLASS_IID (ISizeableStream) diff --git a/libs/ardour/vst3_plugin.cc b/libs/ardour/vst3_plugin.cc index 313751f659..8ee813cc9f 100644 --- a/libs/ardour/vst3_plugin.cc +++ b/libs/ardour/vst3_plugin.cc @@ -19,6 +19,8 @@ #include "pbd/gstdio_compat.h" #include +#include + #include "pbd/basename.h" #include "pbd/compose.h" #include "pbd/convert.h" @@ -54,6 +56,146 @@ using namespace Temporal; using namespace Steinberg; using namespace Presonus; +#if SMTG_OS_LINUX +class AVST3Runloop : public Linux::IRunLoop +{ +private: + struct EventHandler + { + EventHandler (Linux::IEventHandler* handler = 0, GIOChannel* gio_channel = 0, guint source_id = 0) + : _handler (handler) + , _gio_channel (gio_channel) + , _source_id (source_id) + {} + + bool operator== (EventHandler const& other) { + return other._handler == _handler && other._gio_channel == _gio_channel && other._source_id == _source_id; + } + Linux::IEventHandler* _handler; + GIOChannel* _gio_channel; + guint _source_id; + }; + + boost::unordered_map _event_handlers; + boost::unordered_map _timer_handlers; + + static gboolean event (GIOChannel* source, GIOCondition condition, gpointer data) + { + Linux::IEventHandler* handler = reinterpret_cast (data); + handler->onFDIsSet (g_io_channel_unix_get_fd (source)); + if (condition & ~G_IO_IN) { + /* remove on error */ + return false; + } else { + return true; + } + } + + static gboolean timeout (gpointer data) + { + Linux::ITimerHandler* handler = reinterpret_cast (data); + handler->onTimer (); + return true; + } + +public: + ~AVST3Runloop () + { + clear (); + } + + void clear () { + Glib::Threads::Mutex::Lock lm (_lock); + for (boost::unordered_map::const_iterator it = _event_handlers.begin (); it != _event_handlers.end (); ++it) { + g_source_remove (it->second._source_id); + g_io_channel_unref (it->second._gio_channel); + } + for (boost::unordered_map::const_iterator it = _timer_handlers.begin (); it != _timer_handlers.end (); ++it) { + g_source_remove (it->first); + } + _event_handlers.clear (); + _timer_handlers.clear (); + } + + /* VST3 IRunLoop interface */ + tresult registerEventHandler (Linux::IEventHandler* handler, FileDescriptor fd) SMTG_OVERRIDE + { + if (!handler || _event_handlers.find(fd) != _event_handlers.end()) { + return kInvalidArgument; + } + + Glib::Threads::Mutex::Lock lm (_lock); + GIOChannel* gio_channel = g_io_channel_unix_new (fd); + guint id = g_io_add_watch (gio_channel, (GIOCondition) (G_IO_IN /*| G_IO_OUT*/ | G_IO_ERR | G_IO_HUP), event, handler); + _event_handlers[fd] = EventHandler (handler, gio_channel, id); + return kResultTrue; + } + + tresult unregisterEventHandler (Linux::IEventHandler* handler) SMTG_OVERRIDE + { + if (!handler) { + return kInvalidArgument; + } + + tresult rv = false; + Glib::Threads::Mutex::Lock lm (_lock); + for (boost::unordered_map::const_iterator it = _event_handlers.begin (); it != _event_handlers.end ();) { + if (it->second._handler == handler) { + g_source_remove (it->second._source_id); + g_io_channel_unref (it->second._gio_channel); + it = _event_handlers.erase (it); + rv = kResultTrue; + } else { + ++it; + } + } + return rv; + } + + tresult registerTimer (Linux::ITimerHandler* handler, TimerInterval milliseconds) SMTG_OVERRIDE + { + if (!handler || milliseconds == 0) { + return kInvalidArgument; + } + Glib::Threads::Mutex::Lock lm (_lock); + guint id = g_timeout_add_full (G_PRIORITY_HIGH_IDLE, milliseconds, timeout, handler, NULL); + _timer_handlers[id] = handler; + return kResultTrue; + + } + + tresult unregisterTimer (Linux::ITimerHandler* handler) SMTG_OVERRIDE + { + if (!handler) { + return kInvalidArgument; + } + + tresult rv = false; + Glib::Threads::Mutex::Lock lm (_lock); + for (boost::unordered_map::const_iterator it = _timer_handlers.begin (); it != _timer_handlers.end ();) { + if (it->second == handler) { + g_source_remove (it->first); + it = _timer_handlers.erase (it); + rv = kResultTrue; + } else { + ++it; + } + } + return rv; + } + + uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return 1; } + uint32 PLUGIN_API release () SMTG_OVERRIDE { return 1; } + tresult queryInterface (const TUID, void**) SMTG_OVERRIDE { return kNoInterface; } + +private: + Glib::Threads::Mutex _lock; +}; + +AVST3Runloop static_runloop; + +#endif + VST3Plugin::VST3Plugin (AudioEngine& engine, Session& session, VST3PI* plug) : Plugin (engine, session) , _plug (plug) @@ -365,14 +507,6 @@ VST3Plugin::close_view () _plug->close_view (); } -#if SMTG_OS_LINUX -void -VST3Plugin::set_runloop (Steinberg::Linux::IRunLoop* run_loop) -{ - return _plug->set_runloop (run_loop); -} -#endif - void VST3Plugin::update_contoller_param () { @@ -1166,9 +1300,6 @@ VST3PI::VST3PI (std::shared_ptr m, std::string unique_ , _component (0) , _controller (0) , _view (0) -#if SMTG_OS_LINUX - , _run_loop (0) -#endif , _is_loading_state (false) , _is_processing (false) , _block_size (0) @@ -1277,6 +1408,14 @@ VST3PI::VST3PI (std::shared_ptr m, std::string unique_ throw failed_constructor (); } +#if SMTG_OS_LINUX + IPtr factory3 = FUnknownPtr (factory); + if (factory3) { + Vst::IComponentHandler* ctx = this; + factory3->setHostContext ((FUnknown*) ctx); + } +#endif + /* prepare process context */ memset (&_context, 0, sizeof (Vst::ProcessContext)); @@ -1497,8 +1636,8 @@ VST3PI::queryInterface (const TUID _iid, void** obj) QUERY_INTERFACE (_iid, obj, IPlugFrame::iid, IPlugFrame) #if SMTG_OS_LINUX - if (_run_loop && FUnknownPrivate::iidEqual (_iid, Linux::IRunLoop::iid)) { - *obj = _run_loop; + if (FUnknownPrivate::iidEqual (_iid, Linux::IRunLoop::iid)) { + *obj = &static_runloop; return kResultOk; } #endif @@ -3240,14 +3379,6 @@ VST3PI::has_editor () const return rv; } -#if SMTG_OS_LINUX -void -VST3PI::set_runloop (Linux::IRunLoop* run_loop) -{ - _run_loop = run_loop; -} -#endif - tresult VST3PI::resizeView (IPlugView* view, ViewRect* new_size) {