diff options
-rw-r--r-- | libs/ardour/ardour/gain_control.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/slavable.h | 14 | ||||
-rw-r--r-- | libs/ardour/ardour/vca_manager.h | 1 | ||||
-rw-r--r-- | libs/ardour/gain_control.cc | 44 | ||||
-rw-r--r-- | libs/ardour/route.cc | 15 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 4 | ||||
-rw-r--r-- | libs/ardour/slavable.cc | 65 | ||||
-rw-r--r-- | libs/ardour/vca.cc | 4 | ||||
-rw-r--r-- | libs/ardour/vca_manager.cc | 2 |
9 files changed, 87 insertions, 66 deletions
diff --git a/libs/ardour/ardour/gain_control.h b/libs/ardour/ardour/gain_control.h index f7041fff78..f72320f1dd 100644 --- a/libs/ardour/ardour/gain_control.h +++ b/libs/ardour/ardour/gain_control.h @@ -54,10 +54,6 @@ class LIBARDOUR_API GainControl : public SlavableAutomationControl { void inc_gain (gain_t); private: - std::string masters_string; - PBD::ScopedConnection vca_loaded_connection; - - void vcas_loaded(); void recompute_masters_ratios (double val); }; diff --git a/libs/ardour/ardour/slavable.h b/libs/ardour/ardour/slavable.h index ae53caef38..b0ef33e1b4 100644 --- a/libs/ardour/ardour/slavable.h +++ b/libs/ardour/ardour/slavable.h @@ -26,12 +26,14 @@ #include <boost/shared_ptr.hpp> +#include <pbd/signals.h> + class XMLNode; namespace ARDOUR { class VCA; -class Session; +class VCAManager; class Slavable { @@ -39,14 +41,17 @@ class Slavable Slavable (); virtual ~Slavable() {} - XMLNode& state () const; - int assign (Session& s, XMLNode const&); + XMLNode& get_state () const; + int set_state (XMLNode const&, int); void assign (boost::shared_ptr<VCA>); void unassign (boost::shared_ptr<VCA>); static std::string xml_node_name; + /* signal sent VCAManager once assignment is possible */ + static PBD::Signal1<void,VCAManager*> Assign; + protected: virtual int assign_controls (boost::shared_ptr<VCA>) = 0; virtual int unassign_controls (boost::shared_ptr<VCA>) = 0; @@ -54,6 +59,9 @@ class Slavable private: mutable Glib::Threads::RWLock master_lock; std::set<uint32_t> _masters; + PBD::ScopedConnection assign_connection; + + int do_assign (VCAManager* s); }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/vca_manager.h b/libs/ardour/ardour/vca_manager.h index d18044a8df..5102d14698 100644 --- a/libs/ardour/ardour/vca_manager.h +++ b/libs/ardour/ardour/vca_manager.h @@ -50,7 +50,6 @@ class VCAManager : public SessionHandleRef, public PBD::StatefulDestructible VCAList vcas() const; - PBD::Signal0<void> VCAsLoaded; PBD::Signal1<void,VCAList&> VCAAdded; PBD::Signal1<void,VCAList&> VCARemoved; diff --git a/libs/ardour/gain_control.cc b/libs/ardour/gain_control.cc index 3ffeb057da..ef560085cc 100644 --- a/libs/ardour/gain_control.cc +++ b/libs/ardour/gain_control.cc @@ -178,48 +178,6 @@ GainControl::get_state () int GainControl::set_state (XMLNode const& node, int version) { - AutomationControl::set_state (node, version); - -#if 0 - XMLProperty const* prop = node.property (X_("masters")); - - /* Problem here if we allow VCA's to be slaved to other VCA's .. we - * have to load all VCAs first, then set up slave/master relationships - * once we have them all. - */ - - if (prop) { - masters_string = prop->value (); - - if (_session.vca_manager().vcas_loaded()) { - vcas_loaded (); - } else { - _session.vca_manager().VCAsLoaded.connect_same_thread (vca_loaded_connection, boost::bind (&GainControl::vcas_loaded, this)); - } - } -#endif - - return 0; -} - -void -GainControl::vcas_loaded () -{ - if (masters_string.empty()) { - return; - } - - vector<string> masters; - split (masters_string, masters, ','); - - for (vector<string>::const_iterator m = masters.begin(); m != masters.end(); ++m) { - boost::shared_ptr<VCA> vca = _session.vca_manager().vca_by_number (PBD::atoi (*m)); - if (vca) { - add_master (vca->gain_control()); - } - } - - vca_loaded_connection.disconnect (); - masters_string.clear (); + return AutomationControl::set_state (node, version); } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 301c7ba5c0..3e424a9603 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -2447,6 +2447,8 @@ Route::state(bool full_state) foreach_processor (sigc::bind (sigc::mem_fun (*this, &Route::set_plugin_state_dir), "")); } + node->add_child_copy (Slavable::get_state()); + return *node; } @@ -2517,21 +2519,16 @@ Route::set_state (const XMLNode& node, int version) } else if (prop->value() == "Output") { _output->set_state (*child, version); } - } - if (child->name() == X_("Processor")) { + } else if (child->name() == X_("Processor")) { processor_state.add_child_copy (*child); - } - - if (child->name() == X_("Pannable")) { + } else if (child->name() == X_("Pannable")) { if (_pannable) { _pannable->set_state (*child, version); } else { warning << string_compose (_("Pannable state found for route (%1) without a panner!"), name()) << endmsg; } - } - - if (child->name() == Controllable::xml_node_name) { + } else if (child->name() == Controllable::xml_node_name) { if ((prop = child->property (X_("name"))) == 0) { continue; } @@ -2547,6 +2544,8 @@ Route::set_state (const XMLNode& node, int version) } else if (prop->value() == _solo_control->name()) { _mute_control->set_state (*child, version); } + } else if (child->name() == Slavable::xml_node_name) { + Slavable::set_state (*child, version); } } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 4d5ffbffa7..ebbd37e4f9 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -1486,6 +1486,10 @@ Session::set_state (const XMLNode& node, int version) goto out; } + /* Now that we have Routes and masters loaded, connect them if appropriate */ + + Slavable::Assign (_vca_manager); /* EMIT SIGNAL */ + /* our diskstreams list is no longer needed as they are now all owned by their Route */ _diskstreams_2X.clear (); diff --git a/libs/ardour/slavable.cc b/libs/ardour/slavable.cc index 989c2ec663..7a7b8e2919 100644 --- a/libs/ardour/slavable.cc +++ b/libs/ardour/slavable.cc @@ -17,27 +17,34 @@ */ +#include <vector> + #include <glibmm/threads.h> #include "pbd/convert.h" +#include "pbd/error.h" #include "pbd/xml++.h" #include "ardour/slavable.h" #include "ardour/vca.h" +#include "ardour/vca_manager.h" #include "i18n.h" +using namespace PBD; using namespace ARDOUR; std::string Slavable::xml_node_name = X_("Slavable"); +PBD::Signal1<void,VCAManager*> Slavable::Assign; /* signal sent once + * assignment is possible */ Slavable::Slavable () { - + Assign.connect_same_thread (assign_connection, boost::bind (&Slavable::do_assign, this, _1)); } XMLNode& -Slavable::state () const +Slavable::get_state () const { XMLNode* node = new XMLNode (xml_node_name); XMLNode* child; @@ -45,7 +52,7 @@ Slavable::state () const Glib::Threads::RWLock::ReaderLock lm (master_lock); for (std::set<uint32_t>::const_iterator i = _masters.begin(); i != _masters.end(); ++i) { child = new XMLNode (X_("Master")); - child->add_property (X_("number"), PBD::to_string (*i, std::dec)); + child->add_property (X_("number"), to_string (*i, std::dec)); node->add_child_nocopy (*child); } @@ -53,16 +60,62 @@ Slavable::state () const } int -Slavable::assign (Session& s, XMLNode const& node) +Slavable::set_state (XMLNode const& node, int version) +{ + if (node.name() != xml_node_name) { + return -1; + } + + XMLNodeList const& children (node.children()); + Glib::Threads::RWLock::WriterLock lm (master_lock); + + for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) { + if ((*i)->name() == X_("Master")) { + XMLProperty const* prop = (*i)->property (X_("number")); + if (prop) { + uint32_t n = atoi (prop->value()); + _masters.insert (n); + } + } + } + + return 0; +} + +int +Slavable::do_assign (VCAManager* manager) { + std::vector<boost::shared_ptr<VCA> > vcas; + + { + Glib::Threads::RWLock::ReaderLock lm (master_lock); + + for (std::set<uint32_t>::const_iterator i = _masters.begin(); i != _masters.end(); ++i) { + boost::shared_ptr<VCA> v = manager->vca_by_number (*i); + if (v) { + vcas.push_back (v); + } else { + warning << string_compose (_("Master #%1 not found, assignment lost"), *i) << endmsg; + } + } + } + + /* now that we've released the lock, we can do the assignments */ + + for (std::vector<boost::shared_ptr<VCA> >::iterator v = vcas.begin(); v != vcas.end(); ++v) { + assign (*v); + } + + assign_connection.disconnect (); + return 0; } void Slavable::assign (boost::shared_ptr<VCA> v) { + Glib::Threads::RWLock::WriterLock lm (master_lock); if (assign_controls (v) == 0) { - Glib::Threads::RWLock::WriterLock lm (master_lock); _masters.insert (v->number()); } } @@ -70,7 +123,7 @@ Slavable::assign (boost::shared_ptr<VCA> v) void Slavable::unassign (boost::shared_ptr<VCA> v) { - (void) unassign_controls (v); Glib::Threads::RWLock::WriterLock lm (master_lock); + (void) unassign_controls (v); _masters.erase (v->number()); } diff --git a/libs/ardour/vca.cc b/libs/ardour/vca.cc index 2ab84d5570..72c0a2cdcb 100644 --- a/libs/ardour/vca.cc +++ b/libs/ardour/vca.cc @@ -106,6 +106,8 @@ VCA::get_state () node->add_child_nocopy (_mute_control->get_state()); node->add_child_nocopy (get_automation_xml_state()); + node->add_child_nocopy (Slavable::get_state()); + return *node; } @@ -141,6 +143,8 @@ VCA::set_state (XMLNode const& node, int version) if (prop->value() == _mute_control->name()) { _mute_control->set_state (**i, version); } + } else if ((*i)->name() == Slavable::xml_node_name) { + Slavable::set_state (**i, version); } } diff --git a/libs/ardour/vca_manager.cc b/libs/ardour/vca_manager.cc index e0d7e0fc82..e6143ea0b2 100644 --- a/libs/ardour/vca_manager.cc +++ b/libs/ardour/vca_manager.cc @@ -21,6 +21,7 @@ #include "pbd/error.h" #include "pbd/replace_all.h" +#include "ardour/slavable.h" #include "ardour/vca.h" #include "ardour/vca_manager.h" @@ -175,7 +176,6 @@ VCAManager::set_state (XMLNode const& node, int version) _vcas_loaded = true; - VCAsLoaded (); /* EMIT SIGNAL */ VCAAdded (vcal); /* EMIT SIGNAL */ return 0; |