diff options
Diffstat (limited to 'libs/ardour/automation_event.cc')
-rw-r--r-- | libs/ardour/automation_event.cc | 93 |
1 files changed, 82 insertions, 11 deletions
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index 5cc2f50e38..af6fffdeb9 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -26,7 +26,7 @@ #include <algorithm> #include <sigc++/bind.h> #include <ardour/automation_event.h> -#include <pbd/convert.h> +#include <pbd/stacktrace.h> #include "i18n.h" @@ -37,6 +37,11 @@ using namespace PBD; sigc::signal<void,AutomationList *> AutomationList::AutomationListCreated; +static bool sort_events_by_time (ControlEvent* a, ControlEvent* b) +{ + return a->when < b->when; +} + #if 0 static void dumpit (const AutomationList& al, string prefix = "") { @@ -50,7 +55,7 @@ static void dumpit (const AutomationList& al, string prefix = "") AutomationList::AutomationList (double defval) { - _frozen = false; + _frozen = 0; changed_when_thawed = false; _state = Off; _style = Absolute; @@ -63,13 +68,14 @@ AutomationList::AutomationList (double defval) rt_insertion_point = events.end(); lookup_cache.left = -1; lookup_cache.range.first = events.end(); + sort_pending = false; AutomationListCreated(this); } AutomationList::AutomationList (const AutomationList& other) { - _frozen = false; + _frozen = 0; changed_when_thawed = false; _style = other._style; min_yval = other.min_yval; @@ -82,6 +88,7 @@ AutomationList::AutomationList (const AutomationList& other) rt_insertion_point = events.end(); lookup_cache.left = -1; lookup_cache.range.first = events.end(); + sort_pending = false; for (const_iterator i = other.events.begin(); i != other.events.end(); ++i) { /* we have to use other point_factory() because @@ -96,7 +103,7 @@ AutomationList::AutomationList (const AutomationList& other) AutomationList::AutomationList (const AutomationList& other, double start, double end) { - _frozen = false; + _frozen = 0; changed_when_thawed = false; _style = other._style; min_yval = other.min_yval; @@ -109,6 +116,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl rt_insertion_point = events.end(); lookup_cache.left = -1; lookup_cache.range.first = events.end(); + sort_pending = false; /* now grab the relevant points, and shift them back if necessary */ @@ -129,7 +137,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl AutomationList::AutomationList (const XMLNode& node) { - _frozen = false; + _frozen = 0; changed_when_thawed = false; _touching = false; min_yval = FLT_MIN; @@ -141,6 +149,7 @@ AutomationList::AutomationList (const XMLNode& node) rt_insertion_point = events.end(); lookup_cache.left = -1; lookup_cache.range.first = events.end(); + sort_pending = false; set_state (node); @@ -402,7 +411,7 @@ AutomationList::add (double when, double value) } if (insert) { - + events.insert (insertion_point, point_factory (when, value)); reposition_for_rt_add (0); @@ -512,9 +521,18 @@ AutomationList::move_range (iterator start, iterator end, double xdelta, double while (start != end) { (*start)->when += xdelta; (*start)->value += ydelta; + if (isnan ((*start)->value)) { + abort (); + } ++start; } + if (!_frozen) { + events.sort (sort_events_by_time); + } else { + sort_pending = true; + } + mark_dirty (); } @@ -522,6 +540,25 @@ AutomationList::move_range (iterator start, iterator end, double xdelta, double } void +AutomationList::slide (iterator before, double distance) +{ + { + Glib::Mutex::Lock lm (lock); + + if (before == events.end()) { + return; + } + + while (before != events.end()) { + (*before)->when += distance; + ++before; + } + } + + maybe_signal_changed (); +} + +void AutomationList::modify (iterator iter, double when, double val) { /* note: we assume higher level logic is in place to avoid this @@ -531,11 +568,23 @@ AutomationList::modify (iterator iter, double when, double val) { Glib::Mutex::Lock lm (lock); + (*iter)->when = when; (*iter)->value = val; + + if (isnan (val)) { + abort (); + } + + if (!_frozen) { + events.sort (sort_events_by_time); + } else { + sort_pending = true; + } + mark_dirty (); } - + maybe_signal_changed (); } @@ -576,13 +625,31 @@ AutomationList::control_points_adjacent (double xval) void AutomationList::freeze () { - _frozen = true; + _frozen++; } void AutomationList::thaw () { - _frozen = false; + if (_frozen == 0) { + PBD::stacktrace (cerr); + fatal << string_compose (_("programming error: %1"), X_("AutomationList::thaw() called while not frozen")) << endmsg; + /*NOTREACHED*/ + } + + if (--_frozen > 0) { + return; + } + + { + Glib::Mutex::Lock lm (lock); + + if (sort_pending) { + events.sort (sort_events_by_time); + sort_pending = false; + } + } + if (changed_when_thawed) { StateChanged(); /* EMIT SIGNAL */ } @@ -1240,6 +1307,7 @@ AutomationList::deserialize_events (const XMLNode& node) } thaw (); + return 0; } @@ -1271,6 +1339,7 @@ AutomationList::set_state (const XMLNode& node) jack_nframes_t x; double y; + freeze (); clear (); for (i = elist.begin(); i != elist.end(); ++i) { @@ -1287,9 +1356,11 @@ AutomationList::set_state (const XMLNode& node) } y = atof (prop->value().c_str()); - add (x, y); + fast_simple_add (x, y); } + thaw (); + return 0; } @@ -1345,7 +1416,7 @@ AutomationList::set_state (const XMLNode& node) deserialize_events (*(*niter)); } } - + return 0; } |