From edd1061c3d8822ab586e2bbc80894e125b521a52 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 6 Feb 2017 16:18:09 +0100 Subject: save/restore VCA master state inside slaves, so that a reloaded session ends up back in the same state --- libs/ardour/slavable_automation_control.cc | 127 +++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 5 deletions(-) (limited to 'libs/ardour/slavable_automation_control.cc') diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc index 31e81a2931..b76f91b13b 100644 --- a/libs/ardour/slavable_automation_control.cc +++ b/libs/ardour/slavable_automation_control.cc @@ -20,6 +20,8 @@ #define __libardour_slavable_automation_control_h__ #include "pbd/enumwriter.h" +#include "pbd/error.h" +#include "pbd/i18n.h" #include "ardour/slavable_automation_control.h" #include "ardour/session.h" @@ -35,9 +37,18 @@ SlavableAutomationControl::SlavableAutomationControl(ARDOUR::Session& s, const std::string& name, Controllable::Flag flags) : AutomationControl (s, parameter, desc, l, name, flags) + , _masters_node (0) { } +SlavableAutomationControl::~SlavableAutomationControl () +{ + if (_masters_node) { + delete _masters_node; + _masters_node = 0; + } +} + double SlavableAutomationControl::get_masters_value_locked () const { @@ -116,7 +127,7 @@ SlavableAutomationControl::actually_set_value (double val, Controllable::GroupCo } void -SlavableAutomationControl::add_master (boost::shared_ptr m) +SlavableAutomationControl::add_master (boost::shared_ptr m, bool loading) { std::pair res; @@ -131,7 +142,9 @@ SlavableAutomationControl::add_master (boost::shared_ptr m) if (res.second) { - recompute_masters_ratios (current_value); + if (!loading) { + recompute_masters_ratios (current_value); + } /* note that we bind @param m as a weak_ptr, thus avoiding holding a reference to the control in the binding @@ -143,11 +156,11 @@ SlavableAutomationControl::add_master (boost::shared_ptr m) /* Store the connection inside the MasterRecord, so that when we destroy it, the connection is destroyed and we no longer hear about changes to the - AutomationControl. + AutomationControl. Note that this also makes it safe to store a boost::shared_ptr in the functor, - since we know we will destroy the functor when the + since we know we will destroy the functor when the connection is destroyed, which happens when we disconnect from the master (for any reason). @@ -157,7 +170,6 @@ SlavableAutomationControl::add_master (boost::shared_ptr m) */ m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&SlavableAutomationControl::master_changed, this, _1, _2, m)); - cerr << this << enum_2_string ((AutomationType) _parameter.type()) << " now listening to Changed from " << m << endl; } } @@ -330,4 +342,109 @@ SlavableAutomationControl::slaved () const return !_masters.empty(); } +void +SlavableAutomationControl::use_saved_master_ratios () +{ + if (!_masters_node) { + return; + } + + Glib::Threads::RWLock::ReaderLock lm (master_lock); + + /* use stored state, do not recompute */ + + if (_desc.toggled) { + + XMLNodeList nlist = _masters_node->children(); + XMLNodeIterator niter; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + XMLProperty const * id_prop = (*niter)->property (X_("id")); + if (!id_prop) { + continue; + } + XMLProperty const * yn_prop = (*niter)->property (X_("yn")); + if (!yn_prop) { + continue; + } + Masters::iterator mi = _masters.find (ID (id_prop->value())); + if (mi != _masters.end()) { + mi->second.set_yn (string_is_affirmative (yn_prop->value())); + } + } + + } else { + + XMLProperty const * prop = _masters_node->property (X_("ratio")); + + if (prop) { + + gain_t ratio; + sscanf (prop->value().c_str(), "%g", &ratio); + + for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) { + mr->second.reset_ratio (ratio); + } + } else { + PBD::error << string_compose (_("programming error: %1"), X_("missing ratio information for control slave"))<< endmsg; + } + } + + delete _masters_node; + _masters_node = 0; + + return; +} + + +XMLNode& +SlavableAutomationControl::get_state () +{ + XMLNode& node (AutomationControl::get_state()); + + /* store VCA master ratios */ + + { + Glib::Threads::RWLock::ReaderLock lm (master_lock); + + if (!_masters.empty()) { + + XMLNode* masters_node = new XMLNode (X_("masters")); + + if (_desc.toggled) { + for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) { + XMLNode* mnode = new XMLNode (X_("master")); + mnode->add_property (X_("id"), mr->second.master()->id().to_s()); + mnode->add_property (X_("yn"), mr->second.yn()); + masters_node->add_child_nocopy (*mnode); + } + } else { + XMLNode* masters_node = new XMLNode (X_("masters")); + /* ratio is the same for all masters, so just store one */ + masters_node->add_property (X_("ratio"), PBD::to_string (_masters.begin()->second.ratio(), std::dec)); + } + + node.add_child_nocopy (*masters_node); + } + } + + return node; +} + +int +SlavableAutomationControl::set_state (XMLNode const& node, int version) +{ + XMLNodeList nlist = node.children(); + XMLNodeIterator niter; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + if ((*niter)->name() == X_("masters")) { + _masters_node = new XMLNode (**niter); + } + } + + return AutomationControl::set_state (node, version); +} + + #endif /* __libardour_slavable_automation_control_h__ */ -- cgit v1.2.3