#include <cassert>
#include <utility>
#include <iostream>
-#include <evoral/ControlList.hpp>
+#include "evoral/ControlList.hpp"
using namespace std;
{
Glib::Mutex::Lock lm (_lock);
- ControlEvent cp (start, 0.0f);
- iterator s;
- iterator e;
+ erased = erase_range_internal (start, endt, _events);
- if ((s = lower_bound (_events.begin(), _events.end(), &cp, time_comparator)) != _events.end()) {
- cp.when = endt;
- e = upper_bound (_events.begin(), _events.end(), &cp, time_comparator);
- _events.erase (s, e);
+ if (erased) {
reposition_for_rt_add (0);
- erased = true;
mark_dirty ();
}
}
}
-void
-ControlList::move_range (iterator start, iterator end, double xdelta, double ydelta)
+bool
+ControlList::erase_range_internal (double start, double endt, EventList & events)
{
- /* note: we assume higher level logic is in place to avoid this
- reordering the time-order of control events in the list. ie. all
- points after end are later than (end)->when.
- */
-
- {
- Glib::Mutex::Lock lm (_lock);
-
- while (start != end) {
- (*start)->when += xdelta;
- (*start)->value += ydelta;
- if (isnan ((*start)->value)) {
- abort ();
- }
- ++start;
- }
-
- if (!_frozen) {
- _events.sort (event_time_less_than);
- } else {
- _sort_pending = true;
- }
-
- mark_dirty ();
+ bool erased = false;
+ ControlEvent cp (start, 0.0f);
+ iterator s;
+ iterator e;
+
+ if ((s = lower_bound (events.begin(), events.end(), &cp, time_comparator)) != events.end()) {
+ cp.when = endt;
+ e = upper_bound (events.begin(), events.end(), &cp, time_comparator);
+ events.erase (s, e);
+ erased = true;
}
- maybe_signal_changed ();
+ return erased;
}
void
double fraction;
const_iterator length_check_iter = _events.begin();
- for (npoints = 0; npoints < 4; ++npoints, ++length_check_iter)
- if (length_check_iter == _events.end())
+ for (npoints = 0; npoints < 4; ++npoints, ++length_check_iter) {
+ if (length_check_iter == _events.end()) {
break;
+ }
+ }
switch (npoints) {
case 0:
return _default_value;
case 1:
- if (x >= _events.front()->when) {
- return _events.front()->value;
- } else {
- // return _default_value;
- return _events.front()->value;
- }
+ return _events.front()->value;
case 2:
if (x >= _events.back()->when) {
return _events.back()->value;
- } else if (x == _events.front()->when) {
- return _events.front()->value;
- } else if (x < _events.front()->when) {
- // return _default_value;
+ } else if (x <= _events.front()->when) {
return _events.front()->value;
}
upos = _events.back()->when;
uval = _events.back()->value;
- if (_interpolation == Discrete)
+ if (_interpolation == Discrete) {
return lval;
+ }
- /* linear interpolation betweeen the two points
- */
-
+ /* linear interpolation betweeen the two points */
fraction = (double) (x - lpos) / (double) (upos - lpos);
return lval + (fraction * (uval - lval));
default:
-
if (x >= _events.back()->when) {
return _events.back()->value;
- } else if (x == _events.front()->when) {
- return _events.front()->value;
- } else if (x < _events.front()->when) {
- // return _default_value;
+ } else if (x <= _events.front()->when) {
return _events.front()->value;
}
return multipoint_eval (x);
- break;
}
/*NOTREACHED*/ /* stupid gcc */
- return 0.0;
+ return _default_value;
}
double
const bool past_start = (inclusive ? first->when >= start : first->when > start);
/* Earliest points is in range, return it */
- if (past_start >= start && first->when < end) {
+ if (past_start && first->when < end) {
x = first->when;
y = first->value;
bool
ControlList::rt_safe_earliest_event_linear_unlocked (double start, double end, double& x, double& y, bool inclusive) const
{
- //cerr << "earliest_event(" << start << ", " << end << ", " << x << ", " << y << ", " << inclusive << endl;
+ cerr << "earliest_event(start: " << start << ", end: " << end << ", x: " << x << ", y: " << y << ", inclusive: " << inclusive << ")" << endl;
const_iterator length_check_iter = _events.begin();
if (_events.empty()) // 0 events
* (Optimize for immediate call this cycle within range) */
_search_cache.left = x;
//++_search_cache.range.first;
- assert(inclusive ? x >= start : x > start);
+ assert(x >= start);
return true;
}
if (fabs(first->value - next->value) <= 1) {
- if (next->when <= end && (!inclusive || next->when > start)) {
+ if (next->when <= end && (next->when > start)) {
x = next->when;
y = next->value;
/* Move left of cache to this point
x = first->when + (y - first->value) / (double)slope;
}
- /*cerr << first->value << " @ " << first->when << " ... "
+ cerr << first->value << " @ " << first->when << " ... "
<< next->value << " @ " << next->when
- << " = " << y << " @ " << x << endl;*/
+ << " = " << y << " @ " << x << endl;
assert( (y >= first->value && y <= next->value)
|| (y <= first->value && y >= next->value) );
return true;
}
+/** Move automation around according to a list of region movements */
+void
+ControlList::move_ranges (const list< RangeMove<double> >& movements)
+{
+ typedef list< RangeMove<double> > RangeMoveList;
+
+ {
+ Glib::Mutex::Lock lm (_lock);
+
+ /* a copy of the events list before we started moving stuff around */
+ EventList old_events = _events;
+
+ /* clear the source and destination ranges in the new list */
+ for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) {
+
+ erase_range_internal (i->from, i->from + i->length, _events);
+ erase_range_internal (i->to, i->to + i->length, _events);
+
+ }
+
+ /* copy the events into the new list */
+ for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) {
+ iterator j = old_events.begin ();
+ const double limit = i->from + i->length;
+ const double dx = i->to - i->from;
+ while (j != old_events.end () && (*j)->when <= limit) {
+ if ((*j)->when >= i->from) {
+ ControlEvent* ev = new ControlEvent (**j);
+ ev->when += dx;
+ _events.push_back (ev);
+ }
+ ++j;
+ }
+ }
+
+ if (!_frozen) {
+ _events.sort (event_time_less_than);
+ } else {
+ _sort_pending = true;
+ }
+
+ reposition_for_rt_add (0);
+ mark_dirty ();
+ }
+
+ maybe_signal_changed ();
+}
+
} // namespace Evoral