forward port 2.X changes up to and including rev 6909
[ardour.git] / libs / ardour / automatable.cc
index 1ef39a61f0df82dfd81f9481b214c1c336cd9641..5ae4e96b4e1f87436e53a0356ba9ed350e6d22b6 100644 (file)
@@ -22,6 +22,9 @@
 #include <inttypes.h>
 #include <cstdio>
 #include <errno.h>
+
+#include <glibmm/miscutils.h>
+
 #include "pbd/error.h"
 #include "pbd/enumwriter.h"
 
@@ -49,6 +52,18 @@ Automatable::Automatable(Session& session)
 {
 }
 
+Automatable::Automatable (const Automatable& other)
+        : ControlSet (other)
+        , _a_session (other._a_session)
+        , _last_automation_snapshot (0)
+{
+        Glib::Mutex::Lock lm (other._control_lock);
+
+        for (Controls::const_iterator i = other._controls.begin(); i != other._controls.end(); ++i) {
+                boost::shared_ptr<Evoral::Control> ac (control_factory (i->first));
+               add_control (ac);
+        }
+}
 int
 Automatable::old_set_automation_state (const XMLNode& node)
 {
@@ -86,7 +101,7 @@ Automatable::load_automation (const string& path)
 {
        string fullpath;
 
-       if (path[0] == '/') { // legacy
+       if (Glib::path_is_absolute (path)) { // legacy
                fullpath = path;
        } else {
                fullpath = _a_session.automation_dir();
@@ -135,9 +150,17 @@ Automatable::add_control(boost::shared_ptr<Evoral::Control> ac)
 {
        Evoral::Parameter param = ac->parameter();
 
-       ControlSet::add_control(ac);
-       _can_automate_list.insert(param);
-       auto_state_changed(param); // sync everything up
+       boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (ac->list ());
+       assert (al);
+       
+       al->automation_state_changed.connect_same_thread (
+               _list_connections, boost::bind (&Automatable::automation_list_automation_state_changed, this, ac->parameter(), _1)
+               );
+
+       ControlSet::add_control (ac);
+       _can_automate_list.insert (param);
+
+       automation_list_automation_state_changed (param, al->automation_state ()); // sync everything up
 }
 
 void
@@ -162,7 +185,7 @@ Automatable::describe_parameter (Evoral::Parameter param)
                /* ID's are zero-based, present them as 1-based */
                return (string_compose(_("Pan %1"), param.id() + 1));
        } else if (param.type() == MidiCCAutomation) {
-               return string_compose("%2 [%3]",
+               return string_compose("%1: %2 [%3]",
                                param.id() + 1, midi_name(param.id()), int(param.channel()) + 1);
        } else if (param.type() == MidiPgmChangeAutomation) {
                return string_compose("Program [%1]", int(param.channel()) + 1);
@@ -293,21 +316,16 @@ Automatable::set_parameter_automation_state (Evoral::Parameter param, AutoState
 }
 
 AutoState
-Automatable::get_parameter_automation_state (Evoral::Parameter param, bool lock)
+Automatable::get_parameter_automation_state (Evoral::Parameter param)
 {
        AutoState result = Off;
 
-       if (lock)
-               control_lock().lock();
-
        boost::shared_ptr<Evoral::Control> c = control(param);
        boost::shared_ptr<AutomationList> l = boost::dynamic_pointer_cast<AutomationList>(c->list());
 
-       if (c)
+       if (c) {
                result = l->automation_state();
-
-       if (lock)
-               control_lock().unlock();
+       }
 
        return result;
 }
@@ -376,7 +394,7 @@ Automatable::automation_snapshot (nframes_t now, bool force)
                        boost::shared_ptr<AutomationControl> c
                                        = boost::dynamic_pointer_cast<AutomationControl>(i->second);
                        if (c->automation_write()) {
-                               c->list()->rt_add (now, i->second->user_float());
+                               c->list()->rt_add (now, i->second->user_double());
                        }
                }
 
@@ -457,3 +475,9 @@ Automatable::automation_control (const Evoral::Parameter& id) const
        return boost::dynamic_pointer_cast<const AutomationControl>(Evoral::ControlSet::control(id));
 }
 
+void
+Automatable::clear_controls ()
+{
+       _control_connections.drop_connections ();
+       ControlSet::clear_controls ();
+}