From 1d587592ca1472e38b2f8127b87b6202874f0d4e Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 25 Jul 2017 16:09:47 +0200 Subject: [PATCH] Add support for Latch Automation --- libs/ardour/ardour/automation_list.h | 6 +++--- libs/ardour/ardour/pannable.h | 8 ++++---- libs/ardour/ardour/types.h | 9 +++++---- libs/ardour/automatable.cc | 3 +++ libs/ardour/automation_control.cc | 10 +++++++--- libs/ardour/enums.cc | 1 + libs/ardour/luabindings.cc | 1 + libs/ardour/panner_shell.cc | 2 +- libs/ardour/utils.cc | 6 ++++++ 9 files changed, 31 insertions(+), 15 deletions(-) diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h index 359d98856c..4601740af1 100644 --- a/libs/ardour/ardour/automation_list.h +++ b/libs/ardour/ardour/automation_list.h @@ -89,10 +89,10 @@ public: PBD::Signal1 automation_state_changed; bool automation_playback() const { - return (_state & Play) || ((_state & Touch) && !touching()); + return (_state & Play) || ((_state & (Touch | Latch)) && !touching()); } bool automation_write () const { - return ((_state & Write) || ((_state & Touch) && touching())); + return ((_state & Write) || ((_state & (Touch | Latch)) && touching())); } PBD::Signal0 StateChanged; @@ -106,7 +106,7 @@ public: void stop_touch (double when); bool touching() const { return g_atomic_int_get (const_cast(&_touching)); } bool writing() const { return _state == Write; } - bool touch_enabled() const { return _state == Touch; } + bool touch_enabled() const { return _state & (Touch | Latch); } XMLNode& get_state (); int set_state (const XMLNode &, int version); diff --git a/libs/ardour/ardour/pannable.h b/libs/ardour/ardour/pannable.h index cd88a250cf..f96670afec 100644 --- a/libs/ardour/ardour/pannable.h +++ b/libs/ardour/ardour/pannable.h @@ -58,19 +58,19 @@ class LIBARDOUR_API Pannable : public PBD::Stateful, public Automatable, public PBD::Signal1 automation_state_changed; bool automation_playback() const { - return (_auto_state & Play) || ((_auto_state & Touch) && !touching()); + return (_auto_state & Play) || ((_auto_state & (Touch | Latch)) && !touching()); } bool automation_write () const { - return ((_auto_state & Write) || ((_auto_state & Touch) && touching())); + return ((_auto_state & Write) || ((_auto_state & (Touch | Latch)) && touching())); } std::string value_as_string (boost::shared_ptr) const; void start_touch (double when); void stop_touch (double when); - bool touching() const { return g_atomic_int_get (const_cast(&_touching)); } + bool touching() const { return g_atomic_int_get (const_cast(&_touching)); } bool writing() const { return _auto_state == Write; } - bool touch_enabled() const { return _auto_state == Touch; } + bool touch_enabled() const { return _auto_state & (Touch | Latch); } XMLNode& get_state (); XMLNode& state (bool full_state); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 854fb04066..8358d78e9a 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -163,10 +163,11 @@ namespace ARDOUR { }; enum AutoState { - Off = 0x0, - Write = 0x1, - Touch = 0x2, - Play = 0x4 + Off = 0x00, + Write = 0x01, + Touch = 0x02, + Play = 0x04, + Latch = 0x08 }; std::string auto_state_to_string (AutoState); diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 57c8205717..8025386d1f 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -329,6 +329,8 @@ Automatable::protect_automation () case Write: l->set_automation_state (Off); break; + case Latch: + // no break case Touch: l->set_automation_state (Play); break; @@ -408,6 +410,7 @@ Automatable::non_realtime_transport_stop (framepos_t now, bool /*flush_processor */ const bool list_did_write = !l->in_new_write_pass (); + c->stop_touch (now); l->stop_touch (now); c->commit_transaction (list_did_write); diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index 7deeac4221..02bcbf4f65 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -253,7 +253,7 @@ AutomationControl::set_automation_state (AutoState as) if (as == Write) { AutomationWatch::instance().add_automation_watch (shared_from_this()); - } else if (as == Touch) { + } 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); @@ -283,7 +283,7 @@ AutomationControl::start_touch (double when) return; } - if (alist()->automation_state() == Touch) { + if (alist()->automation_state() & (Touch | Latch)) { /* subtle. aligns the user value with the playback and * use take actual value (incl masters). * @@ -306,9 +306,13 @@ AutomationControl::stop_touch (double when) return; } + if (alist()->automation_state() == Latch && _session.transport_rolling ()) { + return; + } + set_touching (false); - if (alist()->automation_state() == Touch) { + if (alist()->automation_state() & (Touch | Latch)) { alist()->stop_touch (when); if (!_desc.toggled) { AutomationWatch::instance().remove_automation_watch (shared_from_this()); diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index bd7c2dd39b..eee20f811d 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -177,6 +177,7 @@ setup_enum_writer () REGISTER_ENUM (Write); REGISTER_ENUM (Touch); REGISTER_ENUM (Play); + REGISTER_ENUM (Latch); REGISTER_BITS (_AutoState); REGISTER_ENUM (CaptureTime); diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 4575e9fbec..8b5c6a2a34 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -1704,6 +1704,7 @@ LuaBindings::common (lua_State* L) .addConst ("Write", ARDOUR::AutoState(Write)) .addConst ("Touch", ARDOUR::AutoState(Touch)) .addConst ("Play", ARDOUR::AutoState(Play)) + .addConst ("Latch", ARDOUR::AutoState(Latch)) .endNamespace () .beginNamespace ("AutomationType") diff --git a/libs/ardour/panner_shell.cc b/libs/ardour/panner_shell.cc index a3b7de287a..e53c1d346c 100644 --- a/libs/ardour/panner_shell.cc +++ b/libs/ardour/panner_shell.cc @@ -382,7 +382,7 @@ PannerShell::run (BufferSet& inbufs, BufferSet& outbufs, framepos_t start_frame, // If we shouldn't play automation defer to distribute_no_automation - if (!(as & Play || ((as & Touch) && !_panner->touching()))) { + if (!((as & Play) || ((as & (Touch | Latch)) && !_panner->touching()))) { distribute_no_automation (inbufs, outbufs, nframes, 1.0); diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 31a94702e1..17c1da0850 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -561,6 +561,8 @@ ARDOUR::string_to_auto_state (std::string str) return Write; } else if (str == X_("Touch")) { return Touch; + } else if (str == X_("Latch")) { + return Latch; } fatal << string_compose (_("programming error: %1 %2"), "illegal AutoState string: ", str) << endmsg; @@ -585,6 +587,10 @@ ARDOUR::auto_state_to_string (AutoState as) break; case Touch: return X_("Touch"); + break; + case Latch: + return X_("Latch"); + break; } fatal << string_compose (_("programming error: %1 %2"), "illegal AutoState type: ", as) << endmsg; -- 2.30.2