summaryrefslogtreecommitdiff
path: root/libs/ardour/slavable_automation_control.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-06-09 22:54:09 +0200
committerRobin Gareus <robin@gareus.org>2017-06-09 23:25:42 +0200
commita1b4f9b8abf2887b17bce05403ea7eab2421f26a (patch)
treea104cbcde53d6efa1959ac451a43088292ee85d4 /libs/ardour/slavable_automation_control.cc
parent8502aa18c5e69cee79780d370ab6fa88cf7de484 (diff)
Fix deletion of VCA with slaved controls.
The crashed previously because: A VCA is-a Automatable is-a Evoral::ControlSet After VCA's d'tor completes ~Automatable runs and emits signal to DropReferences of all master-controls. This in turn calls SlavableAutomationControl::master_going_away() for slaved parameters for the given master-control In ::master_going_away() the weak-pointer reference to the master's AutomationControl (owned by the destroyed VCA) is still valid. Execution is in the d'tor of Automatable which is-a ControlSet and the ContolSet keeps a reference to the Control and hence also to the AutomationControl which is-a Evoral::Control. So master_going_away() locks a boost::shared_ptr<ARDOUR::AutomationControl> which is actually the MuteControl owned by the VCA. It calls SlavableAutomationControl::remove_master() which in turn calls MuteControl::pre_remove_master() which uses the MuteMaster API to retrieve the value. The MuteMaster however is the VCA that has just been destroyed. The solution is twofold: 1) emit "drop_references" from the VCA d'tor itself, before the VCA is destroyed. 2) disconnect a slaved control from the master's drop_references signal when un-assigning a master-control.
Diffstat (limited to 'libs/ardour/slavable_automation_control.cc')
-rw-r--r--libs/ardour/slavable_automation_control.cc7
1 files changed, 5 insertions, 2 deletions
diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc
index 40f4cb486f..5f24a8786f 100644
--- a/libs/ardour/slavable_automation_control.cc
+++ b/libs/ardour/slavable_automation_control.cc
@@ -222,8 +222,10 @@ SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m, b
avoiding holding a reference to the control in the binding
itself.
*/
-
- m->DropReferences.connect_same_thread (masters_connections, boost::bind (&SlavableAutomationControl::master_going_away, this, boost::weak_ptr<AutomationControl>(m)));
+ assert (masters_connections.find (boost::weak_ptr<AutomationControl>(m)) == masters_connections.end());
+ PBD::ScopedConnection con;
+ m->DropReferences.connect_same_thread (con, boost::bind (&SlavableAutomationControl::master_going_away, this, boost::weak_ptr<AutomationControl>(m)));
+ masters_connections[boost::weak_ptr<AutomationControl>(m)] = con;
/* Store the connection inside the MasterRecord, so
that when we destroy it, the connection is destroyed
@@ -326,6 +328,7 @@ SlavableAutomationControl::master_going_away (boost::weak_ptr<AutomationControl>
void
SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
{
+ masters_connections.erase (boost::weak_ptr<AutomationControl>(m));
pre_remove_master (m);
{