X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=blobdiff_plain;f=libs%2Fardour%2Fautomation_list.cc;h=4b23378cacd1275e0d170fb660682ac177bca556;hp=54d838f6e286c87b72d3cf4e632f2ab4cb6e43f6;hb=c8c6bca6587450ff64303dbc994a4cd28d6ce7aa;hpb=ab9a1eb34899e31f5a224bde3a9b6d83fc3557cb diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index 54d838f6e2..4b23378cac 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -25,11 +25,13 @@ #include #include "ardour/automation_list.h" #include "ardour/event_type_map.h" +#include "ardour/parameter_descriptor.h" #include "evoral/Curve.hpp" +#include "pbd/memento_command.h" #include "pbd/stacktrace.h" #include "pbd/enumwriter.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; @@ -47,8 +49,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 +80,7 @@ AutomationList::AutomationList (Evoral::Parameter id) AutomationList::AutomationList (const AutomationList& other) : StatefulDestructible() , ControlList(other) + , _before (0) { _style = other._style; _state = other._state; @@ -76,6 +94,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 +110,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; @@ -111,12 +131,14 @@ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) AutomationList::~AutomationList() { + delete _before; } 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 +146,7 @@ AutomationList::create_curve_if_necessary() { switch (_parameter.type()) { case GainAutomation: + case TrimAutomation: case PanAzimuthAutomation: case PanElevationAutomation: case PanWidthAutomation: @@ -137,26 +160,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; - _default_value = other._default_value; + ControlList::operator= (other); + _state = other._state; + _style = other._style; + _touching = other._touching; mark_dirty (); maybe_signal_changed (); @@ -180,11 +193,12 @@ 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 ()); - } + delete _before; + if (s == Write && _desc.toggled) { + _before = &get_state (); + } else { + _before = 0; + } automation_state_changed (s); /* EMIT SIGNAL */ } } @@ -198,19 +212,36 @@ AutomationList::set_automation_style (AutoStyle s) } } +void +AutomationList::start_write_pass (double when) +{ + delete _before; + if (in_new_write_pass ()) { + _before = &get_state (); + } else { + _before = 0; + } + ControlList::start_write_pass (when); +} + +void +AutomationList::write_pass_finished (double when, double thinning_factor) +{ + ControlList::write_pass_finished (when, thinning_factor); +} + 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), @@ -223,26 +254,27 @@ AutomationList::stop_touch (bool mark, double when) if (_state == Touch) { - assert (!nascent.empty ()); - - 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. - */ - - 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. + * + * ::before () transfers ownership, setting _before to 0 + */ +void +AutomationList::clear_history () +{ + delete _before; + _before = 0; +} + void AutomationList::thaw () { @@ -254,6 +286,12 @@ AutomationList::thaw () } } +Command* +AutomationList::memento_command (XMLNode* before, XMLNode* after) +{ + return new MementoCommand (*this, before, after); +} + XMLNode& AutomationList::get_state () { @@ -265,7 +303,7 @@ AutomationList::state (bool full) { XMLNode* root = new XMLNode (X_("AutomationList")); char buf[64]; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg; root->add_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter)); @@ -287,7 +325,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 */ @@ -363,8 +405,6 @@ AutomationList::deserialize_events (const XMLNode& node) fast_simple_add (x, y); } - thin (); - if (!ok) { clear (); error << _("automation list: cannot load coordinates from XML, all points ignored") << endmsg; @@ -381,11 +421,11 @@ AutomationList::deserialize_events (const XMLNode& node) int AutomationList::set_state (const XMLNode& node, int version) { - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg; XMLNodeList nlist = node.children(); XMLNode* nsos; XMLNodeIterator niter; - const XMLProperty* prop; + XMLProperty const * prop; if (node.name() == X_("events")) { /* partial state setting*/ @@ -403,7 +443,7 @@ AutomationList::set_state (const XMLNode& node, int version) const XMLNodeList& elist = node.children(); XMLNodeConstIterator i; - XMLProperty* prop; + XMLProperty const * prop; pframes_t x; double y; @@ -427,9 +467,7 @@ AutomationList::set_state (const XMLNode& node, int version) fast_simple_add (x, y); } - thin (); - - thaw (); + thaw (); return 0; } @@ -445,9 +483,9 @@ AutomationList::set_state (const XMLNode& node, int version) } 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) { @@ -473,6 +511,7 @@ AutomationList::set_state (const XMLNode& node, int version) if (_state == Write) { _state = Off; } + automation_state_changed(_state); } else { _state = Off; } @@ -510,3 +549,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())) + ); +} +