X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fautomation_list.cc;h=bc8ca8e6425863beb45d6cf6289a7d6047e1f736;hb=a2108090cf9d8a98d4f681a1f0178c2a59deaf76;hp=b76fa0bb4bc6e2108b98f931de8aafa39493c4ed;hpb=d22cd939a371b24e5e452963c98682a62ed8b6cf;p=ardour.git diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index b76fa0bb4b..bc8ca8e642 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -25,6 +25,7 @@ #include #include "ardour/automation_list.h" #include "ardour/event_type_map.h" +#include "ardour/parameter_descriptor.h" #include "evoral/Curve.hpp" #include "pbd/stacktrace.h" #include "pbd/enumwriter.h" @@ -47,8 +48,23 @@ static void dumpit (const AutomationList& al, string prefix = "") cerr << "\n"; } #endif -AutomationList::AutomationList (Evoral::Parameter id) - : ControlList(id) +AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc) + : ControlList(id, desc) + , _before (0) +{ + _state = Off; + _style = Absolute; + g_atomic_int_set (&_touching, 0); + + create_curve_if_necessary(); + + assert(_parameter.type() != NullAutomation); + AutomationListCreated(this); +} + +AutomationList::AutomationList (const Evoral::Parameter& id) + : ControlList(id, ARDOUR::ParameterDescriptor(id)) + , _before (0) { _state = Off; _style = Absolute; @@ -63,6 +79,7 @@ AutomationList::AutomationList (Evoral::Parameter id) AutomationList::AutomationList (const AutomationList& other) : StatefulDestructible() , ControlList(other) + , _before (0) { _style = other._style; _state = other._state; @@ -76,6 +93,7 @@ AutomationList::AutomationList (const AutomationList& other) AutomationList::AutomationList (const AutomationList& other, double start, double end) : ControlList(other, start, end) + , _before (0) { _style = other._style; _state = other._state; @@ -91,7 +109,8 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl * in or below the AutomationList node. It is used if @param id is non-null. */ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) - : ControlList(id) + : ControlList(id, ARDOUR::ParameterDescriptor(id)) + , _before (0) { g_atomic_int_set (&_touching, 0); _state = Off; @@ -114,9 +133,10 @@ AutomationList::~AutomationList() } boost::shared_ptr -AutomationList::create(Evoral::Parameter id) +AutomationList::create(const Evoral::Parameter& id, + const Evoral::ParameterDescriptor& desc) { - return boost::shared_ptr(new AutomationList(id)); + return boost::shared_ptr(new AutomationList(id, desc)); } void @@ -124,6 +144,7 @@ AutomationList::create_curve_if_necessary() { switch (_parameter.type()) { case GainAutomation: + case TrimAutomation: case PanAzimuthAutomation: case PanElevationAutomation: case PanWidthAutomation: @@ -137,27 +158,16 @@ AutomationList::create_curve_if_necessary() } } -bool -AutomationList::operator== (const AutomationList& other) -{ - return _events == other._events; -} - AutomationList& AutomationList::operator= (const AutomationList& other) { if (this != &other) { - _events.clear (); - - for (const_iterator i = other._events.begin(); i != other._events.end(); ++i) { - _events.push_back (new Evoral::ControlEvent (**i)); - } - _min_yval = other._min_yval; - _max_yval = other._max_yval; - _max_xval = other._max_xval; - _default_value = other._default_value; + ControlList::operator= (other); + _state = other._state; + _style = other._style; + _touching = other._touching; mark_dirty (); maybe_signal_changed (); @@ -181,11 +191,9 @@ AutomationList::set_automation_state (AutoState s) { if (s != _state) { _state = s; - - if (_state == Write) { - Glib::Mutex::Lock lm (ControlList::_lock); - nascent.push_back (new NascentInfo ()); - } + if (s == Write && _desc.toggled) { + _before = &get_state (); + } automation_state_changed (s); /* EMIT SIGNAL */ } } @@ -199,42 +207,66 @@ AutomationList::set_automation_style (AutoStyle s) } } +void +AutomationList::start_write_pass (double when) +{ + if (in_new_write_pass ()) { + _before = &get_state (); + } + ControlList::start_write_pass (when); +} + +void +AutomationList::write_pass_finished (double when, double thinning_factor) +{ + ControlList::write_pass_finished (when, thinning_factor); + /* automation control has deleted this or it is now owned by the session undo stack */ + _before = 0; +} + void AutomationList::start_touch (double when) { if (_state == Touch) { - Glib::Mutex::Lock lm (ControlList::_lock); - nascent.push_back (new NascentInfo (when)); + start_write_pass (when); } g_atomic_int_set (&_touching, 1); } void -AutomationList::stop_touch (bool mark, double when) +AutomationList::stop_touch (bool mark, double) { + if (g_atomic_int_get (&_touching) == 0) { + /* this touch has already been stopped (probably by Automatable::transport_stopped), + so we've nothing to do. + */ + return; + } + g_atomic_int_set (&_touching, 0); if (_state == Touch) { - Glib::Mutex::Lock lm (ControlList::_lock); - + if (mark) { - nascent.back()->end_time = when; - - } else { - - /* nascent info created in start touch but never used. just get rid of it. - */ - - assert (!nascent.empty ()); - - NascentInfo* ninfo = nascent.back (); - nascent.erase (nascent.begin()); - delete ninfo; + + /* XXX need to mark the last added point with the + * current time + */ } } } +/* _before may be owned by the undo stack, + * so we have to be careful about doing this. +*/ +void +AutomationList::clear_history () +{ + delete _before; + _before = 0; +} + void AutomationList::thaw () { @@ -257,11 +289,11 @@ AutomationList::state (bool full) { XMLNode* root = new XMLNode (X_("AutomationList")); char buf[64]; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg (X_("C")); root->add_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter)); - root->add_property ("id", _id.to_s()); + root->add_property ("id", id().to_s()); snprintf (buf, sizeof (buf), "%.12g", _default_value); root->add_property ("default", buf); @@ -269,8 +301,6 @@ AutomationList::state (bool full) root->add_property ("min-yval", buf); snprintf (buf, sizeof (buf), "%.12g", _max_yval); root->add_property ("max-yval", buf); - snprintf (buf, sizeof (buf), "%.12g", _max_xval); - root->add_property ("max-xval", buf); root->add_property ("interpolation-style", enum_2_string (_interpolation)); @@ -281,7 +311,11 @@ AutomationList::state (bool full) if (_state != Write) { root->add_property ("state", auto_state_to_string (_state)); } else { - root->add_property ("state", auto_state_to_string (Off)); + if (_events.empty ()) { + root->add_property ("state", auto_state_to_string (Off)); + } else { + root->add_property ("state", auto_state_to_string (Touch)); + } } } else { /* never save anything but Off for automation state to a template */ @@ -373,6 +407,7 @@ AutomationList::deserialize_events (const XMLNode& node) int AutomationList::set_state (const XMLNode& node, int version) { + LocaleGuard lg (X_("C")); XMLNodeList nlist = node.children(); XMLNode* nsos; XMLNodeIterator niter; @@ -418,7 +453,7 @@ AutomationList::set_state (const XMLNode& node, int version) fast_simple_add (x, y); } - thaw (); + thaw (); return 0; } @@ -428,16 +463,15 @@ AutomationList::set_state (const XMLNode& node, int version) return -1; } - if ((prop = node.property ("id")) != 0) { - _id = prop->value (); + if (set_id (node)) { /* update session AL list */ AutomationListCreated(this); } if ((prop = node.property (X_("automation-id"))) != 0){ - _parameter = EventTypeMap::instance().new_parameter(prop->value()); + _parameter = EventTypeMap::instance().from_symbol(prop->value()); } else { - warning << "Legacy session: automation list has no automation-id property."; + warning << "Legacy session: automation list has no automation-id property." << endmsg; } if ((prop = node.property (X_("interpolation-style"))) != 0) { @@ -463,6 +497,7 @@ AutomationList::set_state (const XMLNode& node, int version) if (_state == Write) { _state = Off; } + automation_state_changed(_state); } else { _state = Off; } @@ -479,14 +514,8 @@ AutomationList::set_state (const XMLNode& node, int version) _max_yval = FLT_MAX; } - if ((prop = node.property (X_("max-xval"))) != 0) { - _max_xval = atof (prop->value ().c_str()); - } else { - _max_xval = 0; // means "no limit ; - } - bool have_events = false; - + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { if ((*niter)->name() == X_("events")) { deserialize_events (*(*niter)); @@ -506,3 +535,24 @@ AutomationList::set_state (const XMLNode& node, int version) return 0; } +bool +AutomationList::operator!= (AutomationList const & other) const +{ + return ( + static_cast (*this) != static_cast (other) || + _state != other._state || + _style != other._style || + _touching != other._touching + ); +} + +PBD::PropertyBase * +AutomationListProperty::clone () const +{ + return new AutomationListProperty ( + this->property_id(), + boost::shared_ptr (new AutomationList (*this->_old.get())), + boost::shared_ptr (new AutomationList (*this->_current.get())) + ); +} +