#include <inttypes.h>
#include <cstdio>
#include <errno.h>
+
+#include <glibmm/miscutils.h>
+
#include "pbd/error.h"
#include "pbd/enumwriter.h"
{
}
+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)
{
{
string fullpath;
- if (path[0] == '/') { // legacy
+ if (Glib::path_is_absolute (path)) { // legacy
fullpath = path;
} else {
fullpath = _a_session.automation_dir();
{
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
/* 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);
}
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;
}
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());
}
}
boost::shared_ptr<AutomationList> list(new AutomationList(param));
Evoral::Control* control = NULL;
if (param.type() >= MidiCCAutomation && param.type() <= MidiChannelPressureAutomation) {
- control = new MidiTrack::MidiControl((MidiTrack*)this, param);
+ MidiTrack* mt = dynamic_cast<MidiTrack*>(this);
+ if (mt) {
+ control = new MidiTrack::MidiControl(mt, param);
+ } else {
+ warning << "MidiCCAutomation for non-MidiTrack" << endl;
+ }
} else if (param.type() == PluginAutomation) {
- control = new PluginInsert::PluginControl((PluginInsert*)this, param);
+ PluginInsert* pi = dynamic_cast<PluginInsert*>(this);
+ if (pi) {
+ control = new PluginInsert::PluginControl(pi, param);
+ } else {
+ warning << "PluginAutomation for non-Plugin" << endl;
+ }
} else if (param.type() == GainAutomation) {
- control = new Amp::GainControl( X_("gaincontrol"), _a_session, (Amp*)this, param);
+ Amp* amp = dynamic_cast<Amp*>(this);
+ if (amp) {
+ control = new Amp::GainControl(X_("gaincontrol"), _a_session, amp, param);
+ } else {
+ warning << "GainAutomation for non-Amp" << endl;
+ }
} else if (param.type() == PanAutomation) {
Panner* me = dynamic_cast<Panner*>(this);
if (me) {
control = new Panner::PanControllable(me->session(), X_("panner"), *me, param);
} else {
- cerr << "ERROR: PanAutomation for non-Panner" << endl;
+ warning << "PanAutomation for non-Panner" << endl;
}
- } else {
+ }
+
+ if (!control) {
control = new AutomationControl(_a_session, param);
}
+
control->set_list(list);
return boost::shared_ptr<Evoral::Control>(control);
}
return boost::dynamic_pointer_cast<const AutomationControl>(Evoral::ControlSet::control(id));
}
+void
+Automatable::clear_controls ()
+{
+ _control_connections.drop_connections ();
+ ControlSet::clear_controls ();
+}