*/
+#include <vector>
+
#include <glibmm/threads.h>
#include "pbd/convert.h"
+#include "pbd/error.h"
#include "pbd/xml++.h"
#include "ardour/slavable.h"
+#include "ardour/slavable_automation_control.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;
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);
}
}
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());
}
}
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());
}
+
+int
+Slavable::assign_controls (boost::shared_ptr<VCA> vca)
+{
+ boost::shared_ptr<SlavableAutomationControl> slave;
+ boost::shared_ptr<AutomationControl> master;
+ AutomationType types[] = {
+ GainAutomation,
+ SoloAutomation,
+ MuteAutomation,
+ RecEnableAutomation,
+ MonitoringAutomation,
+ NullAutomation
+ };
+
+ for (uint32_t n = 0; types[n] != NullAutomation; ++n) {
+
+ slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (types[n]));
+ master = vca->automation_control (types[n]);
+
+ if (slave && master) {
+ slave->add_master (master);
+ }
+ }
+
+ return 0;
+}
+
+int
+Slavable::unassign_controls (boost::shared_ptr<VCA> vca)
+{
+ boost::shared_ptr<SlavableAutomationControl> slave;
+ boost::shared_ptr<AutomationControl> master;
+ AutomationType types[] = {
+ GainAutomation,
+ SoloAutomation,
+ MuteAutomation,
+ RecEnableAutomation,
+ MonitoringAutomation,
+ NullAutomation
+ };
+
+ for (uint32_t n = 0; types[n] != NullAutomation; ++n) {
+
+ slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (types[n]));
+ if (!vca) {
+ /* unassign from all */
+ slave->clear_masters ();
+ } else {
+ slave->remove_master (master);
+ }
+ }
+
+ return 0;
+}
+