X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fautomation_event.cc;h=d5a7d50bb11942629d53b31e84962e2098f8f265;hb=5a3a2fad4fd1c217a5771caa64efe92a0b305275;hp=a2eeebed5603e4b75f86a59796b390836aec321a;hpb=e4e165d5ae804c11c11a37f2f4f164daa8272505;p=ardour.git diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index a2eeebed56..d5a7d50bb1 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -14,8 +14,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ + */ #include @@ -26,6 +25,7 @@ #include #include #include +#include #include "i18n.h" @@ -36,6 +36,11 @@ using namespace PBD; sigc::signal 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 = "") { @@ -49,7 +54,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; @@ -62,13 +67,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; @@ -81,6 +87,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 @@ -95,7 +102,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; @@ -108,6 +115,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 */ @@ -128,7 +136,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; @@ -140,6 +148,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); @@ -176,7 +185,10 @@ AutomationList::operator= (const AutomationList& other) max_yval = other.max_yval; max_xval = other.max_xval; default_value = other.default_value; - + + rt_insertion_point = events.end(); + lookup_cache.range.first = events.end(); + mark_dirty (); maybe_signal_changed (); } @@ -192,7 +204,7 @@ AutomationList::maybe_signal_changed () if (_frozen) { changed_when_thawed = true; } else { - StateChanged (Change (0)); + StateChanged (); } } @@ -355,6 +367,7 @@ AutomationList::rt_add (double when, double value) if (!done) { last_rt_insertion_point = events.insert (where, point_factory (when, value)); + // cerr << "\tINSERTED\n"; } _new_touch = false; @@ -401,7 +414,7 @@ AutomationList::add (double when, double value) } if (insert) { - + events.insert (insertion_point, point_factory (when, value)); reposition_for_rt_add (0); @@ -511,15 +524,43 @@ 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 (); } maybe_signal_changed (); } +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) { @@ -530,11 +571,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 (); } @@ -575,15 +628,33 @@ 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(Change(0)); /* EMIT SIGNAL */ + StateChanged(); /* EMIT SIGNAL */ } } @@ -606,7 +677,7 @@ AutomationList::truncate_end (double last_coordinate) { Glib::Mutex::Lock lm (lock); ControlEvent cp (last_coordinate, 0); - list::reverse_iterator i; + AutomationList::reverse_iterator i; double last_val; if (events.empty()) { @@ -675,7 +746,7 @@ AutomationList::truncate_end (double last_coordinate) uint32_t sz = events.size(); while (i != events.rend() && sz > 2) { - list::reverse_iterator tmp; + AutomationList::reverse_iterator tmp; tmp = i; ++tmp; @@ -772,7 +843,7 @@ AutomationList::truncate_start (double overall_length) i = events.begin(); while (i != events.end() && !events.empty()) { - list::iterator tmp; + AutomationList::iterator tmp; tmp = i; ++tmp; @@ -872,6 +943,9 @@ AutomationList::shared_eval (double x) return multipoint_eval (x); break; } + + /*NOTREACHED*/ /* stupid gcc */ + return 0.0; } double @@ -1176,6 +1250,8 @@ AutomationList::serialize_events () { XMLNode* node = new XMLNode (X_("events")); stringstream str; + + str.precision(15); //10 digits is enough digits for 24 hours at 96kHz for (iterator xx = events.begin(); xx != events.end(); ++xx) { str << (double) (*xx)->when; @@ -1239,6 +1315,7 @@ AutomationList::deserialize_events (const XMLNode& node) } thaw (); + return 0; } @@ -1246,6 +1323,7 @@ int AutomationList::set_state (const XMLNode& node) { XMLNodeList nlist = node.children(); + XMLNode* nsos; XMLNodeIterator niter; const XMLProperty* prop; @@ -1256,6 +1334,11 @@ AutomationList::set_state (const XMLNode& node) if (node.name() == X_("Envelope") || node.name() == X_("FadeOut") || node.name() == X_("FadeIn")) { + if ((nsos = node.child (X_("AutomationList")))) { + /* new school in old school clothing */ + return set_state (*nsos); + } + /* old school */ const XMLNodeList& elist = node.children(); @@ -1264,6 +1347,7 @@ AutomationList::set_state (const XMLNode& node) jack_nframes_t x; double y; + freeze (); clear (); for (i = elist.begin(); i != elist.end(); ++i) { @@ -1280,9 +1364,11 @@ AutomationList::set_state (const XMLNode& node) } y = atof (prop->value().c_str()); - add (x, y); + fast_simple_add (x, y); } + thaw (); + return 0; } @@ -1338,7 +1424,24 @@ AutomationList::set_state (const XMLNode& node) deserialize_events (*(*niter)); } } - + return 0; } +void +AutomationList::shift (nframes64_t pos, nframes64_t frames) +{ + { + Glib::Mutex::Lock lm (lock); + + for (iterator i = begin (); i != end (); ++i) { + if ((*i)->when >= pos) { + (*i)->when += frames; + } + } + + mark_dirty (); + } + + maybe_signal_changed (); +}