From a41198305ebb727e02a2b9e0d973b963f51b93fe Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 24 Jul 2017 20:54:32 +0200 Subject: Update WritePass logic + AutomationList Undo Fixes various issues when changing AutomationState while rolling. --- libs/ardour/ardour/automation_list.h | 8 ++++-- libs/ardour/automation_list.cc | 52 +++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 23 deletions(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h index 65268d503a..46643dc6fa 100644 --- a/libs/ardour/ardour/automation_list.h +++ b/libs/ardour/ardour/automation_list.h @@ -110,8 +110,6 @@ public: XMLNode& get_state (); int set_state (const XMLNode &, int version); - XMLNode& state (bool full); - XMLNode& serialize_events (); Command* memento_command (XMLNode* before, XMLNode* after); @@ -119,6 +117,7 @@ public: XMLNode* before () { XMLNode* rv = _before; _before = 0; return rv; } void clear_history (); + void snapshot_history (bool need_lock); ControlList::InterpolationStyle default_interpolation () const; @@ -126,11 +125,16 @@ private: void create_curve_if_necessary (); int deserialize_events (const XMLNode&); + XMLNode& state (bool full, bool need_lock); + XMLNode& serialize_events (bool need_lock); + void maybe_signal_changed (); AutoState _state; gint _touching; + PBD::ScopedConnection _writepass_connection; + bool operator== (const AutomationList&) const { /* not called */ abort(); return false; } XMLNode* _before; //used for undo of touch start/stop pairs. diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index 74181d5514..d92e65288f 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -161,6 +161,8 @@ AutomationList::create_curve_if_necessary() default: break; } + + WritePassStarted.connect_same_thread (_writepass_connection, boost::bind (&AutomationList::snapshot_history, this, false)); } AutomationList& @@ -193,16 +195,14 @@ AutomationList::maybe_signal_changed () void AutomationList::set_automation_state (AutoState s) { - if (s != _state) { - _state = s; - delete _before; - if (s == Write && _desc.toggled) { - _before = &get_state (); - } else { - _before = 0; - } - automation_state_changed (s); /* EMIT SIGNAL */ + if (s == _state) { + return; + } + _state = s; + if (s == Write && _desc.toggled) { + snapshot_history (true); } + automation_state_changed (s); /* EMIT SIGNAL */ } Evoral::ControlList::InterpolationStyle @@ -231,12 +231,7 @@ AutomationList::default_interpolation () const void AutomationList::start_write_pass (double when) { - delete _before; - if (in_new_write_pass ()) { - _before = &get_state (); - } else { - _before = 0; - } + snapshot_history (true); ControlList::start_write_pass (when); } @@ -249,9 +244,9 @@ AutomationList::write_pass_finished (double when, double thinning_factor) void AutomationList::start_touch (double when) { - if (_state == Touch) { + if (_state == Touch) { start_write_pass (when); - } + } g_atomic_int_set (&_touching, 1); } @@ -281,6 +276,17 @@ AutomationList::clear_history () _before = 0; } +void +AutomationList::snapshot_history (bool need_lock) +{ + if (!in_new_write_pass ()) { + return; + } + delete _before; + _before = &state (true, need_lock); +} + + void AutomationList::thaw () { @@ -326,11 +332,11 @@ AutomationList::memento_command (XMLNode* before, XMLNode* after) XMLNode& AutomationList::get_state () { - return state (true); + return state (true, true); } XMLNode& -AutomationList::state (bool full) +AutomationList::state (bool full, bool need_lock) { XMLNode* root = new XMLNode (X_("AutomationList")); @@ -372,18 +378,22 @@ AutomationList::state (bool full) } if (!_events.empty()) { - root->add_child_nocopy (serialize_events()); + root->add_child_nocopy (serialize_events (need_lock)); } return *root; } XMLNode& -AutomationList::serialize_events () +AutomationList::serialize_events (bool need_lock) { XMLNode* node = new XMLNode (X_("events")); stringstream str; + Glib::Threads::RWLock::ReaderLock lm (Evoral::ControlList::_lock, Glib::Threads::NOT_LOCK); + if (need_lock) { + lm.acquire (); + } for (iterator xx = _events.begin(); xx != _events.end(); ++xx) { str << PBD::to_string ((*xx)->when); str << ' '; -- cgit v1.2.3