fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / automation_list.cc
index 941178a698520b622fb0fdc6620e9228cc101f90..4b23378cacd1275e0d170fb660682ac177bca556 100644 (file)
 #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;
@@ -50,6 +51,7 @@ static void dumpit (const AutomationList& al, string prefix = "")
 #endif
 AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc)
        : ControlList(id, desc)
+       , _before (0)
 {
        _state = Off;
        _style = Absolute;
@@ -63,6 +65,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param
 
 AutomationList::AutomationList (const Evoral::Parameter& id)
        : ControlList(id, ARDOUR::ParameterDescriptor(id))
+       , _before (0)
 {
        _state = Off;
        _style = Absolute;
@@ -77,6 +80,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id)
 AutomationList::AutomationList (const AutomationList& other)
        : StatefulDestructible()
        , ControlList(other)
+       , _before (0)
 {
        _style = other._style;
        _state = other._state;
@@ -90,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;
@@ -106,6 +111,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
  */
 AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
        : ControlList(id, ARDOUR::ParameterDescriptor(id))
+       , _before (0)
 {
        g_atomic_int_set (&_touching, 0);
        _state = Off;
@@ -125,6 +131,7 @@ AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
 
 AutomationList::~AutomationList()
 {
+       delete _before;
 }
 
 boost::shared_ptr<Evoral::ControlList>
@@ -139,6 +146,7 @@ AutomationList::create_curve_if_necessary()
 {
        switch (_parameter.type()) {
        case GainAutomation:
+       case TrimAutomation:
        case PanAzimuthAutomation:
        case PanElevationAutomation:
        case PanWidthAutomation:
@@ -185,6 +193,12 @@ AutomationList::set_automation_state (AutoState s)
 {
        if (s != _state) {
                _state = s;
+               delete _before;
+               if (s == Write && _desc.toggled) {
+                       _before = &get_state ();
+               } else {
+                       _before = 0;
+               }
                automation_state_changed (s); /* EMIT SIGNAL */
        }
 }
@@ -198,6 +212,24 @@ 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)
 {
@@ -223,14 +255,26 @@ AutomationList::stop_touch (bool mark, double)
         if (_state == Touch) {
 
                 if (mark) {
-                       
+
                        /* XXX need to mark the last added point with the
-                        * current time 
+                        * 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 ()
 {
@@ -242,6 +286,12 @@ AutomationList::thaw ()
        }
 }
 
+Command*
+AutomationList::memento_command (XMLNode* before, XMLNode* after)
+{
+       return new MementoCommand<AutomationList> (*this, before, after);
+}
+
 XMLNode&
 AutomationList::get_state ()
 {
@@ -253,7 +303,7 @@ AutomationList::state (bool full)
 {
        XMLNode* root = new XMLNode (X_("AutomationList"));
        char buf[64];
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        root->add_property ("automation-id", EventTypeMap::instance().to_symbol(_parameter));
 
@@ -275,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 */
@@ -367,11 +421,11 @@ AutomationList::deserialize_events (const XMLNode& node)
 int
 AutomationList::set_state (const XMLNode& node, int version)
 {
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
        XMLNodeList nlist = node.children();
        XMLNode* nsos;
        XMLNodeIterator niter;
-       const XMLProperty* prop;
+       XMLProperty const * prop;
 
        if (node.name() == X_("events")) {
                /* partial state setting*/
@@ -389,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;
 
@@ -515,4 +569,4 @@ AutomationListProperty::clone () const
                boost::shared_ptr<AutomationList> (new AutomationList (*this->_current.get()))
                );
 }
-       
+