Fixup prev commit (LV2 X11 UI) -- #7837
[ardour.git] / libs / ardour / automatable.cc
1 /*
2  * Copyright (C) 2001-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2007-2015 David Robillard <d@drobilla.net>
4  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
5  * Copyright (C) 2010-2011 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2015-2018 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2015 Nick Mainsbridge <mainsbridge@gmail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include <cstdio>
25 #include <errno.h>
26
27 #include "pbd/gstdio_compat.h"
28 #include <glibmm/miscutils.h>
29
30 #include "pbd/error.h"
31
32 #include "ardour/amp.h"
33 #include "ardour/automatable.h"
34 #include "ardour/event_type_map.h"
35 #include "ardour/gain_control.h"
36 #include "ardour/monitor_control.h"
37 #include "ardour/midi_track.h"
38 #include "ardour/pan_controllable.h"
39 #include "ardour/pannable.h"
40 #include "ardour/plugin.h"
41 #include "ardour/plugin_insert.h"
42 #include "ardour/record_enable_control.h"
43 #include "ardour/session.h"
44 #ifdef LV2_SUPPORT
45 #include "ardour/uri_map.h"
46 #endif
47 #include "ardour/value_as_string.h"
48
49 #include "pbd/i18n.h"
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 /* used for templates (previously: !full_state) */
56 bool Automatable::skip_saving_automation = false;
57
58 const string Automatable::xml_node_name = X_("Automation");
59
60 Automatable::Automatable(Session& session)
61         : _a_session(session)
62         , _automated_controls (new ControlList)
63 {
64 }
65
66 Automatable::Automatable (const Automatable& other)
67         : ControlSet (other)
68         , Slavable ()
69         , _a_session (other._a_session)
70         , _automated_controls (new ControlList)
71 {
72         Glib::Threads::Mutex::Lock lm (other._control_lock);
73
74         for (Controls::const_iterator i = other._controls.begin(); i != other._controls.end(); ++i) {
75                 boost::shared_ptr<Evoral::Control> ac (control_factory (i->first));
76                 add_control (ac);
77         }
78 }
79
80 Automatable::~Automatable ()
81 {
82         {
83                 RCUWriter<ControlList> writer (_automated_controls);
84                 boost::shared_ptr<ControlList> cl = writer.get_copy ();
85                 cl->clear ();
86         }
87         _automated_controls.flush ();
88
89         Glib::Threads::Mutex::Lock lm (_control_lock);
90         for (Controls::const_iterator li = _controls.begin(); li != _controls.end(); ++li) {
91                 boost::dynamic_pointer_cast<AutomationControl>(li->second)->drop_references ();
92         }
93 }
94
95 int
96 Automatable::old_set_automation_state (const XMLNode& node)
97 {
98         XMLProperty const * prop;
99
100         if ((prop = node.property ("path")) != 0) {
101                 load_automation (prop->value());
102         } else {
103                 warning << _("Automation node has no path property") << endmsg;
104         }
105
106         return 0;
107 }
108
109 int
110 Automatable::load_automation (const string& path)
111 {
112         string fullpath;
113
114         if (Glib::path_is_absolute (path)) { // legacy
115                 fullpath = path;
116         } else {
117                 fullpath = _a_session.automation_dir();
118                 fullpath += path;
119         }
120
121         FILE * in = g_fopen (fullpath.c_str (), "rb");
122
123         if (!in) {
124                 warning << string_compose(_("cannot open %2 to load automation data (%3)")
125                                 , fullpath, strerror (errno)) << endmsg;
126                 return 1;
127         }
128
129         Glib::Threads::Mutex::Lock lm (control_lock());
130         set<Evoral::Parameter> tosave;
131         controls().clear ();
132
133         while (!feof(in)) {
134                 double when;
135                 double value;
136                 uint32_t port;
137
138                 if (3 != fscanf (in, "%d %lf %lf", &port, &when, &value)) {
139                         if (feof(in)) {
140                                 break;
141                         }
142                         goto bad;
143                 }
144
145                 Evoral::Parameter param(PluginAutomation, 0, port);
146                 /* FIXME: this is legacy and only used for plugin inserts?  I think? */
147                 boost::shared_ptr<Evoral::Control> c = control (param, true);
148                 c->list()->add (when, value);
149                 tosave.insert (param);
150         }
151         ::fclose (in);
152
153         return 0;
154
155 bad:
156         error << string_compose(_("cannot load automation data from %2"), fullpath) << endmsg;
157         controls().clear ();
158         ::fclose (in);
159         return -1;
160 }
161
162 void
163 Automatable::add_control(boost::shared_ptr<Evoral::Control> ac)
164 {
165         Evoral::Parameter param = ac->parameter();
166
167         boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (ac->list ());
168
169         boost::shared_ptr<AutomationControl> actl (boost::dynamic_pointer_cast<AutomationControl> (ac));
170
171         if ((!actl || !(actl->flags() & Controllable::NotAutomatable)) && al) {
172                 al->automation_state_changed.connect_same_thread (
173                         _list_connections,
174                         boost::bind (&Automatable::automation_list_automation_state_changed,
175                                      this, ac->parameter(), _1));
176         }
177
178         ControlSet::add_control (ac);
179
180         if ((!actl || !(actl->flags() & Controllable::NotAutomatable)) && al) {
181                 _can_automate_list.insert (param);
182                 automation_list_automation_state_changed (param, al->automation_state ()); // sync everything up
183         }
184 }
185
186 string
187 Automatable::describe_parameter (Evoral::Parameter param)
188 {
189         /* derived classes like PluginInsert should override this */
190
191         if (param == Evoral::Parameter(GainAutomation)) {
192                 return _("Fader");
193         } else if (param.type() == TrimAutomation) {
194                 return _("Trim");
195         } else if (param.type() == MuteAutomation) {
196                 return _("Mute");
197         } else if (param.type() == MidiCCAutomation) {
198                 return string_compose("Controller %1 [%2]", param.id(), int(param.channel()) + 1);
199         } else if (param.type() == MidiPgmChangeAutomation) {
200                 return string_compose("Program [%1]", int(param.channel()) + 1);
201         } else if (param.type() == MidiPitchBenderAutomation) {
202                 return string_compose("Bender [%1]", int(param.channel()) + 1);
203         } else if (param.type() == MidiChannelPressureAutomation) {
204                 return string_compose("Pressure [%1]", int(param.channel()) + 1);
205         } else if (param.type() == MidiNotePressureAutomation) {
206                 return string_compose("PolyPressure [%1]", int(param.channel()) + 1);
207 #ifdef LV2_SUPPORT
208         } else if (param.type() == PluginPropertyAutomation) {
209                 return string_compose("Property %1", URIMap::instance().id_to_uri(param.id()));
210 #endif
211         } else {
212                 return EventTypeMap::instance().to_symbol(param);
213         }
214 }
215
216 void
217 Automatable::can_automate (Evoral::Parameter what)
218 {
219         _can_automate_list.insert (what);
220 }
221
222 /** \a legacy_param is used for loading legacy sessions where an object (IO, Panner)
223  * had a single automation parameter, with it's type implicit.  Derived objects should
224  * pass that type and it will be used for the untyped AutomationList found.
225  */
226 int
227 Automatable::set_automation_xml_state (const XMLNode& node, Evoral::Parameter legacy_param)
228 {
229         Glib::Threads::Mutex::Lock lm (control_lock());
230
231         /* Don't clear controls, since some may be special derived Controllable classes */
232
233         XMLNodeList nlist = node.children();
234         XMLNodeIterator niter;
235
236         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
237
238                 /*if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
239                   error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
240                   continue;
241                   }*/
242
243                 if ((*niter)->name() == "AutomationList") {
244
245                         XMLProperty const * id_prop = (*niter)->property("automation-id");
246
247                         Evoral::Parameter param = (id_prop
248                                         ? EventTypeMap::instance().from_symbol(id_prop->value())
249                                         : legacy_param);
250
251                         if (param.type() == NullAutomation) {
252                                 warning << "Automation has null type" << endl;
253                                 continue;
254                         }
255
256                         if (!id_prop) {
257                                 warning << "AutomationList node without automation-id property, "
258                                         << "using default: " << EventTypeMap::instance().to_symbol(legacy_param) << endmsg;
259                         }
260
261                         if (_can_automate_list.find (param) == _can_automate_list.end ()) {
262                                 boost::shared_ptr<AutomationControl> actl = automation_control (param);
263                                 if (actl && (*niter)->children().size() > 0 && Config->get_limit_n_automatables () > 0) {
264                                         actl->set_flags (Controllable::Flag ((int)actl->flags() & ~Controllable::NotAutomatable));
265                                         can_automate (param);
266                                         info << "Marked parmater as automatable" << endl;
267                                 } else {
268                                         warning << "Ignored automation data for non-automatable parameter" << endl;
269                                         continue;
270                                 }
271                         }
272
273
274                         boost::shared_ptr<AutomationControl> existing = automation_control (param);
275
276                         if (existing) {
277                                 existing->alist()->set_state (**niter, 3000);
278                         } else {
279                                 boost::shared_ptr<Evoral::Control> newcontrol = control_factory(param);
280                                 add_control (newcontrol);
281                                 boost::shared_ptr<AutomationList> al (new AutomationList(**niter, param));
282                                 newcontrol->set_list(al);
283                         }
284
285                 } else {
286                         error << "Expected AutomationList node, got '" << (*niter)->name() << "'" << endmsg;
287                 }
288         }
289
290         return 0;
291 }
292
293 XMLNode&
294 Automatable::get_automation_xml_state ()
295 {
296         Glib::Threads::Mutex::Lock lm (control_lock());
297         XMLNode* node = new XMLNode (Automatable::xml_node_name);
298
299         if (controls().empty()) {
300                 return *node;
301         }
302
303         for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
304                 boost::shared_ptr<AutomationList> l = boost::dynamic_pointer_cast<AutomationList>(li->second->list());
305                 if (l) {
306                         node->add_child_nocopy (l->get_state ());
307                 }
308         }
309
310         return *node;
311 }
312
313 void
314 Automatable::set_parameter_automation_state (Evoral::Parameter param, AutoState s)
315 {
316         Glib::Threads::Mutex::Lock lm (control_lock());
317
318         boost::shared_ptr<AutomationControl> c = automation_control (param, true);
319
320         if (c && (s != c->automation_state())) {
321                 c->set_automation_state (s);
322                 _a_session.set_dirty ();
323                 AutomationStateChanged(); /* Emit signal */
324         }
325 }
326
327 AutoState
328 Automatable::get_parameter_automation_state (Evoral::Parameter param)
329 {
330         AutoState result = Off;
331
332         boost::shared_ptr<AutomationControl> c = automation_control(param);
333
334         if (c) {
335                 result = c->automation_state();
336         }
337
338         return result;
339 }
340
341 void
342 Automatable::protect_automation ()
343 {
344         typedef set<Evoral::Parameter> ParameterSet;
345         const ParameterSet& automated_params = what_can_be_automated ();
346
347         for (ParameterSet::const_iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
348
349                 boost::shared_ptr<Evoral::Control> c = control(*i);
350                 boost::shared_ptr<AutomationList> l = boost::dynamic_pointer_cast<AutomationList>(c->list());
351
352                 switch (l->automation_state()) {
353                 case Write:
354                         l->set_automation_state (Off);
355                         break;
356                 case Latch:
357                         /* fallthrough */
358                 case Touch:
359                         l->set_automation_state (Play);
360                         break;
361                 default:
362                         break;
363                 }
364         }
365 }
366
367 void
368 Automatable::non_realtime_locate (samplepos_t now)
369 {
370         bool rolling = _a_session.transport_rolling ();
371
372         for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
373
374                 boost::shared_ptr<AutomationControl> c
375                                 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
376                 if (c) {
377                         boost::shared_ptr<AutomationList> l
378                                 = boost::dynamic_pointer_cast<AutomationList>(c->list());
379
380                         if (!l) {
381                                 continue;
382                         }
383
384                         bool am_touching = c->touching ();
385                         if (rolling && am_touching) {
386                         /* when locating while rolling, and writing automation,
387                          * start a new write pass.
388                          * compare to compare to non_realtime_transport_stop()
389                          */
390                                 const bool list_did_write = !l->in_new_write_pass ();
391                                 c->stop_touch (-1); // time is irrelevant
392                                 l->stop_touch (-1);
393                                 c->commit_transaction (list_did_write);
394                                 l->write_pass_finished (now, Config->get_automation_thinning_factor ());
395
396                                 if (l->automation_state () == Write) {
397                                         l->set_automation_state (Touch);
398                                 }
399                                 if (l->automation_playback ()) {
400                                         c->set_value_unchecked (c->list ()->eval (now));
401                                 }
402                         }
403
404                         l->start_write_pass (now);
405
406                         if (rolling && am_touching) {
407                                 c->start_touch (now);
408                         }
409                 }
410         }
411 }
412
413 void
414 Automatable::non_realtime_transport_stop (samplepos_t now, bool /*flush_processors*/)
415 {
416         for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
417                 boost::shared_ptr<AutomationControl> c =
418                         boost::dynamic_pointer_cast<AutomationControl>(li->second);
419                 if (!c) {
420                         continue;
421                 }
422
423                 boost::shared_ptr<AutomationList> l =
424                         boost::dynamic_pointer_cast<AutomationList>(c->list());
425                 if (!l) {
426                         continue;
427                 }
428
429                 /* Stop any active touch gesture just before we mark the write pass
430                    as finished.  If we don't do this, the transport can end up stopped with
431                    an AutomationList thinking that a touch is still in progress and,
432                    when the transport is re-started, a touch will magically
433                    be happening without it ever have being started in the usual way.
434                 */
435                 const bool list_did_write = !l->in_new_write_pass ();
436
437                 c->stop_touch (now);
438                 l->stop_touch (now);
439
440                 c->commit_transaction (list_did_write);
441
442                 l->write_pass_finished (now, Config->get_automation_thinning_factor ());
443
444                 if (l->automation_state () == Write) {
445                         l->set_automation_state (Touch);
446                 }
447
448                 if (l->automation_playback ()) {
449                         c->set_value_unchecked (c->list ()->eval (now));
450                 }
451         }
452 }
453
454 void
455 Automatable::automation_run (samplepos_t start, pframes_t nframes, bool only_active)
456 {
457         if (only_active) {
458                 boost::shared_ptr<ControlList> cl = _automated_controls.reader ();
459                 for (ControlList::const_iterator ci = cl->begin(); ci != cl->end(); ++ci) {
460                         (*ci)->automation_run (start, nframes);
461                 }
462                 return;
463         }
464
465         for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
466                 boost::shared_ptr<AutomationControl> c =
467                         boost::dynamic_pointer_cast<AutomationControl>(li->second);
468                 if (!c) {
469                         continue;
470                 }
471                 c->automation_run (start, nframes);
472         }
473 }
474
475 void
476 Automatable::automation_list_automation_state_changed (Evoral::Parameter param, AutoState as)
477 {
478         {
479                 boost::shared_ptr<AutomationControl> c (automation_control(param));
480                 assert (c && c->list());
481
482                 RCUWriter<ControlList> writer (_automated_controls);
483                 boost::shared_ptr<ControlList> cl = writer.get_copy ();
484
485                 ControlList::iterator fi = std::find (cl->begin(), cl->end(), c);
486                 if (fi != cl->end()) {
487                         cl->erase (fi);
488                 }
489                 switch (as) {
490                         /* all potential  automation_playback() states */
491                         case Play:
492                         case Touch:
493                         case Latch:
494                                 cl->push_back (c);
495                                 break;
496                         case Off:
497                         case Write:
498                                 break;
499                 }
500         }
501         _automated_controls.flush();
502 }
503
504 boost::shared_ptr<Evoral::Control>
505 Automatable::control_factory(const Evoral::Parameter& param)
506 {
507         Evoral::Control*                  control   = NULL;
508         bool                              make_list = true;
509         ParameterDescriptor               desc(param);
510         boost::shared_ptr<AutomationList> list;
511
512         if (param.type() >= MidiCCAutomation && param.type() <= MidiChannelPressureAutomation) {
513                 MidiTrack* mt = dynamic_cast<MidiTrack*>(this);
514                 if (mt) {
515                         control = new MidiTrack::MidiControl(mt, param);
516                         make_list = false;  // No list, this is region "automation"
517                 }
518         } else if (param.type() == PluginAutomation) {
519                 PluginInsert* pi = dynamic_cast<PluginInsert*>(this);
520                 if (pi) {
521                         pi->plugin(0)->get_parameter_descriptor(param.id(), desc);
522                         control = new PluginInsert::PluginControl(pi, param, desc);
523                 } else {
524                         warning << "PluginAutomation for non-Plugin" << endl;
525                 }
526         } else if (param.type() == PluginPropertyAutomation) {
527                 PluginInsert* pi = dynamic_cast<PluginInsert*>(this);
528                 if (pi) {
529                         desc = pi->plugin(0)->get_property_descriptor(param.id());
530                         if (desc.datatype != Variant::NOTHING) {
531                                 if (!Variant::type_is_numeric(desc.datatype)) {
532                                         make_list = false;  // Can't automate non-numeric data yet
533                                 } else {
534                                         list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
535                                 }
536                                 control = new PluginInsert::PluginPropertyControl(pi, param, desc, list);
537                         }
538                 } else {
539                         warning << "PluginPropertyAutomation for non-Plugin" << endl;
540                 }
541         } else if (param.type() == GainAutomation) {
542                 control = new GainControl(_a_session, param);
543         } else if (param.type() == TrimAutomation) {
544                 control = new GainControl(_a_session, param);
545         } else if (param.type() == PanAzimuthAutomation || param.type() == PanWidthAutomation || param.type() == PanElevationAutomation) {
546                 Pannable* pannable = dynamic_cast<Pannable*>(this);
547                 if (pannable) {
548                         control = new PanControllable (_a_session, pannable->describe_parameter (param), pannable, param);
549                 } else {
550                         warning << "PanAutomation for non-Pannable" << endl;
551                 }
552         } else if (param.type() == RecEnableAutomation) {
553                 Recordable* re = dynamic_cast<Recordable*> (this);
554                 if (re) {
555                         control = new RecordEnableControl (_a_session, X_("recenable"), *re);
556                 }
557         } else if (param.type() == MonitoringAutomation) {
558                 Monitorable* m = dynamic_cast<Monitorable*>(this);
559                 if (m) {
560                         control = new MonitorControl (_a_session, X_("monitor"), *m);
561                 }
562         } else if (param.type() == SoloAutomation) {
563                 Soloable* s = dynamic_cast<Soloable*>(this);
564                 Muteable* m = dynamic_cast<Muteable*>(this);
565                 if (s && m) {
566                         control = new SoloControl (_a_session, X_("solo"), *s, *m);
567                 }
568         } else if (param.type() == MuteAutomation) {
569                 Muteable* m = dynamic_cast<Muteable*>(this);
570                 if (m) {
571                         control = new MuteControl (_a_session, X_("mute"), *m);
572                 }
573         }
574
575         if (make_list && !list) {
576                 list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
577         }
578
579         if (!control) {
580                 control = new AutomationControl(_a_session, param, desc, list);
581         }
582
583         return boost::shared_ptr<Evoral::Control>(control);
584 }
585
586 boost::shared_ptr<AutomationControl>
587 Automatable::automation_control (PBD::ID const & id) const
588 {
589         Controls::const_iterator li;
590
591         for (li = _controls.begin(); li != _controls.end(); ++li) {
592                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (li->second);
593                 if (ac && (ac->id() == id)) {
594                         return ac;
595                 }
596         }
597
598         return boost::shared_ptr<AutomationControl>();
599 }
600
601 boost::shared_ptr<AutomationControl>
602 Automatable::automation_control (const Evoral::Parameter& id, bool create)
603 {
604         return boost::dynamic_pointer_cast<AutomationControl>(Evoral::ControlSet::control(id, create));
605 }
606
607 boost::shared_ptr<const AutomationControl>
608 Automatable::automation_control (const Evoral::Parameter& id) const
609 {
610         return boost::dynamic_pointer_cast<const AutomationControl>(Evoral::ControlSet::control(id));
611 }
612
613 void
614 Automatable::clear_controls ()
615 {
616         _control_connections.drop_connections ();
617         ControlSet::clear_controls ();
618 }
619
620 bool
621 Automatable::find_next_event (double start, double end, Evoral::ControlEvent& next_event, bool only_active) const
622 {
623         next_event.when = std::numeric_limits<double>::max();
624
625         if (only_active) {
626                 boost::shared_ptr<ControlList> cl = _automated_controls.reader ();
627                 for (ControlList::const_iterator ci = cl->begin(); ci != cl->end(); ++ci) {
628                         if ((*ci)->automation_playback()) {
629                                 find_next_ac_event (*ci, start, end, next_event);
630                         }
631                 }
632         } else {
633                 for (Controls::const_iterator li = _controls.begin(); li != _controls.end(); ++li) {
634                         boost::shared_ptr<AutomationControl> c
635                                 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
636                         if (c) {
637                                 find_next_ac_event (c, start, end, next_event);
638                         }
639                 }
640         }
641         return next_event.when != std::numeric_limits<double>::max();
642 }
643
644 void
645 Automatable::find_next_ac_event (boost::shared_ptr<AutomationControl> c, double start, double end, Evoral::ControlEvent& next_event) const
646 {
647         boost::shared_ptr<SlavableAutomationControl> sc
648                 = boost::dynamic_pointer_cast<SlavableAutomationControl>(c);
649
650         if (sc) {
651                 sc->find_next_event (start, end, next_event);
652         }
653
654         Evoral::ControlList::const_iterator i;
655         boost::shared_ptr<const Evoral::ControlList> alist (c->list());
656         Evoral::ControlEvent cp (start, 0.0f);
657         if (!alist) {
658                 return;
659         }
660
661         for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator); i != alist->end() && (*i)->when < end; ++i) {
662                 if ((*i)->when > start) {
663                         break;
664                 }
665         }
666
667         if (i != alist->end() && (*i)->when < end) {
668                 if ((*i)->when < next_event.when) {
669                         next_event.when = (*i)->when;
670                 }
671         }
672 }