From 6ad519ce8e8367f61187998dc8bb88dce60e7098 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 17 Sep 2016 13:46:30 +0200 Subject: [PATCH] VST threading: prevent concurrent effSetChunk and process() This is a potential fix for unreliable preset load/restore. (http://mixbus.harrisonconsoles.com/forum/thread-1970-post-21486.html#pid21486) Since a Glib Mutex can't be copy-constructed an explicit copy c'tor is needed. --- libs/ardour/ardour/vst_plugin.h | 3 +++ libs/ardour/vst_plugin.cc | 32 +++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h index e56b9c005c..182b432692 100644 --- a/libs/ardour/ardour/vst_plugin.h +++ b/libs/ardour/ardour/vst_plugin.h @@ -40,6 +40,7 @@ class LIBARDOUR_API VSTPlugin : public Plugin { public: VSTPlugin (AudioEngine &, Session &, VSTHandle *); + VSTPlugin (const VSTPlugin& other); virtual ~VSTPlugin (); void activate (); @@ -119,6 +120,8 @@ protected: framepos_t _transport_frame; float _transport_speed; mutable std::map _parameter_defaults; + + Glib::Threads::Mutex _state_lock; }; } diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 8188354062..c9a214c0be 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -52,6 +52,21 @@ VSTPlugin::VSTPlugin (AudioEngine& engine, Session& session, VSTHandle* handle) memset (&_timeInfo, 0, sizeof(_timeInfo)); } +VSTPlugin::VSTPlugin (const VSTPlugin& other) + : Plugin (other) + , _handle (other._handle) + , _state (other._state) + , _plugin (other._plugin) + , _pi (other._pi) + , _num (other._num) + , _midi_out_buf (other._midi_out_buf) + , _transport_frame (0) + , _transport_speed (0.f) + , _parameter_defaults (other._parameter_defaults) +{ + memset (&_timeInfo, 0, sizeof(_timeInfo)); +} + VSTPlugin::~VSTPlugin () { @@ -153,8 +168,12 @@ int VSTPlugin::set_chunk (gchar const * data, bool single) { gsize size = 0; + int r = 0; guchar* raw_data = g_base64_decode (data, &size); - int const r = _plugin->dispatcher (_plugin, 24 /* effSetChunk */, single ? 1 : 0, size, raw_data, 0); + { + Glib::Threads::Mutex::Lock lm (_lock); + r = _plugin->dispatcher (_plugin, 24 /* effSetChunk */, single ? 1 : 0, size, raw_data, 0); + } g_free (raw_data); return r; } @@ -544,6 +563,17 @@ VSTPlugin::connect_and_run (BufferSet& bufs, { Plugin::connect_and_run(bufs, start, end, speed, in_map, out_map, nframes, offset); + Glib::Threads::Mutex::Lock lm (_state_lock, Glib::Threads::TRY_LOCK); + if (!lm.locked()) { + /* by convention 'effSetChunk' should not be called while processing + * http://www.reaper.fm/sdk/vst/vst_ext.php + * + * All VSTs don't use in-place, PluginInsert::connect_and_run() + * does clear output buffers, so we can just return. + */ + return 0; + } + _transport_frame = start; _transport_speed = speed;