summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-07-24 20:54:32 +0200
committerRobin Gareus <robin@gareus.org>2017-07-24 21:00:12 +0200
commita41198305ebb727e02a2b9e0d973b963f51b93fe (patch)
tree6c136c1dc8882747f8446c8189bea52c991306b2 /libs/ardour
parent8c260a647a72e63bb16b1f7d2e732ae286edb38d (diff)
Update WritePass logic + AutomationList Undo
Fixes various issues when changing AutomationState while rolling.
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/automation_list.h8
-rw-r--r--libs/ardour/automation_list.cc52
2 files changed, 37 insertions, 23 deletions
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);
}
@@ -282,6 +277,17 @@ AutomationList::clear_history ()
}
void
+AutomationList::snapshot_history (bool need_lock)
+{
+ if (!in_new_write_pass ()) {
+ return;
+ }
+ delete _before;
+ _before = &state (true, need_lock);
+}
+
+
+void
AutomationList::thaw ()
{
ControlList::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 << ' ';