From 217f51e6fb3daae3be862f7481cab1340da3e887 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 14 Apr 2022 04:42:40 +0200 Subject: [PATCH] Break out common plugin-insert state methods This is in preparation for IO-Plug, and should also come in handy later for per region plugins. --- libs/ardour/ardour/plug_insert_base.h | 7 + libs/ardour/ardour/plugin_insert.h | 3 - libs/ardour/plug_insert_base.cc | 200 ++++++++++++++++++++++++++ libs/ardour/plugin_insert.cc | 158 +------------------- libs/ardour/wscript | 1 + 5 files changed, 213 insertions(+), 156 deletions(-) create mode 100644 libs/ardour/plug_insert_base.cc diff --git a/libs/ardour/ardour/plug_insert_base.h b/libs/ardour/ardour/plug_insert_base.h index ffd792fe58..af3e8dbae7 100644 --- a/libs/ardour/ardour/plug_insert_base.h +++ b/libs/ardour/ardour/plug_insert_base.h @@ -64,6 +64,13 @@ public: virtual bool provides_stats () const = 0; virtual bool get_stats (PBD::microseconds_t&, PBD::microseconds_t&, double&, double&) const = 0; virtual void clear_stats () = 0; + +protected: + bool parse_plugin_type (XMLNode const&, PluginType&, std::string&) const; + boost::shared_ptr find_and_load_plugin (Session&, XMLNode const&, PluginType&, std::string const&, bool& any_vst); + + void set_control_ids (const XMLNode&, int version); + void preset_load_set_value (uint32_t, float); }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index 9d2da6243d..ad90e504dc 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -415,7 +415,6 @@ private: void create_automatable_parameters (); void control_list_automation_state_changed (Evoral::Parameter, AutoState); void set_parameter_state_2X (const XMLNode& node, int version); - void set_control_ids (const XMLNode&, int version); void update_control_values (const XMLNode&, int version); void enable_changed (); @@ -442,8 +441,6 @@ private: typedef std::map >CtrlOutMap; CtrlOutMap _control_outputs; - void preset_load_set_value (uint32_t, float); - PBD::TimingStats _timing_stats; GATOMIC_QUAL gint _stat_reset; GATOMIC_QUAL gint _flush; diff --git a/libs/ardour/plug_insert_base.cc b/libs/ardour/plug_insert_base.cc new file mode 100644 index 0000000000..1ae0694f17 --- /dev/null +++ b/libs/ardour/plug_insert_base.cc @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022 Robin Gareus + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "ardour/ardour.h" +#include "ardour/automation_control.h" +#include "ardour/lv2_plugin.h" +#include "ardour/luaproc.h" +#include "ardour/plug_insert_base.h" + +#include "pbd/i18n.h" + +using namespace PBD; +using namespace ARDOUR; + +bool +PlugInsertBase::parse_plugin_type (XMLNode const& node, PluginType& type, std::string& id) const +{ + std::string str; + if (!node.get_property ("type", str)) { + error << _("XML node describing plugin is missing the `type' field") << endmsg; + return false; + } + + if (str == X_("ladspa") || str == X_("Ladspa")) { /* handle old school sessions */ + type = ARDOUR::LADSPA; + } else if (str == X_("lv2")) { + type = ARDOUR::LV2; + } else if (str == X_("windows-vst")) { + type = ARDOUR::Windows_VST; + } else if (str == X_("lxvst")) { + type = ARDOUR::LXVST; + } else if (str == X_("mac-vst")) { + type = ARDOUR::MacVST; + } else if (str == X_("audiounit")) { + type = ARDOUR::AudioUnit; + } else if (str == X_("luaproc")) { + type = ARDOUR::Lua; + } else if (str == X_("vst3")) { + type = ARDOUR::VST3; + } else { + error << string_compose (_("unknown plugin type %1 in plugin insert state"), str) << endmsg; + return false; + } + + XMLProperty const* prop = node.property ("unique-id"); + + if (prop == 0) { +#ifdef WINDOWS_VST_SUPPORT + /* older sessions contain VST plugins with only an "id" field. */ + if (type == ARDOUR::Windows_VST) { + prop = node.property ("id"); + } +#endif + +#ifdef LXVST_SUPPORT + /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/ + if (type == ARDOUR::LXVST) { + prop = node.property ("id"); + } +#endif + + /* recheck */ + if (prop == 0) { + error << _("Plugin has no unique ID field") << endmsg; + return false; + } + } + + id = prop->value(); + return true; +} + +boost::shared_ptr +PlugInsertBase::find_and_load_plugin (Session& s, XMLNode const& node, PluginType& type, std::string const& unique_id, bool& any_vst) +{ + /* Find and load plugin module */ + boost::shared_ptr plugin = find_plugin (s, unique_id, type); + + /* treat VST plugins equivalent if they have the same uniqueID + * allow to move sessions windows <> linux */ +#ifdef LXVST_SUPPORT + if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::MacVST)) { + type = ARDOUR::LXVST; + plugin = find_plugin (s, unique_id, type); + if (plugin) { + any_vst = true; + } + } +#endif + +#ifdef WINDOWS_VST_SUPPORT + if (plugin == 0 && (type == ARDOUR::LXVST || type == ARDOUR::MacVST)) { + type = ARDOUR::Windows_VST; + plugin = find_plugin (s, unique_id, type); + if (plugin) { any_vst = true; } + } +#endif + +#ifdef MACVST_SUPPORT + if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::LXVST)) { + type = ARDOUR::MacVST; + plugin = find_plugin (s, unique_id, type); + if (plugin) { any_vst = true; } + } +#endif + + if (plugin == 0 && type == ARDOUR::Lua) { + /* unique ID (sha1 of script) was not found, + * load the plugin from the serialized version in the + * session-file instead. + */ + boost::shared_ptr lp (new LuaProc (s.engine(), s, "")); + XMLNode *ls = node.child (lp->state_node_name().c_str()); + if (ls && lp) { + if (0 == lp->set_script_from_state (*ls)) { + plugin = lp; + } + } + } + + if (plugin == 0) { + error << string_compose( + _("Found a reference to a plugin (\"%1\") that is unknown.\n" + "Perhaps it was removed or moved since it was last used."), + unique_id) + << endmsg; + return boost::shared_ptr (); + } + return plugin; +} + +void +PlugInsertBase::set_control_ids (const XMLNode& node, int version) +{ + const XMLNodeList& nlist = node.children(); + for (XMLNodeConstIterator iter = nlist.begin(); iter != nlist.end(); ++iter) { + if ((*iter)->name() != Controllable::xml_node_name) { + continue; + } + + uint32_t p = (uint32_t)-1; + std::string str; + if ((*iter)->get_property (X_("symbol"), str)) { + boost::shared_ptr lv2plugin = boost::dynamic_pointer_cast (plugin ()); + if (lv2plugin) { + p = lv2plugin->port_index(str.c_str()); + } + } + if (p == (uint32_t)-1) { + (*iter)->get_property (X_("parameter"), p); + } + + if (p == (uint32_t)-1) { + continue; + } + + /* this may create the new controllable */ + boost::shared_ptr c = control (Evoral::Parameter (PluginAutomation, 0, p)); + + if (!c) { + continue; + } + boost::shared_ptr ac = boost::dynamic_pointer_cast (c); + if (ac) { + ac->set_state (**iter, version); + } + } +} + +void +PlugInsertBase::preset_load_set_value (uint32_t p, float v) +{ + boost::shared_ptr ac = boost::dynamic_pointer_cast (Evoral::ControlSet::control (Evoral::Parameter(PluginAutomation, 0, p), false)); + if (!ac) { + return; + } + + if (ac->automation_state() & Play) { + return; + } + + ac->start_touch (timepos_t (ac->session ().audible_sample())); + ac->set_value (v, Controllable::NoGroup); + ac->stop_touch (timepos_t (ac->session ().audible_sample())); +} diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 94bee3c724..2c766c0140 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -837,23 +837,6 @@ PluginInsert::write_immediate_event (Evoral::EventType event_type, size_t size, return rv; } -void -PluginInsert::preset_load_set_value (uint32_t p, float v) -{ - boost::shared_ptr ac = automation_control (Evoral::Parameter(PluginAutomation, 0, p)); - if (!ac) { - return; - } - - if (ac->automation_state() & Play) { - return; - } - - start_touch (p); - ac->set_value (v, Controllable::NoGroup); - end_touch (p); -} - void PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, samplecnt_t nframes, samplecnt_t offset) const { @@ -2574,44 +2557,6 @@ PluginInsert::state () const return node; } -void -PluginInsert::set_control_ids (const XMLNode& node, int version) -{ - const XMLNodeList& nlist = node.children(); - for (XMLNodeConstIterator iter = nlist.begin(); iter != nlist.end(); ++iter) { - if ((*iter)->name() != Controllable::xml_node_name) { - continue; - } - - uint32_t p = (uint32_t)-1; - std::string str; - if ((*iter)->get_property (X_("symbol"), str)) { - boost::shared_ptr lv2plugin = boost::dynamic_pointer_cast (_plugins[0]); - if (lv2plugin) { - p = lv2plugin->port_index(str.c_str()); - } - } - if (p == (uint32_t)-1) { - (*iter)->get_property (X_("parameter"), p); - } - - if (p == (uint32_t)-1) { - continue; - } - - /* this may create the new controllable */ - boost::shared_ptr c = control (Evoral::Parameter (PluginAutomation, 0, p)); - - if (!c) { - continue; - } - boost::shared_ptr ac = boost::dynamic_pointer_cast (c); - if (ac) { - ac->set_state (**iter, version); - } - } -} - void PluginInsert::update_control_values (const XMLNode& node, int version) { @@ -2663,112 +2608,19 @@ PluginInsert::set_state(const XMLNode& node, int version) XMLNodeIterator niter; XMLPropertyList plist; ARDOUR::PluginType type; + std::string unique_id; - std::string str; - if (!node.get_property ("type", str)) { - error << _("XML node describing plugin is missing the `type' field") << endmsg; + if (! parse_plugin_type (node, type, unique_id)) { return -1; } - if (str == X_("ladspa") || str == X_("Ladspa")) { /* handle old school sessions */ - type = ARDOUR::LADSPA; - } else if (str == X_("lv2")) { - type = ARDOUR::LV2; - } else if (str == X_("windows-vst")) { - type = ARDOUR::Windows_VST; - } else if (str == X_("lxvst")) { - type = ARDOUR::LXVST; - } else if (str == X_("mac-vst")) { - type = ARDOUR::MacVST; - } else if (str == X_("audiounit")) { - type = ARDOUR::AudioUnit; - } else if (str == X_("luaproc")) { - type = ARDOUR::Lua; - } else if (str == X_("vst3")) { - type = ARDOUR::VST3; - } else { - error << string_compose (_("unknown plugin type %1 in plugin insert state"), str) << endmsg; - return -1; - } - - XMLProperty const* prop = node.property ("unique-id"); - - if (prop == 0) { -#ifdef WINDOWS_VST_SUPPORT - /* older sessions contain VST plugins with only an "id" field. */ - if (type == ARDOUR::Windows_VST) { - prop = node.property ("id"); - } -#endif - -#ifdef LXVST_SUPPORT - /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/ - if (type == ARDOUR::LXVST) { - prop = node.property ("id"); - } -#endif - - /* recheck */ - if (prop == 0) { - error << _("Plugin has no unique ID field") << endmsg; - return -1; - } - } - bool any_vst = false; uint32_t count = 1; node.get_property ("count", count); if (_plugins.empty()) { - /* Find and load plugin module */ - boost::shared_ptr plugin = find_plugin (_session, prop->value(), type); - - /* treat VST plugins equivalent if they have the same uniqueID - * allow to move sessions windows <> linux */ -#ifdef LXVST_SUPPORT - if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::MacVST)) { - type = ARDOUR::LXVST; - plugin = find_plugin (_session, prop->value(), type); - if (plugin) { any_vst = true; } - } -#endif - -#ifdef WINDOWS_VST_SUPPORT - if (plugin == 0 && (type == ARDOUR::LXVST || type == ARDOUR::MacVST)) { - type = ARDOUR::Windows_VST; - plugin = find_plugin (_session, prop->value(), type); - if (plugin) { any_vst = true; } - } -#endif - -#ifdef MACVST_SUPPORT - if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::LXVST)) { - type = ARDOUR::MacVST; - plugin = find_plugin (_session, prop->value(), type); - if (plugin) { any_vst = true; } - } -#endif - - if (plugin == 0 && type == ARDOUR::Lua) { - /* unique ID (sha1 of script) was not found, - * load the plugin from the serialized version in the - * session-file instead. - */ - boost::shared_ptr lp (new LuaProc (_session.engine(), _session, "")); - XMLNode *ls = node.child (lp->state_node_name().c_str()); - if (ls && lp) { - if (0 == lp->set_script_from_state (*ls)) { - plugin = lp; - } - } - } - - if (plugin == 0) { - error << string_compose( - _("Found a reference to a plugin (\"%1\") that is unknown.\n" - "Perhaps it was removed or moved since it was last used."), - prop->value()) - << endmsg; + boost::shared_ptr plugin = find_and_load_plugin (_session, node, type, unique_id, any_vst); + if (!plugin) { return -1; } @@ -2796,7 +2648,7 @@ PluginInsert::set_state(const XMLNode& node, int version) } } } else { - assert (_plugins[0]->unique_id() == prop->value()); + assert (_plugins[0]->unique_id() == unique_id); /* update controllable value only (copy plugin state) */ set_id (node); update_control_values (node, version); diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 504ed6d185..67ce48db51 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -174,6 +174,7 @@ libardour_sources = [ 'playlist.cc', 'playlist_factory.cc', 'playlist_source.cc', + 'plug_insert_base.cc', 'plugin.cc', 'plugin_insert.cc', 'plugin_manager.cc',