diff options
author | Robin Gareus <robin@gareus.org> | 2018-12-22 02:04:17 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2018-12-22 02:04:17 +0100 |
commit | 6fa1c58ceca40fda0175d5ac3b3538fc8e7231d1 (patch) | |
tree | 777d13e1413754f104da4f0cfef8f398ca8bc2f6 /libs/evoral | |
parent | 616f7f40b6db150c18aa29f132bf13d1db8c5e49 (diff) |
Add guard-points when shifting automation
Diffstat (limited to 'libs/evoral')
-rw-r--r-- | libs/evoral/src/ControlList.cpp | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index e1729483cc..da6d9b7c25 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -990,21 +990,52 @@ ControlList::shift (double pos, double frames) { { Glib::Threads::RWLock::WriterLock lm (_lock); + double v0, v1; if (frames < 0) { /* Route::shift () with negative shift is used * for "remove time". The time [pos.. pos-frames] is removed. * and everyhing after, moved backwards. - * TODO: consider adding guard-points (need special-casing) */ + v0 = unlocked_eval (pos); + v1 = unlocked_eval (pos - frames); erase_range_internal (pos, pos - frames, _events); + } else { + v0 = v1 = unlocked_eval (pos); } + bool dst_guard_exists = false; + for (iterator i = _events.begin(); i != _events.end(); ++i) { + if ((*i)->when == pos) { + dst_guard_exists = true; + } if ((*i)->when >= pos) { (*i)->when += frames; } } + /* add guard-points to retain shape, if needed */ + if (frames > 0) { + ControlEvent cp (pos, 0.0); + iterator s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); + if (s != _events.end ()) { + _events.insert (s, new ControlEvent (pos, v0)); + } + pos += frames; + } else if (frames < 0 && pos > 0) { + ControlEvent cp (pos - 1, 0.0); + iterator s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); + if (s != _events.end ()) { + _events.insert (s, new ControlEvent (pos - 1, v0)); + } + } + if (!dst_guard_exists) { + ControlEvent cp (pos, 0.0); + iterator s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); + _events.insert (s, new ControlEvent (pos, s == _events.end () ? v0 : v1)); + } + + mark_dirty (); } |