X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fautomation_list.cc;h=479674aee6a55aee94ad86aaca3dbaf54454e707;hb=7d96960b162d25da87c388a3083775e8770bba56;hp=68bbd1716244434c47f252ef24380658e41f5cca;hpb=6b0d22268b85f7033eb7ddcfe9e50e21b86eec34;p=ardour.git diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index 68bbd17162..479674aee6 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Paul Davis + Copyright (C) 2002 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,21 +23,19 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include "ardour/automation_list.h" +#include "ardour/event_type_map.h" +#include "evoral/Curve.hpp" +#include "pbd/stacktrace.h" +#include "pbd/enumwriter.h" #include "i18n.h" using namespace std; using namespace ARDOUR; -using namespace sigc; using namespace PBD; -sigc::signal AutomationList::AutomationListCreated; +PBD::Signal1 AutomationList::AutomationListCreated; #if 0 static void dumpit (const AutomationList& al, string prefix = "") @@ -50,7 +48,6 @@ static void dumpit (const AutomationList& al, string prefix = "") } #endif -/* XXX: min_val max_val redundant? (param.min() param.max()) */ AutomationList::AutomationList (Evoral::Parameter id) : ControlList(id) { @@ -58,27 +55,35 @@ AutomationList::AutomationList (Evoral::Parameter id) _style = Absolute; _touching = false; + create_curve_if_necessary(); + assert(_parameter.type() != NullAutomation); AutomationListCreated(this); } AutomationList::AutomationList (const AutomationList& other) - : ControlList(other) + : StatefulDestructible() + , ControlList(other) { + _style = other._style; _state = other._state; _touching = other._touching; - + + create_curve_if_necessary(); + assert(_parameter.type() != NullAutomation); AutomationListCreated(this); } AutomationList::AutomationList (const AutomationList& other, double start, double end) - : ControlList(other) + : ControlList(other, start, end) { _style = other._style; _state = other._state; _touching = other._touching; + create_curve_if_necessary(); + assert(_parameter.type() != NullAutomation); AutomationListCreated(this); } @@ -92,11 +97,14 @@ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) _touching = false; _state = Off; _style = Absolute; - - set_state (node); - if (id) + set_state (node, Stateful::loading_state_version); + + if (id) { _parameter = id; + } + + create_curve_if_necessary(); assert(_parameter.type() != NullAutomation); AutomationListCreated(this); @@ -104,7 +112,6 @@ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id) AutomationList::~AutomationList() { - GoingAway (); } boost::shared_ptr @@ -113,6 +120,22 @@ AutomationList::create(Evoral::Parameter id) return boost::shared_ptr(new AutomationList(id)); } +void +AutomationList::create_curve_if_necessary() +{ + switch (_parameter.type()) { + case GainAutomation: + case PanAutomation: + case FadeInAutomation: + case FadeOutAutomation: + case EnvelopeAutomation: + create_curve(); + break; + default: + break; + } +} + bool AutomationList::operator== (const AutomationList& other) { @@ -123,18 +146,18 @@ 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; - + mark_dirty (); maybe_signal_changed (); } @@ -196,11 +219,12 @@ AutomationList::thaw () ControlList::thaw(); if (_changed_when_thawed) { + _changed_when_thawed = false; StateChanged(); /* EMIT SIGNAL */ } } -void +void AutomationList::mark_dirty () const { ControlList::mark_dirty (); @@ -232,7 +256,7 @@ AutomationList::state (bool full) 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)); if (full) { @@ -257,6 +281,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; str << ' '; @@ -289,13 +315,13 @@ AutomationList::deserialize_events (const XMLNode& node) freeze (); clear (); - + stringstream str (content_node->content()); - + double x; double y; bool ok = true; - + while (str) { str >> x; if (!str) { @@ -308,7 +334,7 @@ AutomationList::deserialize_events (const XMLNode& node) } fast_simple_add (x, y); } - + if (!ok) { clear (); error << _("automation list: cannot load coordinates from XML, all points ignored") << endmsg; @@ -324,7 +350,7 @@ AutomationList::deserialize_events (const XMLNode& node) } int -AutomationList::set_state (const XMLNode& node) +AutomationList::set_state (const XMLNode& node, int version) { XMLNodeList nlist = node.children(); XMLNode* nsos; @@ -335,12 +361,12 @@ AutomationList::set_state (const XMLNode& node) /* partial state setting*/ return deserialize_events (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); + return set_state (*nsos, version); } /* old school */ @@ -350,27 +376,27 @@ AutomationList::set_state (const XMLNode& node) XMLProperty* prop; nframes_t x; double y; - + freeze (); clear (); - + for (i = elist.begin(); i != elist.end(); ++i) { - + if ((prop = (*i)->property ("x")) == 0) { error << _("automation list: no x-coordinate stored for control point (point ignored)") << endmsg; continue; } x = atoi (prop->value().c_str()); - + if ((prop = (*i)->property ("y")) == 0) { error << _("automation list: no y-coordinate stored for control point (point ignored)") << endmsg; continue; } y = atof (prop->value().c_str()); - + fast_simple_add (x, y); } - + thaw (); return 0; @@ -386,20 +412,20 @@ AutomationList::set_state (const XMLNode& node) /* update session AL list */ AutomationListCreated(this); } - - if ((prop = node.property (X_("automation-id"))) != 0){ + + if ((prop = node.property (X_("automation-id"))) != 0){ _parameter = EventTypeMap::instance().new_parameter(prop->value()); } else { warning << "Legacy session: automation list has no automation-id property."; } - + if ((prop = node.property (X_("interpolation-style"))) != 0) { _interpolation = (InterpolationStyle)string_2_enum(prop->value(), _interpolation); } else { _interpolation = Linear; } - - if ((prop = node.property (X_("default"))) != 0){ + + if ((prop = node.property (X_("default"))) != 0){ _default_value = atof (prop->value().c_str()); } else { _default_value = 0.0;