From 7b19392dea6c3f8626e25da9e3082aee53186a33 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 23 Apr 2010 02:13:40 +0000 Subject: more cleanups, redesigns and subtle bug fixes for automation editing git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@6972 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/generic_pluginui.cc | 2 +- libs/ardour/ardour/automation_event.h | 37 +++++--- libs/ardour/automation_event.cc | 156 +++++++++++++++++++--------------- libs/ardour/io.cc | 4 +- 4 files changed, 117 insertions(+), 82 deletions(-) diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc index 68762ae49f..52813aa231 100644 --- a/gtk2_ardour/generic_pluginui.cc +++ b/gtk2_ardour/generic_pluginui.cc @@ -589,7 +589,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontr void GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui) { - insert->automation_list (cui->port_index).start_touch (); + insert->automation_list (cui->port_index).start_touch (insert->session().transport_frame()); } void diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index fc998e5cb2..7918845efa 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -130,15 +130,15 @@ class AutomationList : public PBD::StatefulDestructible sigc::signal automation_state_changed; bool automation_playback() { - return (_state & Auto_Play) || ((_state & Auto_Touch) && !_touching); + return (_state & Auto_Play) || ((_state & Auto_Touch) && !touching()); } bool automation_write () { - return (_state & Auto_Write) || ((_state & Auto_Touch) && _touching); + return (_state & Auto_Write) || ((_state & Auto_Touch) && touching()); } - void start_touch (); + void start_touch (double when); void stop_touch (bool mark, double when); - bool touching() const { return _touching; } + bool touching() const { return g_atomic_int_get (&_touching); } void set_yrange (double min, double max) { min_yval = min; @@ -202,9 +202,22 @@ class AutomationList : public PBD::StatefulDestructible static sigc::signal AutomationListCreated; protected: + + struct NascentInfo { + AutomationEventList events; + bool is_touch; + double start_time; + double end_time; + + NascentInfo (bool touching, double start = -1.0) + : is_touch (touching) + , start_time (start) + , end_time (-1.0) + {} + }; AutomationEventList events; - std::list nascent; + std::list nascent; mutable Glib::Mutex lock; int8_t _frozen; bool changed_when_thawed; @@ -219,13 +232,13 @@ class AutomationList : public PBD::StatefulDestructible AutoState _state; AutoStyle _style; - bool _touching; - bool _new_touch; - double max_xval; - double min_yval; - double max_yval; - double default_value; - bool sort_pending; + gint _touching; + bool _new_touch; + double max_xval; + double min_yval; + double max_yval; + double default_value; + bool sort_pending; void maybe_signal_changed (); void mark_dirty (); diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index f28149e3e6..6d7476c08e 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -59,8 +60,7 @@ AutomationList::AutomationList (double defval) changed_when_thawed = false; _state = Auto_Off; _style = Auto_Absolute; - _touching = false; - _new_touch = false; + g_atomic_int_set (&_touching, 0); min_yval = FLT_MIN; max_yval = FLT_MAX; max_xval = 0; // means "no limit" @@ -83,8 +83,7 @@ AutomationList::AutomationList (const AutomationList& other) max_xval = other.max_xval; default_value = other.default_value; _state = other._state; - _touching = other._touching; - _new_touch = false; + g_atomic_int_set (&_touching, 0); _dirty = false; lookup_cache.left = -1; lookup_cache.range.first = events.end(); @@ -111,7 +110,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl max_xval = other.max_xval; default_value = other.default_value; _state = other._state; - _touching = other._touching; + g_atomic_int_set (&_touching, other.touching()); _dirty = false; lookup_cache.left = -1; lookup_cache.range.first = events.end(); @@ -138,7 +137,7 @@ AutomationList::AutomationList (const XMLNode& node) { _frozen = 0; changed_when_thawed = false; - _touching = false; + g_atomic_int_set (&_touching, 0); min_yval = FLT_MIN; max_yval = FLT_MAX; max_xval = 0; // means "no limit" @@ -162,8 +161,8 @@ AutomationList::~AutomationList() delete (*x); } - for (list::iterator n = nascent.begin(); n != nascent.end(); ++n) { - for (AutomationEventList::iterator x = (*n)->begin(); x != (*n)->end(); ++x) { + for (list::iterator n = nascent.begin(); n != nascent.end(); ++n) { + for (AutomationEventList::iterator x = (*n)->events.begin(); x != (*n)->events.end(); ++x) { delete *x; } delete (*n); @@ -209,7 +208,6 @@ AutomationList::maybe_signal_changed () if (_frozen) { changed_when_thawed = true; } else { - cerr << " SC, events holds " << events.size() << endl; StateChanged (); } } @@ -222,7 +220,7 @@ AutomationList::set_automation_state (AutoState s) if (_state == Auto_Write) { Glib::Mutex::Lock lm (lock); - nascent.push_back (new AutomationEventList); + nascent.push_back (new NascentInfo (false)); } automation_state_changed (); /* EMIT SIGNAL */ @@ -239,19 +237,37 @@ AutomationList::set_automation_style (AutoStyle s) } void -AutomationList::start_touch () +AutomationList::start_touch (double when) { - _touching = true; - _new_touch = true; + if (_state == Auto_Touch) { + Glib::Mutex::Lock lm (lock); + nascent.push_back (new NascentInfo (true, when)); + } - nascent.push_back (new AutomationEventList); + g_atomic_int_set (&_touching, 1); } void AutomationList::stop_touch (bool mark, double when) { - _touching = false; - _new_touch = false; + g_atomic_int_set (&_touching, 0); + + if (_state == Auto_Touch) { + Glib::Mutex::Lock lm (lock); + + if (mark) { + nascent.back()->end_time = when; + + } else { + + /* nascent info created in start touch but never used. just get rid of it. + */ + + NascentInfo* ninfo = nascent.back (); + nascent.erase (nascent.begin()); + delete ninfo; + } + } } void @@ -312,7 +328,7 @@ AutomationList::rt_add (double when, double value) { /* this is for automation recording */ - if ((_state & Auto_Touch) && !_touching) { + if ((_state & Auto_Touch) && !touching()) { return; } @@ -320,10 +336,10 @@ AutomationList::rt_add (double when, double value) if (lm.locked()) { assert (!nascent.empty()); - if (!nascent.front()->empty()) { - assert (when > nascent.front()->back()->when); + if (!nascent.back()->events.empty()) { + assert (when > nascent.back()->events.back()->when); } - nascent.front()->push_back (point_factory (when, value)); + nascent.back()->events.push_back (point_factory (when, value)); } } @@ -337,36 +353,41 @@ AutomationList::merge_nascent (double when) return; } - for (list::iterator n = nascent.begin(); n != nascent.end(); ++n) { - AutomationEventList* nascent_events = *n; + for (list::iterator n = nascent.begin(); n != nascent.end(); ++n) { + + NascentInfo* ninfo = *n; + AutomationEventList& nascent_events (ninfo->events); - if (nascent_events->empty()) { - delete nascent_events; + if (nascent_events.empty()) { + delete ninfo; continue; } - double lower = nascent_events->front()->when; + if (ninfo->start_time < 0.0) { + ninfo->start_time = nascent_events.front()->when; + } + + if (ninfo->end_time < 0.0) { + ninfo->end_time = when; + } + bool preexisting = !events.empty(); - double clamp_time = nascent_events->back()->when + 1; // XXX FIX ME - + if (!preexisting) { - events = *nascent_events; + events = nascent_events; - } else if (clamp_time < events.front()->when) { + } else if (ninfo->end_time < events.front()->when) { /* all points in nascent are before the first existing point */ - if (preexisting) { - events.insert (events.begin(), point_factory (clamp_time, unlocked_eval (clamp_time))); - } - events.insert (events.begin(), nascent_events->begin(), nascent_events->end()); + events.insert (events.begin(), nascent_events.begin(), nascent_events.end()); - } else if (lower > events.back()->when) { + } else if (ninfo->start_time > events.back()->when) { /* all points in nascent are after the last existing point */ - events.insert (events.end(), nascent_events->begin(), nascent_events->end()); + events.insert (events.end(), nascent_events.begin(), nascent_events.end()); } else { @@ -377,16 +398,16 @@ AutomationList::merge_nascent (double when) iterator i; iterator range_begin = events.end(); iterator range_end = events.end(); - + for (i = events.begin(); i != events.end(); ++i) { - if ((*i)->when >= lower) { + if ((*i)->when >= ninfo->start_time) { if (range_begin == events.end()) { range_begin = i; } - if ((*i)->when > clamp_time) { + if ((*i)->when > ninfo->end_time) { range_end = i; break; } @@ -394,39 +415,31 @@ AutomationList::merge_nascent (double when) } assert (range_begin != events.end()); + + double end_value = unlocked_eval (ninfo->end_time); - double clamp_value; - - if (preexisting) { - clamp_value = unlocked_eval (clamp_time); - - if (range_begin != events.begin()) { - /* clamp point before */ - double preclamp_time = nascent_events->front()->when - 1; - events.insert (range_begin, point_factory (preclamp_time, clamp_value)); - } + if (range_begin != events.begin()) { + /* clamp point before */ + events.insert (range_begin, point_factory (ninfo->start_time, unlocked_eval (ninfo->start_time))); } + + events.insert (range_begin, nascent_events.begin(), nascent_events.end()); - events.insert (range_begin, nascent_events->begin(), nascent_events->end()); - - if (preexisting) { - if (range_end != events.end()) { - /* clamp point after */ - events.insert (range_begin, point_factory (clamp_time, clamp_value)); - } + if (range_end != events.end()) { + /* clamp point after */ + events.insert (range_begin, point_factory (ninfo->end_time, end_value)); } - events.erase (range_begin, range_end); } - delete nascent_events; + delete ninfo; } nascent.clear (); if (_state == Auto_Write) { - nascent.push_back (new AutomationEventList); + nascent.push_back (new NascentInfo (false)); } } @@ -702,7 +715,6 @@ AutomationList::thaw () } if (changed_when_thawed) { - cerr << " thaw SC, events holds " << events.size() << endl; StateChanged(); /* EMIT SIGNAL */ } } @@ -1116,21 +1128,25 @@ AutomationList::cut_copy_clear (double start, double end, int op) because we want the copy ("nal") to have a zero time reference. */ + + /* before we begin any cut/clear operations, get the value of the curve + at "end". + */ + + double end_value = unlocked_eval (end); + if ((*s)->when != start) { double val = unlocked_eval (start); - events.insert (s, (point_factory (start, val))); + + if (start > events.front()->when) { + events.insert (s, (point_factory (start, val))); + } if (op != 2) { nal->events.push_back (point_factory (0, val)); } } - - /* before we begin any cut/clear operations, get the value of the curve - at "end". - */ - - double end_value = unlocked_eval (end); for (iterator x = s; x != e; ) { @@ -1150,7 +1166,13 @@ AutomationList::cut_copy_clear (double start, double end, int op) } if (e == events.end() || (*e)->when != end) { - events.insert (e, point_factory (end, end_value)); + + /* only add a boundary point if there is a point after "end" + */ + + if (e != events.end() || end < (*e)->when) { + events.insert (e, point_factory (end, end_value)); + } if (op != 2) { nal->events.push_back (point_factory (end - start, end_value)); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 430ae46abb..21f51e68fe 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -2669,7 +2669,7 @@ IO::set_gain (gain_t val, void *src) void IO::start_gain_touch () { - _gain_automation_curve.start_touch (); + _gain_automation_curve.start_touch (_session.transport_frame()); } void @@ -2690,7 +2690,7 @@ void IO::start_pan_touch (uint32_t which) { if (which < _panner->size()) { - (*_panner)[which]->automation().start_touch(); + (*_panner)[which]->automation().start_touch (_session.transport_frame()); } } -- cgit v1.2.3