summaryrefslogtreecommitdiff
path: root/libs/evoral
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2018-12-22 02:04:17 +0100
committerRobin Gareus <robin@gareus.org>2018-12-22 02:04:17 +0100
commit6fa1c58ceca40fda0175d5ac3b3538fc8e7231d1 (patch)
tree777d13e1413754f104da4f0cfef8f398ca8bc2f6 /libs/evoral
parent616f7f40b6db150c18aa29f132bf13d1db8c5e49 (diff)
Add guard-points when shifting automation
Diffstat (limited to 'libs/evoral')
-rw-r--r--libs/evoral/src/ControlList.cpp33
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 ();
}