summaryrefslogtreecommitdiff
path: root/libs/evoral
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2008-12-16 23:21:01 +0000
committerCarl Hetherington <carl@carlh.net>2008-12-16 23:21:01 +0000
commit2ebb1af2997b8e8f162635b11e8acc5c5d0fe563 (patch)
treea88ebc1e46dbe43cc760626eddd57d0feac81216 /libs/evoral
parent43b14aa6098e266f07e1d7dfe4a8a65edda36b0a (diff)
Implement #2425: option for automation to follow region moves.
git-svn-id: svn://localhost/ardour2/branches/3.0@4326 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/evoral')
-rw-r--r--libs/evoral/evoral/ControlList.hpp3
-rw-r--r--libs/evoral/evoral/types.hpp11
-rw-r--r--libs/evoral/src/ControlList.cpp96
3 files changed, 74 insertions, 36 deletions
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 36799300fe..48050f9e93 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -120,7 +120,7 @@ public:
void erase_range (double start, double end);
void erase (iterator);
void erase (iterator, iterator);
- void move_range (iterator start, iterator end, double, double);
+ void move_ranges (RangeMoveList const &);
void modify (iterator, double, double);
boost::shared_ptr<ControlList> cut (double, double);
@@ -241,6 +241,7 @@ protected:
bool rt_safe_earliest_event_linear_unlocked (double start, double end, double& x, double& y, bool inclusive) const;
boost::shared_ptr<ControlList> cut_copy_clear (double, double, int op);
+ bool erase_range_internal (double start, double end, EventList &);
virtual void maybe_signal_changed ();
diff --git a/libs/evoral/evoral/types.hpp b/libs/evoral/evoral/types.hpp
index fc1001c7d8..4bca6f1288 100644
--- a/libs/evoral/evoral/types.hpp
+++ b/libs/evoral/evoral/types.hpp
@@ -20,6 +20,7 @@
#define EVORAL_TYPES_HPP
#include <stdint.h>
+#include <list>
namespace Evoral {
@@ -41,6 +42,16 @@ typedef double EventLength;
/** Type of an event (opaque, mapped by application) */
typedef uint32_t EventType;
+/** Type to describe the movement of a time range */
+struct RangeMove {
+ RangeMove (EventTime f, FrameTime l, EventTime t) : from (f), length (l), to (t) {}
+ EventTime from; ///< start of the range
+ FrameTime length; ///< length of the range
+ EventTime to; ///< new start of the range
+};
+
+typedef std::list<RangeMove> RangeMoveList;
+
} // namespace Evoral
#endif // EVORAL_TYPES_HPP
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index e1cea8e191..033e375a8a 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -390,16 +390,10 @@ ControlList::erase_range (double start, double endt)
{
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 ();
}
@@ -410,36 +404,22 @@ ControlList::erase_range (double start, double endt)
}
}
-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
@@ -1315,5 +1295,51 @@ ControlList::paste (ControlList& alist, double pos, float times)
return true;
}
+/** Move automation around according to a list of region movements */
+void
+ControlList::move_ranges (RangeMoveList const & movements)
+{
+ {
+ 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 ();
+ EventTime const limit = i->from + i->length;
+ EventTime const 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