summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-08-09 22:23:23 +0000
committerCarl Hetherington <carl@carlh.net>2010-08-09 22:23:23 +0000
commit78986385e17b82a6704c8792fb21a42cd86add9a (patch)
tree54bdca03098ff7e26b536b0640e3321b4b0a042e /libs/ardour
parent7c5f1b7a26df60417590340d4cfe367ed00e180a (diff)
Fix save/load of MIDI automation state. Fixes #3354.
git-svn-id: svn://localhost/ardour2/branches/3.0@7578 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/automatable.h8
-rw-r--r--libs/ardour/ardour/automation_list.h2
-rw-r--r--libs/ardour/ardour/midi_model.h2
-rw-r--r--libs/ardour/ardour/midi_source.h13
-rw-r--r--libs/ardour/ardour/plugin_insert.h2
-rw-r--r--libs/ardour/automatable.cc42
-rw-r--r--libs/ardour/automation_list.cc2
-rw-r--r--libs/ardour/midi_model.cc31
-rw-r--r--libs/ardour/midi_region.cc2
-rw-r--r--libs/ardour/midi_source.cc70
-rw-r--r--libs/ardour/plugin_insert.cc4
11 files changed, 133 insertions, 45 deletions
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index 2f35fc6b42..e0fe38e67e 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -65,7 +65,7 @@ public:
virtual std::string describe_parameter(Evoral::Parameter param);
- AutoState get_parameter_automation_state (Evoral::Parameter param, bool lock = true);
+ AutoState get_parameter_automation_state (Evoral::Parameter param);
virtual void set_parameter_automation_state (Evoral::Parameter param, AutoState);
AutoStyle get_parameter_automation_style (Evoral::Parameter param);
@@ -95,16 +95,13 @@ public:
int set_automation_state (const XMLNode&, Evoral::Parameter default_param);
XMLNode& get_automation_state();
-
- /** Emitted when the automation state of one of our controls changes */
- PBD::Signal1<void, Evoral::Parameter> AutomationStateChanged;
protected:
Session& _a_session;
void can_automate(Evoral::Parameter);
- virtual void auto_state_changed (Evoral::Parameter /*which*/) {}
+ virtual void automation_list_automation_state_changed (Evoral::Parameter, AutoState) {}
int load_automation (const std::string& path);
int old_set_automation_state(const XMLNode&);
@@ -116,7 +113,6 @@ public:
static nframes_t _automation_interval;
private:
- void automation_state_changed (Evoral::Parameter const &);
PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals
};
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index 77b8d49dc7..acb071cca7 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -54,7 +54,7 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
void set_automation_state (AutoState);
AutoState automation_state() const { return _state; }
- PBD::Signal0<void> automation_state_changed;
+ PBD::Signal1<void, AutoState> automation_state_changed;
void set_automation_style (AutoStyle m);
AutoStyle automation_style() const { return _style; }
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index e91d6484ea..e959535a36 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -174,7 +174,9 @@ private:
friend class DeltaCommand;
void source_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle);
+ void source_automation_state_changed (Evoral::Parameter, AutoState);
void control_list_interpolation_changed (Evoral::Parameter, Evoral::ControlList::InterpolationStyle);
+ void automation_list_automation_state_changed (Evoral::Parameter, AutoState);
PBD::ScopedConnectionList _midi_source_connections;
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index 8d20f9c7b6..5afcc20255 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -122,10 +122,17 @@ class MidiSource : virtual public Source
void copy_interpolation_from (boost::shared_ptr<MidiSource>);
void copy_interpolation_from (MidiSource *);
+ AutoState automation_state_of (Evoral::Parameter) const;
+ void set_automation_state_of (Evoral::Parameter, AutoState);
+ void copy_automation_state_from (boost::shared_ptr<MidiSource>);
+ void copy_automation_state_from (MidiSource *);
+
/** Emitted when a different MidiModel is set */
PBD::Signal0<void> ModelChanged;
/** Emitted when a parameter's interpolation style is changed */
PBD::Signal2<void, Evoral::Parameter, Evoral::ControlList::InterpolationStyle> InterpolationChanged;
+ /** Emitted when a parameter's automation state is changed */
+ PBD::Signal2<void, Evoral::Parameter, AutoState> AutomationStateChanged;
protected:
virtual void flush_midi() = 0;
@@ -159,6 +166,12 @@ class MidiSource : virtual public Source
*/
typedef std::map<Evoral::Parameter, Evoral::ControlList::InterpolationStyle> InterpolationStyleMap;
InterpolationStyleMap _interpolation_style;
+
+ /** Map of automation states to use for Parameters; if they are not in this map,
+ * the correct automation state is Off.
+ */
+ typedef std::map<Evoral::Parameter, AutoState> AutomationStateMap;
+ AutomationStateMap _automation_state;
};
}
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index c962832eb1..6656f755cf 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -133,7 +133,7 @@ class PluginInsert : public Processor
void connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now = 0);
void set_automatable ();
- void auto_state_changed (Evoral::Parameter which);
+ void control_list_automation_state_changed (Evoral::Parameter, AutoState);
void set_parameter_state (const XMLNode& node, int version);
void set_parameter_state_2X (const XMLNode& node, int version);
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index c71fabda37..d6379eb38e 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -147,19 +147,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
-
- /* connect to automation_state_changed so that we can emit a signal when one of our controls'
- automation state changes
- */
- boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl> (ac);
- if (c) {
- c->alist()->automation_state_changed.connect_same_thread (
- _control_connections, boost::bind (&Automatable::automation_state_changed, this, c->parameter())
- );
- }
+ 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
@@ -315,21 +313,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;
}
@@ -480,15 +473,8 @@ Automatable::automation_control (const Evoral::Parameter& id) const
}
void
-Automatable::automation_state_changed (Evoral::Parameter const & p)
-{
- AutomationStateChanged (p); /* EMIT SIGNAL */
-}
-
-void
Automatable::clear_controls ()
{
_control_connections.drop_connections ();
ControlSet::clear_controls ();
}
-
diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc
index 17f346db1d..2270b2eff7 100644
--- a/libs/ardour/automation_list.cc
+++ b/libs/ardour/automation_list.cc
@@ -180,7 +180,7 @@ AutomationList::set_automation_state (AutoState s)
{
if (s != _state) {
_state = s;
- automation_state_changed (); /* EMIT SIGNAL */
+ automation_state_changed (s); /* EMIT SIGNAL */
}
}
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 6922384e71..39daaacdea 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -1094,14 +1094,18 @@ MidiModel::set_midi_source (MidiSource* s)
_midi_source->InterpolationChanged.connect_same_thread (
_midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2)
);
+
+ _midi_source->AutomationStateChanged.connect_same_thread (
+ _midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2)
+ );
}
/** The source has signalled that the interpolation style for a parameter has changed. In order to
* keep MidiSource and ControlList interpolation state the same, we pass this change onto the
* appropriate ControlList.
*
- * The idea is that MidiSource and the MidiModel's ControlList states are kept in sync, and the
- * MidiSource's InterpolationChanged signal is listened to by the GUI.
+ * The idea is that MidiSource and the MidiModel's ControlList states are kept in sync, and one
+ * or the other is listened to by the GUI.
*/
void
MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
@@ -1119,18 +1123,37 @@ MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::Cont
_midi_source->set_interpolation_of (p, s);
}
+void
+MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s)
+{
+ Glib::Mutex::Lock lm (_control_lock);
+ boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (control(p)->list ());
+ al->set_automation_state (s);
+}
+
+void
+MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s)
+{
+ _midi_source->set_automation_state_of (p, s);
+}
+
boost::shared_ptr<Evoral::Control>
MidiModel::control_factory (Evoral::Parameter const & p)
{
boost::shared_ptr<Evoral::Control> c = Automatable::control_factory (p);
- /* Set up newly created control's lists to the appropriate interpolation state
- from our source.
+ /* Set up newly created control's lists to the appropriate interpolation and
+ automation state from our source.
*/
assert (_midi_source);
c->list()->set_interpolation (_midi_source->interpolation_of (p));
+ boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (c->list ());
+ assert (al);
+
+ al->set_automation_state (_midi_source->automation_state_of (p));
+
return c;
}
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index c76b6a859e..91f9ee58ed 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -291,7 +291,7 @@ MidiRegion::model_changed ()
}
/* watch for changes to controls' AutoState */
- model()->AutomationStateChanged.connect_same_thread (
+ midi_source()->AutomationStateChanged.connect_same_thread (
_model_connection, boost::bind (&MidiRegion::model_automation_state_changed, this, _1)
);
}
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 5a823d332e..97fb801a6c 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -102,7 +102,13 @@ MidiSource::get_state ()
child->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
child->add_property (X_("style"), enum_2_string (i->second));
}
-
+
+ for (AutomationStateMap::const_iterator i = _automation_state.begin(); i != _automation_state.end(); ++i) {
+ XMLNode* child = node.add_child (X_("AutomationState"));
+ child->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first));
+ child->add_property (X_("state"), enum_2_string (i->second));
+ }
+
return node;
}
@@ -134,6 +140,25 @@ MidiSource::set_state (const XMLNode& node, int /*version*/)
Evoral::ControlList::InterpolationStyle s = static_cast<Evoral::ControlList::InterpolationStyle> (string_2_enum (prop->value(), s));
set_interpolation_of (p, s);
+
+ } else if ((*i)->name() == X_("AutomationState")) {
+
+ XMLProperty* prop;
+
+ if ((prop = (*i)->property (X_("parameter"))) == 0) {
+ error << _("Missing parameter property on AutomationState") << endmsg;
+ return -1;
+ }
+
+ Evoral::Parameter p = EventTypeMap::instance().new_parameter (prop->value());
+
+ if ((prop = (*i)->property (X_("state"))) == 0) {
+ error << _("Missing state property on AutomationState") << endmsg;
+ return -1;
+ }
+
+ AutoState s = static_cast<AutoState> (string_2_enum (prop->value(), s));
+ set_automation_state_of (p, s);
}
}
@@ -290,6 +315,7 @@ MidiSource::clone (Evoral::MusicalTime begin, Evoral::MusicalTime end)
newsrc->set_timeline_position(_timeline_position);
newsrc->copy_interpolation_from (this);
+ newsrc->copy_automation_state_from (this);
if (_model) {
if (begin == Evoral::MinMusicalTime && end == Evoral::MaxMusicalTime) {
@@ -385,6 +411,17 @@ MidiSource::interpolation_of (Evoral::Parameter p) const
return i->second;
}
+AutoState
+MidiSource::automation_state_of (Evoral::Parameter p) const
+{
+ AutomationStateMap::const_iterator i = _automation_state.find (p);
+ if (i == _automation_state.end()) {
+ return Off;
+ }
+
+ return i->second;
+}
+
/** Set interpolation style to be used for a given parameter. This change will be
* propagated to anyone who needs to know.
*/
@@ -406,15 +443,46 @@ MidiSource::set_interpolation_of (Evoral::Parameter p, Evoral::ControlList::Inte
}
void
+MidiSource::set_automation_state_of (Evoral::Parameter p, AutoState s)
+{
+ if (automation_state_of (p) == s) {
+ return;
+ }
+
+ if (s == Off) {
+ /* automation state is being set to the default, so we don't need a note in our map */
+ _automation_state.erase (p);
+ } else {
+ _automation_state[p] = s;
+ }
+
+ AutomationStateChanged (p, s); /* EMIT SIGNAL */
+}
+
+void
MidiSource::copy_interpolation_from (boost::shared_ptr<MidiSource> s)
{
copy_interpolation_from (s.get ());
}
void
+MidiSource::copy_automation_state_from (boost::shared_ptr<MidiSource> s)
+{
+ copy_automation_state_from (s.get ());
+}
+
+void
MidiSource::copy_interpolation_from (MidiSource* s)
{
_interpolation_style = s->_interpolation_style;
/* XXX: should probably emit signals here */
}
+
+void
+MidiSource::copy_automation_state_from (MidiSource* s)
+{
+ _automation_state = s->_automation_state;
+
+ /* XXX: should probably emit signals here */
+}
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index fa48156787..d1f09dd0a8 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -114,7 +114,7 @@ PluginInsert::~PluginInsert ()
}
void
-PluginInsert::auto_state_changed (Evoral::Parameter which)
+PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
{
if (which.type() != PluginAutomation)
return;
@@ -122,7 +122,7 @@ PluginInsert::auto_state_changed (Evoral::Parameter which)
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(control (which));
- if (c && ((AutomationList*)c->list().get())->automation_state() != Off) {
+ if (c && s != Off) {
_plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
}
}