From 4650d86312e7c191d208eefb03c299bfc1b4c031 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 16 Oct 2009 16:44:16 +0000 Subject: more set_state() tweaks to aid with plugin state loading git-svn-id: svn://localhost/ardour2/branches/3.0@5791 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/plugin.h | 3 - libs/ardour/ardour/plugin_insert.h | 3 +- libs/ardour/plugin_insert.cc | 192 +++++++++++++++++++++++++------------ 3 files changed, 135 insertions(+), 63 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index d80f299385..aeec4ee32e 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -176,9 +176,6 @@ class Plugin : public PBD::StatefulDestructible, public Latent virtual ChanCount output_streams() const; virtual ChanCount input_streams() const; - PBD::Controllable *get_nth_control (uint32_t, bool do_not_create = false); - void make_nth_control (uint32_t, const XMLNode&); - PluginInfoPtr get_info() { return _info; } void set_info (const PluginInfoPtr inf) { _info = inf; } diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index ea8228f5fc..348cda218e 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -134,9 +134,10 @@ class PluginInsert : public Processor void automation_run (BufferSet& bufs, nframes_t nframes); void connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now = 0); - void init (); void set_automatable (); void auto_state_changed (Evoral::Parameter which); + void set_parameter_state (const XMLNode& node, int version); + void set_parameter_state_2X (const XMLNode& node, int version); int32_t count_for_configuration (ChanCount in, ChanCount out) const; diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 2a5ef29a45..1d9d274a09 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -70,8 +70,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr plug) /* the first is the master */ _plugins.push_back (plug); - - init (); + set_automatable (); { Glib::Mutex::Lock em (_session.engine().process_lock()); @@ -90,11 +89,6 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node) throw failed_constructor(); } - // XXX: This would dump all automation, which has already been loaded by - // Processor. But this could also have been related to the Parameter change.. - // will look into this later. - //set_automatable (); - { Glib::Mutex::Lock em (_session.engine().process_lock()); IO::PortCountChanged (max(input_streams(), output_streams())); @@ -133,12 +127,6 @@ PluginInsert::set_count (uint32_t num) return true; } -void -PluginInsert::init () -{ - set_automatable (); -} - PluginInsert::~PluginInsert () { GoingAway (); /* EMIT SIGNAL */ @@ -695,22 +683,22 @@ PluginInsert::state (bool full) node.add_child_nocopy (_plugins[0]->get_state()); /* add port automation state */ - //XMLNode *autonode = new XMLNode(port_automation_node_name); + XMLNode *autonode = new XMLNode(port_automation_node_name); set automatable = _plugins[0]->automatable(); for (set::iterator x = automatable.begin(); x != automatable.end(); ++x) { - + /*XMLNode* child = new XMLNode("port"); snprintf(buf, sizeof(buf), "%" PRIu32, *x); child->add_property("number", string(buf)); - + child->add_child_nocopy (automation_list (*x).state (full)); autonode->add_child_nocopy (*child); */ - //autonode->add_child_nocopy (((AutomationList*)data().control(*x)->list().get())->state (full)); + autonode->add_child_nocopy (((AutomationList*)data().control(*x)->list().get())->state (full)); } - //node.add_child_nocopy (*autonode); + node.add_child_nocopy (*autonode); return node; } @@ -725,7 +713,7 @@ PluginInsert::set_state(const XMLNode& node, int version) ARDOUR::PluginType type; if ((prop = node.property ("type")) == 0) { - error << _("XML node describing insert is missing the `type' field") << endmsg; + error << _("XML node describing plugin is missing the `type' field") << endmsg; return -1; } @@ -736,6 +724,8 @@ PluginInsert::set_state(const XMLNode& node, int version) type = ARDOUR::LV2; } else if (prop->value() == X_("vst")) { type = ARDOUR::VST; + } else if (prop->value() == X_("audiounit")) { + type = ARDOUR::AudioUnit; } else { error << string_compose (_("unknown plugin type %1 in plugin insert state"), prop->value()) @@ -744,12 +734,26 @@ PluginInsert::set_state(const XMLNode& node, int version) } prop = node.property ("unique-id"); - cout << "- ID " << prop->value() << "\n"; + if (prop == 0) { - error << _("Plugin has no unique ID field") << endmsg; - return -1; +#ifdef VST_SUPPORT + /* older sessions contain VST plugins with only an "id" field. + */ + + if (type == ARDOUR::VST) { + prop = node.property ("id"); + } +#endif + /* recheck */ + + if (prop == 0) { + error << _("Plugin has no unique ID field") << endmsg; + return -1; + } } + cout << "- ID " << prop->value() << "\n"; + boost::shared_ptr plugin; plugin = find_plugin (_session, prop->value(), type); @@ -762,6 +766,14 @@ PluginInsert::set_state(const XMLNode& node, int version) } uint32_t count = 1; + bool need_automatables = true; + + if (_plugins.empty()) { + /* if we are adding the first plugin, we will need to set + up automatable controls. + */ + need_automatables = true; + } if ((prop = node.property ("count")) != 0) { sscanf (prop->value().c_str(), "%u", &count); @@ -771,11 +783,15 @@ PluginInsert::set_state(const XMLNode& node, int version) _plugins.push_back (plugin); - for (uint32_t n=1; n < count; ++n) { + for (uint32_t n = 1; n < count; ++n) { _plugins.push_back (plugin_factory (plugin)); } } + if (need_automatables) { + set_automatable (); + } + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { if ((*niter)->name() == plugin->state_node_name()) { for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { @@ -785,26 +801,38 @@ PluginInsert::set_state(const XMLNode& node, int version) } } - const XMLNode* insert_node = &node; - - // legacy sessions: search for child IOProcessor node - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - if ((*niter)->name() == "IOProcessor") { - insert_node = *niter; - break; + if (version < 3000) { + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + if ((*niter)->name() == "Redirect") { + /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */ + Processor::set_state (**niter, version); + break; + } } + set_parameter_state_2X (node, version); + } else { + Processor::set_state (node, version); + set_parameter_state (node, version); } - - Processor::set_state (*insert_node, version); - /* look for port automation node */ + // The name of the PluginInsert comes from the plugin, nothing else + _name = plugin->get_info()->name; - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + return 0; +} +void +PluginInsert::set_parameter_state (const XMLNode& node, int version) +{ + XMLNodeList nlist = node.children(); + XMLNodeIterator niter; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + if ((*niter)->name() != port_automation_node_name) { continue; } - + XMLNodeList cnodes; XMLProperty *cprop; XMLNodeConstIterator iter; @@ -812,61 +840,107 @@ PluginInsert::set_state(const XMLNode& node, int version) const char *port; uint32_t port_id; - cnodes = (*niter)->children ("Port"); + cnodes = (*niter)->children ("AutomationList"); for (iter = cnodes.begin(); iter != cnodes.end(); ++iter) { child = *iter; - if ((cprop = child->property("number")) != 0) { + /* XXX this code knows way too much about the internal details of an AutomationList state node */ + + if ((cprop = child->property("automation-id")) != 0) { port = cprop->value().c_str(); } else { - warning << _("PluginInsert: Auto: no plugin port number") << endmsg; + warning << _("PluginInsert: Auto: no plugin parameter number seen") << endmsg; continue; } - sscanf (port, "%" PRIu32, &port_id); + if (sscanf (port, "parameter-%" PRIu32, &port_id) != 1) { + warning << _("PluginInsert: Auto: no parameter number found") << endmsg; + continue; + } if (port_id >= _plugins[0]->parameter_count()) { - warning << _("PluginInsert: Auto: port id out of range") << endmsg; + warning << _("PluginInsert: Auto: plugin parameter out of range") << endmsg; continue; } boost::shared_ptr c = boost::dynamic_pointer_cast( data().control(Evoral::Parameter(PluginAutomation, 0, port_id), true)); - if (!child->children().empty()) { - c->alist()->set_state (*child->children().front(), version); + if (c) { + c->alist()->set_state (*child, version); } else { - if ((cprop = child->property("auto")) != 0) { + error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg; + } + } - /* old school */ + /* done */ + + break; + } +} - int x; - sscanf (cprop->value().c_str(), "0x%x", &x); - c->alist()->set_automation_state (AutoState (x)); +void +PluginInsert::set_parameter_state_2X (const XMLNode& node, int version) +{ + XMLNodeList nlist = node.children(); + XMLNodeIterator niter; - } else { + /* look for port automation node */ + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - /* missing */ + if ((*niter)->name() != port_automation_node_name) { + continue; + } - c->alist()->set_automation_state (Off); - } + XMLNodeList cnodes; + XMLProperty *cprop; + XMLNodeConstIterator iter; + XMLNode *child; + const char *port; + uint32_t port_id; + + cnodes = (*niter)->children ("port"); + + for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){ + + child = *iter; + + if ((cprop = child->property("number")) != 0) { + port = cprop->value().c_str(); + } else { + warning << _("PluginInsert: Auto: no ladspa port number") << endmsg; + continue; + } + + sscanf (port, "%" PRIu32, &port_id); + + if (port_id >= _plugins[0]->parameter_count()) { + warning << _("PluginInsert: Auto: port id out of range") << endmsg; + continue; } - } + boost::shared_ptr c = boost::dynamic_pointer_cast( + data().control(Evoral::Parameter(PluginAutomation, 0, port_id), true)); + if (c) { + if (!child->children().empty()) { + c->alist()->set_state (*child->children().front(), version); + } + } else { + error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg; + } + } + /* done */ - + break; - } - - // The name of the PluginInsert comes from the plugin, nothing else - _name = plugin->get_info()->name; - - return 0; + } } + string PluginInsert::describe_parameter (Evoral::Parameter param) { -- cgit v1.2.3