summaryrefslogtreecommitdiff
path: root/libs/ardour/slavable_automation_control.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-06-10 14:36:03 +0200
committerRobin Gareus <robin@gareus.org>2017-06-10 14:38:21 +0200
commit2bc2aea009d967fa23f9b04f0dbd2919e68aecb4 (patch)
tree0a55e19ae21041caf0c543982c1780bf4a8f972e /libs/ardour/slavable_automation_control.cc
parent50c54250040509080f7686b64739ef94e6d29e51 (diff)
Implement slaved boolean automation and update mute special-case
Diffstat (limited to 'libs/ardour/slavable_automation_control.cc')
-rw-r--r--libs/ardour/slavable_automation_control.cc70
1 files changed, 69 insertions, 1 deletions
diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc
index c912d16370..8a7a8ba00f 100644
--- a/libs/ardour/slavable_automation_control.cc
+++ b/libs/ardour/slavable_automation_control.cc
@@ -312,8 +312,16 @@ SlavableAutomationControl::update_boolean_masters_records (boost::shared_ptr<Aut
void
SlavableAutomationControl::master_changed (bool /*from_self*/, GroupControlDisposition gcd, boost::shared_ptr<AutomationControl> m)
{
+ Glib::Threads::RWLock::ReaderLock lm (master_lock, Glib::Threads::TRY_LOCK);
+ if (!lm.locked ()) {
+ /* boolean_automation_run_locked () special case */
+ return;
+ }
+ bool send_signal = handle_master_change (m);
update_boolean_masters_records (m);
- Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ if (send_signal) {
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
}
void
@@ -451,6 +459,66 @@ SlavableAutomationControl::find_next_event_locked (double now, double end, Evora
}
bool
+SlavableAutomationControl::handle_master_change (boost::shared_ptr<AutomationControl>)
+{
+ return true; // emit Changed
+}
+
+bool
+SlavableAutomationControl::boolean_automation_run_locked (framepos_t start, pframes_t len)
+{
+ bool rv = false;
+ if (!_desc.toggled) {
+ return false;
+ }
+ for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+ boost::shared_ptr<AutomationControl> ac (mr->second.master());
+ if (!ac->automation_playback ()) {
+ continue;
+ }
+ if (!ac->toggled ()) {
+ continue;
+ }
+ boost::shared_ptr<SlavableAutomationControl> sc = boost::dynamic_pointer_cast<MuteControl>(ac);
+ if (sc) {
+ rv |= sc->boolean_automation_run (start, len);
+ }
+ boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
+ bool valid = false;
+ const bool yn = alist->rt_safe_eval (start, valid) >= 0.5;
+ if (!valid) {
+ continue;
+ }
+ /* ideally we'd call just master_changed() which calls update_boolean_masters_records()
+ * but that takes the master_lock, which is already locked */
+ if (mr->second.yn() != yn) {
+ rv |= handle_master_change (ac);
+ mr->second.set_yn (yn);
+ /* notify the GUI, without recursion:
+ * master_changed() above will ignore the change if the lock is held.
+ */
+ ac->set_value_unchecked (yn ? 1. : 0.);
+ ac->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
+ }
+ return rv;
+}
+
+bool
+SlavableAutomationControl::boolean_automation_run (framepos_t start, pframes_t len)
+{
+ bool change = false;
+ {
+ Glib::Threads::RWLock::ReaderLock lm (master_lock);
+ change = boolean_automation_run_locked (start, len);
+ }
+ if (change) {
+ Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
+ }
+ return change;
+}
+
+bool
SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
{
Glib::Threads::RWLock::ReaderLock lm (master_lock);