save and restore vca assignments

This commit is contained in:
Paul Davis 2016-04-25 11:03:08 -04:00
parent 760beab7fa
commit 1e9b2abe73
9 changed files with 87 additions and 66 deletions

View File

@ -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);
};

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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 ();

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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;