Update Spanish translation
[ardour.git] / libs / ardour / slavable.cc
index 7a7b8e291947bc4c85d66b4293357414426f5de5..10eb08437250cc372d37d5d79d74636d6ecfb839 100644 (file)
 #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"
+#include "pbd/i18n.h"
 
 using namespace PBD;
 using namespace ARDOUR;
@@ -82,6 +83,7 @@ Slavable::set_state (XMLNode const& node, int version)
        return 0;
 }
 
+
 int
 Slavable::do_assign (VCAManager* manager)
 {
@@ -114,10 +116,29 @@ Slavable::do_assign (VCAManager* manager)
 void
 Slavable::assign (boost::shared_ptr<VCA> v)
 {
+       assert (v);
        Glib::Threads::RWLock::WriterLock lm (master_lock);
        if (assign_controls (v) == 0) {
                _masters.insert (v->number());
        }
+
+       /* Do NOT use ::unassign() because it will store a
+        * boost::shared_ptr<VCA> in the functor, leaving a dangling ref to the
+        * VCA.
+        */
+
+
+       v->Drop.connect_same_thread (unassign_connections, boost::bind (&Slavable::weak_unassign, this, boost::weak_ptr<VCA>(v)));
+       v->DropReferences.connect_same_thread (unassign_connections, boost::bind (&Slavable::weak_unassign, this, boost::weak_ptr<VCA>(v)));
+}
+
+void
+Slavable::weak_unassign (boost::weak_ptr<VCA> v)
+{
+       boost::shared_ptr<VCA> sv (v.lock());
+       if (sv) {
+               unassign (sv);
+       }
 }
 
 void
@@ -125,5 +146,65 @@ Slavable::unassign (boost::shared_ptr<VCA> v)
 {
        Glib::Threads::RWLock::WriterLock lm (master_lock);
        (void) unassign_controls (v);
-       _masters.erase (v->number());
+       if (v) {
+               _masters.erase (v->number());
+       } else {
+               _masters.clear ();
+       }
+}
+
+/* Gain, solo & mute are currently the only controls that are
+ * automatically slaved to the master's own equivalent controls.
+ */
+
+static AutomationType auto_slave_types[] = {
+       GainAutomation,
+       SoloAutomation,
+       MuteAutomation,
+       NullAutomation
+};
+
+int
+Slavable::assign_controls (boost::shared_ptr<VCA> vca)
+{
+       boost::shared_ptr<SlavableAutomationControl> slave;
+       boost::shared_ptr<AutomationControl> master;
+
+       for (uint32_t n = 0; auto_slave_types[n] != NullAutomation; ++n) {
+
+               slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (auto_slave_types[n]));
+               master = vca->automation_control (auto_slave_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;
+
+       for (uint32_t n = 0; auto_slave_types[n] != NullAutomation; ++n) {
+
+               slave = boost::dynamic_pointer_cast<SlavableAutomationControl> (automation_control (auto_slave_types[n]));
+
+               if (!vca) {
+                       /* unassign from all */
+                       if (slave) {
+                               slave->clear_masters ();
+                       }
+               } else {
+                       master = vca->automation_control (auto_slave_types[n]);
+                       if (slave && master) {
+                               slave->remove_master (master);
+                       }
+               }
+       }
+
+       return 0;
 }