diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index 570b48de9a..9e76a9d5bc 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -396,6 +396,7 @@ private: 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 (); void bypassable_changed (); diff --git a/libs/ardour/export_formats.cc b/libs/ardour/export_formats.cc index 718dcd81c6..b6c090652c 100644 --- a/libs/ardour/export_formats.cc +++ b/libs/ardour/export_formats.cc @@ -413,6 +413,7 @@ ExportFormatFFMPEG::ExportFormatFFMPEG (std::string const& name, std::string con add_codec_quality ("CBR 160 kb/s", 160); add_codec_quality ("CBR 192 kb/s", 192); add_codec_quality ("CBR 256 kb/s", 256); + add_codec_quality ("CBR 320 kb/s", 320); set_extension (ext); set_quality (Q_LossyCompression); diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index c4a1e0c24f..2b45e9e28a 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -2197,7 +2197,17 @@ LV2Plugin::set_state(const XMLNode& node, int version) set_state_dir (""); } - latency_compute_run(); + /* Do not call latency_compute_run() concurrently with connect_and_run(). + * So far this can only guarnteed when the session is loading, + * and the plugin has not been added to the processor chain. + * + * Ideally this would clso be called when copying a plugin from another track, + * but NOT when copying the state from a plugin to another (active) plugin + * instance. + */ + if (_session.loading ()) { + latency_compute_run(); + } #endif return Plugin::set_state(node, version); diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 3a7aff34ab..8d34c4f1e4 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -2498,43 +2498,85 @@ void PluginInsert::set_control_ids (const XMLNode& node, int version) { const XMLNodeList& nlist = node.children(); - XMLNodeConstIterator iter; - set::const_iterator p; + for (XMLNodeConstIterator iter = nlist.begin(); iter != nlist.end(); ++iter) { + if ((*iter)->name() != Controllable::xml_node_name) { + continue; + } - for (iter = nlist.begin(); iter != nlist.end(); ++iter) { - if ((*iter)->name() == Controllable::xml_node_name) { - - uint32_t p = (uint32_t)-1; + uint32_t p = (uint32_t)-1; #ifdef LV2_SUPPORT - 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()); - } + 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()); } + } #endif - if (p == (uint32_t)-1) { - (*iter)->get_property (X_("parameter"), p); - } + if (p == (uint32_t)-1) { + (*iter)->get_property (X_("parameter"), p); + } - if (p != (uint32_t)-1) { + if (p == (uint32_t)-1) { + continue; + } - /* this may create the new controllable */ - - boost::shared_ptr c = control (Evoral::Parameter (PluginAutomation, 0, p)); + /* this may create the new controllable */ + boost::shared_ptr c = control (Evoral::Parameter (PluginAutomation, 0, p)); #ifndef NO_PLUGIN_STATE - if (!c) { - continue; - } - boost::shared_ptr ac = boost::dynamic_pointer_cast (c); - if (ac) { - ac->set_state (**iter, version); - } + if (!c) { + continue; + } + boost::shared_ptr ac = boost::dynamic_pointer_cast (c); + if (ac) { + ac->set_state (**iter, version); + } #endif + } +} + +void +PluginInsert::update_control_values (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; + } + + float val; + if (!(*iter)->get_property (X_("value"), val)) { + continue; + } + + uint32_t p = (uint32_t)-1; +#ifdef LV2_SUPPORT + 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()); } } +#endif + if (p == (uint32_t)-1) { + (*iter)->get_property (X_("parameter"), p); + } + + if (p == (uint32_t)-1) { + continue; + } + + /* lookup controllable */ + boost::shared_ptr c = control (Evoral::Parameter (PluginAutomation, 0, p), false); + if (!c) { + continue; + } + boost::shared_ptr ac = boost::dynamic_pointer_cast (c); + if (ac) { + ac->set_value (val, Controllable::NoGroup); + } } } @@ -2661,11 +2703,14 @@ PluginInsert::set_state(const XMLNode& node, int version) if (_plugins.empty()) { /* if we are adding the first plugin, we will need to set - up automatable controls. + * up automatable controls. */ add_plugin (plugin); create_automatable_parameters (); set_control_ids (node, version); + } else { + /* update controllable value only (copy plugin state) */ + update_control_values (node, version); } node.get_property ("count", count);