X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fautomation_control.cc;h=a194e2858af4caf94f5161ae9427f1e8a26b1442;hb=84272b4e27e537bf2c38c9cd25675c61addea40a;hp=e9bc1aebe052ba34b0920959e27dba4ad9a11dd3;hpb=b29b46d371b0721c49071481796ab2c7bcfc915f;p=ardour.git diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index e9bc1aebe0..a194e2858a 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -56,8 +56,9 @@ AutomationControl::AutomationControl(ARDOUR::Session& s : Controllable (name.empty() ? EventTypeMap::instance().to_symbol(parameter) : name, flags) , Evoral::Control(parameter, desc, list) - , _session(session) + , SessionHandleRef (session) , _desc(desc) + , _no_session(false) { if (_desc.toggled) { set_flags (Controllable::Toggle); @@ -70,8 +71,18 @@ AutomationControl::AutomationControl(ARDOUR::Session& s AutomationControl::~AutomationControl () { - _session.selection().remove_control_by_id (id()); + if (!_no_session && !_session.deletion_in_progress ()) { + _session.selection().remove_control_by_id (id()); + DropReferences (); /* EMIT SIGNAL */ + } +} + +void +AutomationControl::session_going_away () +{ + SessionHandleRef::session_going_away (); DropReferences (); /* EMIT SIGNAL */ + _no_session = true; } bool @@ -88,8 +99,8 @@ AutomationControl::writable() const double AutomationControl::get_value() const { - bool from_list = _list && boost::dynamic_pointer_cast(_list)->automation_playback(); - return Control::get_double (from_list, _session.transport_frame()); + bool from_list = alist() && alist()->automation_playback(); + return Control::get_double (from_list, _session.transport_sample()); } double @@ -130,7 +141,7 @@ AutomationControl::set_value (double val, PBD::Controllable::GroupControlDisposi } if (_group && _group->use_me (gcd)) { - _group->set_group_value (shared_from_this(), val); + _group->set_group_value (boost::dynamic_pointer_cast(shared_from_this()), val); } else { actually_set_value (val, gcd); } @@ -147,7 +158,7 @@ AutomationControl::grouped_controls () const } void -AutomationControl::automation_run (framepos_t start, pframes_t nframes) +AutomationControl::automation_run (samplepos_t start, pframes_t nframes) { if (!automation_playback ()) { return; @@ -174,8 +185,8 @@ AutomationControl::automation_run (framepos_t start, pframes_t nframes) void AutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd) { - boost::shared_ptr al = boost::dynamic_pointer_cast (_list); - const framepos_t pos = _session.transport_frame(); + boost::shared_ptr al = alist (); + const samplepos_t pos = _session.transport_sample(); bool to_list; /* We cannot use ::get_value() here since that is virtual, and intended @@ -230,7 +241,7 @@ AutomationControl::set_automation_state (AutoState as) if (flags() & NotAutomatable) { return; } - if (_list && as != alist()->automation_state()) { + if (alist() && as != alist()->automation_state()) { const double val = get_value (); @@ -241,67 +252,70 @@ AutomationControl::set_automation_state (AutoState as) } if (as == Write) { - AutomationWatch::instance().add_automation_watch (shared_from_this()); - } else if (as == Touch) { + AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); + } else if (as & (Touch | Latch)) { if (alist()->empty()) { - Control::set_double (val, _session.current_start_frame (), true); - Control::set_double (val, _session.current_end_frame (), true); + Control::set_double (val, _session.current_start_sample (), true); + Control::set_double (val, _session.current_end_sample (), true); Changed (true, Controllable::NoGroup); } if (!touching()) { - AutomationWatch::instance().remove_automation_watch (shared_from_this()); + AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); } else { /* this seems unlikely, but the combination of * a control surface and the mouse could make * it possible to put the control into Touch * mode *while* touching it. */ - AutomationWatch::instance().add_automation_watch (shared_from_this()); + AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); } } else { - AutomationWatch::instance().remove_automation_watch (shared_from_this()); + AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); Changed (false, Controllable::NoGroup); } } } void -AutomationControl::start_touch(double when) +AutomationControl::start_touch (double when) { - if (!_list) { + if (!_list || touching ()) { return; } - if (!touching()) { - if (alist()->automation_state() == Touch) { - /* subtle. aligns the user value with the playback and - * use take actual value (incl masters). - * - * Touch + hold writes inverse curve of master-automation - * using AutomationWatch::timer () - */ - AutomationControl::actually_set_value (get_value (), Controllable::NoGroup); - alist()->start_touch (when); - if (!_desc.toggled) { - AutomationWatch::instance().add_automation_watch (shared_from_this()); - } + if (alist()->automation_state() & (Touch | Latch)) { + /* subtle. aligns the user value with the playback and + * use take actual value (incl masters). + * + * Touch + hold writes inverse curve of master-automation + * using AutomationWatch::timer () + */ + AutomationControl::actually_set_value (get_value (), Controllable::NoGroup); + alist()->start_touch (when); + if (!_desc.toggled) { + AutomationWatch::instance().add_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); } set_touching (true); } } void -AutomationControl::stop_touch(double when) +AutomationControl::stop_touch (double when) { - if (!_list) return; - if (touching()) { - set_touching (false); - - if (alist()->automation_state() == Touch) { - alist()->stop_touch (when); - if (!_desc.toggled) { - AutomationWatch::instance().remove_automation_watch (shared_from_this()); - } + if (!_list || !touching ()) { + return; + } + + if (alist()->automation_state() == Latch && _session.transport_rolling ()) { + return; + } + + set_touching (false); + + if (alist()->automation_state() & (Touch | Latch)) { + alist()->stop_touch (when); + if (!_desc.toggled) { + AutomationWatch::instance().remove_automation_watch (boost::dynamic_pointer_cast(shared_from_this())); } } } @@ -364,7 +378,7 @@ AutomationControl::check_rt (double val, Controllable::GroupControlDisposition g { if (!_session.loading() && (flags() & Controllable::RealTime) && !AudioEngine::instance()->in_process_thread()) { /* queue change in RT context */ - _session.set_control (shared_from_this(), val, gcd); + _session.set_control (boost::dynamic_pointer_cast(shared_from_this()), val, gcd); return true; }