summaryrefslogtreecommitdiff
path: root/libs/ardour/automation_event.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/automation_event.cc')
-rw-r--r--libs/ardour/automation_event.cc93
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;
}