2 Copyright (C) 2001,2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <ardour/ardour.h>
25 #include <pbd/error.h>
26 #include <pbd/enumwriter.h>
27 #include <ardour/session.h>
28 #include <ardour/automatable.h>
33 using namespace ARDOUR;
37 Automatable::Automatable(Session& _session, const string& name)
38 : SessionObject(_session, name)
39 , _last_automation_snapshot(0)
43 Automatable::old_set_automation_state (const XMLNode& node)
45 const XMLProperty *prop;
47 if ((prop = node.property ("path")) != 0) {
48 load_automation (prop->value());
50 warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
53 if ((prop = node.property ("visible")) != 0) {
57 _visible_parameter_automation.clear ();
59 sstr << prop->value();
65 mark_automation_visible (what, true);
73 Automatable::load_automation (const string& path)
77 if (path[0] == '/') { // legacy
80 fullpath = _session.automation_dir();
83 ifstream in (fullpath.c_str());
86 warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
90 Glib::Mutex::Lock lm (_automation_lock);
92 _parameter_automation.clear ();
99 in >> port; if (!in) break;
100 in >> when; if (!in) goto bad;
101 in >> value; if (!in) goto bad;
103 AutomationList& al = automation_list (port);
104 al.add (when, value);
105 tosave.insert (port);
111 error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
112 _parameter_automation.clear ();
118 Automatable::what_has_automation (set<uint32_t>& s) const
120 Glib::Mutex::Lock lm (_automation_lock);
121 map<uint32_t,AutomationList*>::const_iterator li;
123 for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
124 s.insert ((*li).first);
129 Automatable::what_has_visible_automation (set<uint32_t>& s) const
131 Glib::Mutex::Lock lm (_automation_lock);
132 set<uint32_t>::const_iterator li;
134 for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) {
139 Automatable::automation_list (uint32_t parameter)
141 AutomationList* al = _parameter_automation[parameter];
144 al = _parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
145 /* let derived classes do whatever they need with this */
146 automation_list_creation_callback (parameter, *al);
153 Automatable::describe_parameter (uint32_t which)
155 /* derived classes will override this */
160 Automatable::can_automate (uint32_t what)
162 _can_automate_list.insert (what);
166 Automatable::mark_automation_visible (uint32_t what, bool yn)
169 _visible_parameter_automation.insert (what);
171 set<uint32_t>::iterator i;
173 if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) {
174 _visible_parameter_automation.erase (i);
180 Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
182 map<uint32_t,AutomationList*>::const_iterator li;
183 AutomationList::TimeComparator cmp;
185 next_event.when = max_frames;
187 for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
189 AutomationList::const_iterator i;
190 const AutomationList& alist (*((*li).second));
191 ControlEvent cp (now, 0.0f);
193 for (i = lower_bound (alist.const_begin(), alist.const_end(), &cp, cmp); i != alist.const_end() && (*i)->when < end; ++i) {
194 if ((*i)->when > now) {
199 if (i != alist.const_end() && (*i)->when < end) {
201 if ((*i)->when < next_event.when) {
202 next_event.when = (*i)->when;
207 return next_event.when != max_frames;
211 Automatable::set_automation_state (const XMLNode& node)
213 Glib::Mutex::Lock lm (_automation_lock);
215 _parameter_automation.clear ();
217 XMLNodeList nlist = node.children();
218 XMLNodeIterator niter;
220 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
223 if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, ¶m) != 1) {
224 error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
228 AutomationList& al = automation_list (param);
229 if (al.set_state (*(*niter)->children().front())) {
237 error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
238 _parameter_automation.clear ();
243 Automatable::get_automation_state ()
245 Glib::Mutex::Lock lm (_automation_lock);
246 XMLNode* node = new XMLNode (X_("Automation"));
249 if (_parameter_automation.empty()) {
253 map<uint32_t,AutomationList*>::iterator li;
255 for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
261 snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
262 child = new XMLNode (buf);
263 child->add_child_nocopy (li->second->get_state ());