summaryrefslogtreecommitdiff
path: root/libs/ardour/automatable.cc
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-06-27 15:51:50 +0000
committerDavid Robillard <d@drobilla.net>2007-06-27 15:51:50 +0000
commitd7bd270aa10b3a8669223debe4c1b572ae876e2b (patch)
treedb9ad92cb5096a54a9d7e91873fe73530ceaf21b /libs/ardour/automatable.cc
parentd7afe01c307e35719dc1ee41c079f81f40f009df (diff)
Big ol' automation refactor.
Things with automation parameters now inherit from Automatable, which handles serialization, fetching/adding/removing parameters, etc. Use AutomationList everywhere instead of Curve, make Curve a member of AutomationList instead (towards other types of "Curve" needed for CC, among other things). Work towards MIDI CC sending "automation" tracks. git-svn-id: svn://localhost/ardour2/trunk@2069 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/automatable.cc')
-rw-r--r--libs/ardour/automatable.cc242
1 files changed, 193 insertions, 49 deletions
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 2ce553a188..40ab7af769 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -62,7 +62,7 @@ Automatable::old_set_automation_state (const XMLNode& node)
if (sstr.fail()) {
break;
}
- mark_automation_visible (what, true);
+ mark_automation_visible (ParamID(PluginAutomation, what), true);
}
}
@@ -88,7 +88,7 @@ Automatable::load_automation (const string& path)
}
Glib::Mutex::Lock lm (_automation_lock);
- set<uint32_t> tosave;
+ set<ParamID> tosave;
_parameter_automation.clear ();
while (in) {
@@ -100,9 +100,10 @@ Automatable::load_automation (const string& path)
in >> when; if (!in) goto bad;
in >> value; if (!in) goto bad;
- AutomationList& al = automation_list (port);
- al.add (when, value);
- tosave.insert (port);
+ /* FIXME: this is legacy and only used for plugin inserts? I think? */
+ AutomationList* al = automation_list (ParamID(PluginAutomation, port), true);
+ al->add (when, value);
+ tosave.insert (ParamID(PluginAutomation, port));
}
return 0;
@@ -113,12 +114,27 @@ Automatable::load_automation (const string& path)
return -1;
}
+void
+Automatable::add_automation_parameter(AutomationList* al)
+{
+ _parameter_automation[al->param_id()] = al;
+
+ /* let derived classes do whatever they need with this */
+ automation_list_creation_callback (al->param_id(), *al);
+
+ cerr << _name << ": added (visible, can_automate) parameter " << al->param_id().to_string() << ", # params = "
+ << _parameter_automation.size() << endl;
+
+ // FIXME: sane default behaviour?
+ _visible_parameter_automation.insert(al->param_id());
+ _can_automate_list.insert(al->param_id());
+}
void
-Automatable::what_has_automation (set<uint32_t>& s) const
+Automatable::what_has_automation (set<ParamID>& s) const
{
Glib::Mutex::Lock lm (_automation_lock);
- map<uint32_t,AutomationList*>::const_iterator li;
+ map<ParamID,AutomationList*>::const_iterator li;
for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
s.insert ((*li).first);
@@ -126,49 +142,79 @@ Automatable::what_has_automation (set<uint32_t>& s) const
}
void
-Automatable::what_has_visible_automation (set<uint32_t>& s) const
+Automatable::what_has_visible_automation (set<ParamID>& s) const
{
Glib::Mutex::Lock lm (_automation_lock);
- set<uint32_t>::const_iterator li;
+ set<ParamID>::const_iterator li;
for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) {
s.insert (*li);
}
}
-AutomationList&
-Automatable::automation_list (uint32_t parameter)
+
+/** Returns NULL if we don't have an AutomationList for \a parameter.
+ */
+AutomationList*
+Automatable::automation_list (ParamID parameter, bool create_if_missing)
{
- AutomationList* al = _parameter_automation[parameter];
+ std::map<ParamID,AutomationList*>::iterator i = _parameter_automation.find(parameter);
+
+ if (i != _parameter_automation.end()) {
+ return i->second;
+
+ } else if (create_if_missing) {
+ AutomationList* al = new AutomationList (parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter));
+ add_automation_parameter(al);
+ return al;
- if (al == 0) {
- al = _parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
- /* let derived classes do whatever they need with this */
- automation_list_creation_callback (parameter, *al);
+ } else {
+ warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg;
+ return NULL;
}
+}
- return *al;
+const AutomationList*
+Automatable::automation_list (ParamID parameter) const
+{
+ std::map<ParamID,AutomationList*>::const_iterator i = _parameter_automation.find(parameter);
+
+ if (i != _parameter_automation.end()) {
+ return i->second;
+ } else {
+ warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg;
+ return NULL;
+ }
}
+
string
-Automatable::describe_parameter (uint32_t which)
+Automatable::describe_parameter (ParamID param)
{
- /* derived classes will override this */
- return "";
+ /* derived classes like PluginInsert should override this */
+
+ if (param == ParamID(GainAutomation))
+ return _("Fader");
+ else if (param == ParamID(PanAutomation))
+ return _("Pan");
+ else if (param.type() == MidiCCAutomation)
+ return string_compose("MIDI CC %1", param.id());
+ else
+ return param.to_string();
}
void
-Automatable::can_automate (uint32_t what)
+Automatable::can_automate (ParamID what)
{
_can_automate_list.insert (what);
}
void
-Automatable::mark_automation_visible (uint32_t what, bool yn)
+Automatable::mark_automation_visible (ParamID what, bool yn)
{
if (yn) {
_visible_parameter_automation.insert (what);
} else {
- set<uint32_t>::iterator i;
+ set<ParamID>::iterator i;
if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) {
_visible_parameter_automation.erase (i);
@@ -179,7 +225,7 @@ Automatable::mark_automation_visible (uint32_t what, bool yn)
bool
Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
{
- map<uint32_t,AutomationList*>::const_iterator li;
+ map<ParamID,AutomationList*>::const_iterator li;
AutomationList::TimeComparator cmp;
next_event.when = max_frames;
@@ -207,36 +253,50 @@ Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_e
return next_event.when != max_frames;
}
+/** \a legacy_param is used for loading legacy sessions where an object (IO, Panner)
+ * had a single automation parameter, with it's type implicit. Derived objects should
+ * pass that type and it will be used for the untyped AutomationList found.
+ */
int
-Automatable::set_automation_state (const XMLNode& node)
+Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param)
{
Glib::Mutex::Lock lm (_automation_lock);
_parameter_automation.clear ();
+ _visible_parameter_automation.clear ();
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
-
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- uint32_t param;
- if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
- error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
- continue;
- }
+ /*if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
+ error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
+ continue;
+ }*/
+
+ if ((*niter)->name() == "AutomationList") {
+
+ const XMLProperty* id_prop = (*niter)->property("automation-id");
- AutomationList& al = automation_list (param);
- if (al.set_state (*(*niter)->children().front())) {
- goto bad;
+ ParamID param = (id_prop ? ParamID(id_prop->value()) : legacy_param);
+
+ AutomationList* al = new AutomationList(**niter, param);
+
+ if (!id_prop) {
+ warning << "AutomationList node without automation-id property, "
+ << "using default: " << legacy_param.to_string() << endmsg;
+ al->set_param_id(legacy_param);
+ }
+
+ add_automation_parameter(al);
+
+ } else {
+ error << "Expected AutomationList node, got '" << (*niter)->name() << endmsg;
}
}
return 0;
-
- bad:
- error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
- _parameter_automation.clear ();
- return -1;
}
XMLNode&
@@ -244,24 +304,108 @@ Automatable::get_automation_state ()
{
Glib::Mutex::Lock lm (_automation_lock);
XMLNode* node = new XMLNode (X_("Automation"));
- string fullpath;
+
+ cerr << "'" << _name << "'->get_automation_state, # params = " << _parameter_automation.size() << endl;
if (_parameter_automation.empty()) {
return *node;
}
- map<uint32_t,AutomationList*>::iterator li;
+ map<ParamID,AutomationList*>::iterator li;
for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
-
- XMLNode* child;
-
- char buf[64];
- stringstream str;
- snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
- child = new XMLNode (buf);
- child->add_child_nocopy (li->second->get_state ());
+ node->add_child_nocopy (li->second->get_state ());
}
return *node;
}
+
+void
+Automatable::clear_automation ()
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ map<ParamID,AutomationList*>::iterator li;
+
+ for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li)
+ li->second->clear();
+}
+
+void
+Automatable::set_parameter_automation_state (ParamID param, AutoState s)
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ AutomationList* al = automation_list (param, true);
+
+ if (s != al->automation_state()) {
+ al->set_automation_state (s);
+ _session.set_dirty ();
+ }
+}
+
+AutoState
+Automatable::get_parameter_automation_state (ParamID param)
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ AutomationList* al = automation_list(param);
+
+ if (al) {
+ return al->automation_state();
+ } else {
+ return Off;
+ }
+}
+
+void
+Automatable::set_parameter_automation_style (ParamID param, AutoStyle s)
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ AutomationList* al = automation_list (param, true);
+
+ if (s != al->automation_style()) {
+ al->set_automation_style (s);
+ _session.set_dirty ();
+ }
+}
+
+AutoStyle
+Automatable::get_parameter_automation_style (ParamID param)
+{
+ Glib::Mutex::Lock lm (_automation_lock);
+
+ AutomationList* al = automation_list(param);
+
+ if (al) {
+ return al->automation_style();
+ } else {
+ return Absolute; // whatever
+ }
+}
+
+void
+Automatable::protect_automation ()
+{
+ set<ParamID> automated_params;
+
+ what_has_automation (automated_params);
+
+ for (set<ParamID>::iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
+
+ AutomationList* al = automation_list (*i);
+
+ switch (al->automation_state()) {
+ case Write:
+ al->set_automation_state (Off);
+ break;
+ case Touch:
+ al->set_automation_state (Play);
+ break;
+ default:
+ break;
+ }
+ }
+}
+