Revert "rename ParameterChanged signal in Plugin to ParameterChangedExternally to...
[ardour.git] / libs / ardour / plugin_insert.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <string>
25
26 #include "pbd/failed_constructor.h"
27 #include "pbd/xml++.h"
28 #include "pbd/convert.h"
29
30 #include "ardour/audio_buffer.h"
31 #include "ardour/automation_list.h"
32 #include "ardour/buffer_set.h"
33 #include "ardour/debug.h"
34 #include "ardour/event_type_map.h"
35 #include "ardour/ladspa_plugin.h"
36 #include "ardour/plugin.h"
37 #include "ardour/plugin_insert.h"
38
39 #ifdef LV2_SUPPORT
40 #include "ardour/lv2_plugin.h"
41 #endif
42
43 #ifdef WINDOWS_VST_SUPPORT
44 #include "ardour/windows_vst_plugin.h"
45 #endif
46
47 #ifdef LXVST_SUPPORT
48 #include "ardour/lxvst_plugin.h"
49 #endif
50
51 #ifdef AUDIOUNIT_SUPPORT
52 #include "ardour/audio_unit.h"
53 #endif
54
55 #include "ardour/session.h"
56 #include "ardour/types.h"
57
58 #include "i18n.h"
59
60 using namespace std;
61 using namespace ARDOUR;
62 using namespace PBD;
63
64 const string PluginInsert::port_automation_node_name = "PortAutomation";
65
66 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
67         : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
68         , _signal_analysis_collected_nframes(0)
69         , _signal_analysis_collect_nframes_max(0)
70 {
71         /* the first is the master */
72
73         if (plug) {
74                 add_plugin (plug);
75                 create_automatable_parameters ();
76         }
77 }
78
79 bool
80 PluginInsert::set_count (uint32_t num)
81 {
82         bool require_state = !_plugins.empty();
83
84         /* this is a bad idea.... we shouldn't do this while active.
85            only a route holding their redirect_lock should be calling this
86         */
87
88         if (num == 0) {
89                 return false;
90         } else if (num > _plugins.size()) {
91                 uint32_t diff = num - _plugins.size();
92
93                 for (uint32_t n = 0; n < diff; ++n) {
94                         boost::shared_ptr<Plugin> p = plugin_factory (_plugins[0]);
95                         add_plugin (p);
96                         if (active ()) {
97                                 p->activate ();
98                         }
99
100                         if (require_state) {
101                                 /* XXX do something */
102                         }
103                 }
104
105         } else if (num < _plugins.size()) {
106                 uint32_t diff = _plugins.size() - num;
107                 for (uint32_t n= 0; n < diff; ++n) {
108                         _plugins.pop_back();
109                 }
110         }
111
112         return true;
113 }
114
115 PluginInsert::~PluginInsert ()
116 {
117 }
118
119 void
120 PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
121 {
122         if (which.type() != PluginAutomation)
123                 return;
124
125         boost::shared_ptr<AutomationControl> c
126                         = boost::dynamic_pointer_cast<AutomationControl>(control (which));
127
128         if (c && s != Off) {
129                 _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
130         }
131 }
132
133 ChanCount
134 PluginInsert::output_streams() const
135 {
136         assert (!_plugins.empty());
137
138         PluginInfoPtr info = _plugins.front()->get_info();
139
140         if (info->reconfigurable_io()) {
141                 ChanCount out = _plugins.front()->output_streams ();
142                 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
143                 return out;
144         } else {
145                 ChanCount out = info->n_outputs;
146                 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
147                 out.set_audio (out.n_audio() * _plugins.size());
148                 out.set_midi (out.n_midi() * _plugins.size() + midi_bypass.n_midi());
149                 return out;
150         }
151 }
152
153 ChanCount
154 PluginInsert::input_streams() const
155 {
156         assert (!_plugins.empty());
157
158         ChanCount in;
159
160         PluginInfoPtr info = _plugins.front()->get_info();
161
162         if (info->reconfigurable_io()) {
163                 assert (_plugins.size() == 1);
164                 in = _plugins.front()->input_streams();
165         } else {
166                 in = info->n_inputs;
167         }
168
169         DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, input streams = %1, match using %2\n", in, _match.method));
170
171         if (_match.method == Split) {
172
173                 /* we are splitting 1 processor input to multiple plugin inputs,
174                    so we have a maximum of 1 stream of each type.
175                 */
176                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
177                         if (in.get (*t) > 1) {
178                                 in.set (*t, 1);
179                         }
180                 }
181                 return in;
182
183         } else if (_match.method == Hide) {
184
185                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
186                         in.set (*t, in.get (*t) - _match.hide.get (*t));
187                 }
188                 return in;
189
190         } else {
191
192                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
193                         in.set (*t, in.get (*t) * _plugins.size ());
194                 }
195
196                 return in;
197         }
198 }
199
200 ChanCount
201 PluginInsert::natural_output_streams() const
202 {
203         return _plugins[0]->get_info()->n_outputs;
204 }
205
206 ChanCount
207 PluginInsert::natural_input_streams() const
208 {
209         return _plugins[0]->get_info()->n_inputs;
210 }
211
212 bool
213 PluginInsert::has_no_inputs() const
214 {
215         return _plugins[0]->get_info()->n_inputs == ChanCount::ZERO;
216 }
217
218 bool
219 PluginInsert::has_no_audio_inputs() const
220 {
221         return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
222 }
223
224 bool
225 PluginInsert::is_midi_instrument() const
226 {
227         /* XXX more finesse is possible here. VST plugins have a
228            a specific "instrument" flag, for example.
229          */
230         PluginInfoPtr pi = _plugins[0]->get_info();
231
232         return pi->n_inputs.n_midi() != 0 &&
233                 pi->n_outputs.n_audio() > 0;
234 }
235
236 void
237 PluginInsert::create_automatable_parameters ()
238 {
239         assert (!_plugins.empty());
240
241         set<Evoral::Parameter> a = _plugins.front()->automatable ();
242
243         for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
244                 if (i->type() == PluginAutomation) {
245
246                         Evoral::Parameter param(*i);
247
248                         ParameterDescriptor desc;
249                         _plugins.front()->get_parameter_descriptor(i->id(), desc);
250
251                         can_automate (param);
252                         boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
253                         add_control (boost::shared_ptr<AutomationControl> (new PluginControl(this, param, desc, list)));
254                 } else if (i->type() == PluginPropertyAutomation) {
255                         Evoral::Parameter param(*i);
256                         const ParameterDescriptor& desc = _plugins.front()->get_property_descriptor(param.id());
257                         if (desc.datatype != Variant::NOTHING) {
258                                 boost::shared_ptr<AutomationList> list;
259                                 if (Variant::type_is_numeric(desc.datatype)) {
260                                         list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
261                                 }
262                                 add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
263                         }
264                 }
265         }
266 }
267
268 void
269 PluginInsert::parameter_changed (uint32_t which, float val)
270 {
271         boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, which));
272
273         if (ac) {
274                 ac->set_value (val);
275
276                 Plugins::iterator i = _plugins.begin();
277
278                 /* don't set the first plugin, just all the slaves */
279
280                 if (i != _plugins.end()) {
281                         ++i;
282                         for (; i != _plugins.end(); ++i) {
283                                 (*i)->set_parameter (which, val);
284                         }
285                 }
286         }
287 }
288
289 int
290 PluginInsert::set_block_size (pframes_t nframes)
291 {
292         int ret = 0;
293         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
294                 if ((*i)->set_block_size (nframes) != 0) {
295                         ret = -1;
296                 }
297         }
298         return ret;
299 }
300
301 void
302 PluginInsert::activate ()
303 {
304         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
305                 (*i)->activate ();
306         }
307
308         Processor::activate ();
309 }
310
311 void
312 PluginInsert::deactivate ()
313 {
314         Processor::deactivate ();
315
316         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
317                 (*i)->deactivate ();
318         }
319 }
320
321 void
322 PluginInsert::flush ()
323 {
324         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
325                 (*i)->flush ();
326         }
327 }
328
329 void
330 PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now)
331 {
332         // Calculate if, and how many frames we need to collect for analysis
333         framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
334                                              _signal_analysis_collected_nframes);
335         if (nframes < collect_signal_nframes) { // we might not get all frames now
336                 collect_signal_nframes = nframes;
337         }
338
339         ChanCount const in_streams = input_streams ();
340         ChanCount const out_streams = output_streams ();
341
342         ChanMapping in_map (in_streams);
343         ChanMapping out_map (out_streams);
344         bool valid;
345         if (_match.method == Split) {
346                 /* fix the input mapping so that we have maps for each of the plugin's inputs */
347                 in_map = ChanMapping (natural_input_streams ());
348
349                 /* copy the first stream's buffer contents to the others */
350                 /* XXX: audio only */
351                 uint32_t first_idx = in_map.get (DataType::AUDIO, 0, &valid);
352                 if (valid) {
353                         for (uint32_t i = in_streams.n_audio(); i < natural_input_streams().n_audio(); ++i) {
354                                 bufs.get_audio(in_map.get (DataType::AUDIO, i, &valid)).read_from(bufs.get_audio(first_idx), nframes, offset, offset);
355                         }
356                 }
357         }
358
359         bufs.set_count(ChanCount::max(bufs.count(), in_streams));
360         bufs.set_count(ChanCount::max(bufs.count(), out_streams));
361
362         /* Note that we've already required that plugins
363            be able to handle in-place processing.
364         */
365
366         if (with_auto) {
367
368                 uint32_t n = 0;
369
370                 for (Controls::iterator li = controls().begin(); li != controls().end(); ++li, ++n) {
371
372                         boost::shared_ptr<AutomationControl> c
373                                 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
374
375                         if (c->list() && c->automation_playback()) {
376                                 bool valid;
377
378                                 const float val = c->list()->rt_safe_eval (now, valid);
379
380                                 if (valid) {
381                                         c->set_value(val);
382                                 }
383
384                         }
385                 }
386         }
387
388         if (collect_signal_nframes > 0) {
389                 // collect input
390                 //std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count,  " << bufs.available().n_audio() << " available" << std::endl;
391                 //std::cerr << "               streams " << input_streams().n_audio() << std::endl;
392                 //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
393
394                 _signal_analysis_inputs.set_count(input_streams());
395
396                 for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
397                         _signal_analysis_inputs.get_audio(i).read_from(
398                                 bufs.get_audio(i),
399                                 collect_signal_nframes,
400                                 _signal_analysis_collected_nframes); // offset is for target buffer
401                 }
402
403         }
404
405         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
406                 (*i)->connect_and_run(bufs, in_map, out_map, nframes, offset);
407                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
408                         in_map.offset_to(*t, natural_input_streams().get(*t));
409                         out_map.offset_to(*t, natural_output_streams().get(*t));
410                 }
411         }
412
413         if (collect_signal_nframes > 0) {
414                 // collect output
415                 //std::cerr << "       output, bufs " << bufs.count().n_audio() << " count,  " << bufs.available().n_audio() << " available" << std::endl;
416                 //std::cerr << "               streams " << output_streams().n_audio() << std::endl;
417
418                 _signal_analysis_outputs.set_count(output_streams());
419
420                 for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
421                         _signal_analysis_outputs.get_audio(i).read_from(
422                                 bufs.get_audio(i),
423                                 collect_signal_nframes,
424                                 _signal_analysis_collected_nframes); // offset is for target buffer
425                 }
426
427                 _signal_analysis_collected_nframes += collect_signal_nframes;
428                 assert(_signal_analysis_collected_nframes <= _signal_analysis_collect_nframes_max);
429
430                 if (_signal_analysis_collected_nframes == _signal_analysis_collect_nframes_max) {
431                         _signal_analysis_collect_nframes_max = 0;
432                         _signal_analysis_collected_nframes   = 0;
433
434                         AnalysisDataGathered(&_signal_analysis_inputs,
435                                              &_signal_analysis_outputs);
436                 }
437         }
438         /* leave remaining channel buffers alone */
439 }
440
441 void
442 PluginInsert::silence (framecnt_t nframes)
443 {
444         if (!active ()) {
445                 return;
446         }
447
448         ChanMapping in_map(input_streams());
449         ChanMapping out_map(output_streams());
450
451         if (_match.method == Split) {
452                 /* fix the input mapping so that we have maps for each of the plugin's inputs */
453                 in_map = ChanMapping (natural_input_streams ());
454         }
455
456         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
457                 (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0);
458         }
459 }
460
461 void
462 PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t /*end_frame*/, pframes_t nframes, bool)
463 {
464         if (_pending_active) {
465                 /* run as normal if we are active or moving from inactive to active */
466
467                 if (_session.transport_rolling() || _session.bounce_processing()) {
468                         automation_run (bufs, start_frame, nframes);
469                 } else {
470                         connect_and_run (bufs, nframes, 0, false);
471                 }
472
473         } else {
474                 uint32_t in = input_streams ().n_audio ();
475                 uint32_t out = output_streams().n_audio ();
476
477                 if (has_no_audio_inputs() || in == 0) {
478
479                         /* silence all (audio) outputs. Should really declick
480                          * at the transitions of "active"
481                          */
482
483                         for (uint32_t n = 0; n < out; ++n) {
484                                 bufs.get_audio (n).silence (nframes);
485                         }
486
487                 } else if (out > in) {
488
489                         /* not active, but something has make up for any channel count increase */
490
491                         // TODO: option round-robin (n % in) or silence additional buffers ??
492                         // for now , simply replicate last buffer
493                         for (uint32_t n = in; n < out; ++n) {
494                                 bufs.get_audio(n).read_from(bufs.get_audio(in - 1), nframes);
495                         }
496                 }
497
498                 bufs.count().set_audio (out);
499         }
500
501         _active = _pending_active;
502
503         /* we have no idea whether the plugin generated silence or not, so mark
504          * all buffers appropriately.
505          */
506
507 }
508
509 void
510 PluginInsert::set_parameter (Evoral::Parameter param, float val)
511 {
512         if (param.type() != PluginAutomation) {
513                 return;
514         }
515
516         /* the others will be set from the event triggered by this */
517
518         _plugins[0]->set_parameter (param.id(), val);
519
520         boost::shared_ptr<AutomationControl> ac
521                         = boost::dynamic_pointer_cast<AutomationControl>(control(param));
522
523         if (ac) {
524                 ac->set_value(val);
525         } else {
526                 warning << "set_parameter called for nonexistent parameter "
527                         << EventTypeMap::instance().to_symbol(param) << endmsg;
528         }
529
530         _session.set_dirty();
531 }
532
533 float
534 PluginInsert::get_parameter (Evoral::Parameter param)
535 {
536         if (param.type() != PluginAutomation) {
537                 return 0.0;
538         } else {
539                 assert (!_plugins.empty ());
540                 return _plugins[0]->get_parameter (param.id());
541         }
542 }
543
544 void
545 PluginInsert::automation_run (BufferSet& bufs, framepos_t start, pframes_t nframes)
546 {
547         Evoral::ControlEvent next_event (0, 0.0f);
548         framepos_t now = start;
549         framepos_t end = now + nframes;
550         framecnt_t offset = 0;
551
552         Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
553
554         if (!lm.locked()) {
555                 connect_and_run (bufs, nframes, offset, false);
556                 return;
557         }
558
559         if (!find_next_event (now, end, next_event) || requires_fixed_sized_buffers()) {
560
561                 /* no events have a time within the relevant range */
562
563                 connect_and_run (bufs, nframes, offset, true, now);
564                 return;
565         }
566
567         while (nframes) {
568
569                 framecnt_t cnt = min (((framecnt_t) ceil (next_event.when) - now), (framecnt_t) nframes);
570
571                 connect_and_run (bufs, cnt, offset, true, now);
572
573                 nframes -= cnt;
574                 offset += cnt;
575                 now += cnt;
576
577                 if (!find_next_event (now, end, next_event)) {
578                         break;
579                 }
580         }
581
582         /* cleanup anything that is left to do */
583
584         if (nframes) {
585                 connect_and_run (bufs, nframes, offset, true, now);
586         }
587 }
588
589 float
590 PluginInsert::default_parameter_value (const Evoral::Parameter& param)
591 {
592         if (param.type() != PluginAutomation)
593                 return 1.0;
594
595         if (_plugins.empty()) {
596                 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
597                       << endmsg;
598                 abort(); /*NOTREACHED*/
599         }
600
601         return _plugins[0]->default_value (param.id());
602 }
603
604
605 bool
606 PluginInsert::can_reset_all_parameters ()
607 {
608         bool all = true;
609         uint32_t params = 0;
610         for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
611                 bool ok=false;
612                 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
613
614                 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
615                         continue;
616                 }
617
618                 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
619                 if (!ac) {
620                         continue;
621                 }
622
623                 ++params;
624                 if (ac->automation_state() & Play) {
625                         all = false;
626                         break;
627                 }
628         }
629         return all && (params > 0);
630 }
631
632 bool
633 PluginInsert::reset_parameters_to_default ()
634 {
635         bool all = true;
636
637         for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
638                 bool ok=false;
639                 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
640
641                 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
642                         continue;
643                 }
644
645                 const float dflt = _plugins[0]->default_value (cid);
646                 const float curr = _plugins[0]->get_parameter (cid);
647
648                 if (dflt == curr) {
649                         continue;
650                 }
651
652                 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
653                 if (!ac) {
654                         continue;
655                 }
656
657                 if (ac->automation_state() & Play) {
658                         all = false;
659                         continue;
660                 }
661
662                 ac->set_value (dflt);
663         }
664         return all;
665 }
666
667 boost::shared_ptr<Plugin>
668 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
669 {
670         boost::shared_ptr<LadspaPlugin> lp;
671 #ifdef LV2_SUPPORT
672         boost::shared_ptr<LV2Plugin> lv2p;
673 #endif
674 #ifdef WINDOWS_VST_SUPPORT
675         boost::shared_ptr<WindowsVSTPlugin> vp;
676 #endif
677 #ifdef LXVST_SUPPORT
678         boost::shared_ptr<LXVSTPlugin> lxvp;
679 #endif
680 #ifdef AUDIOUNIT_SUPPORT
681         boost::shared_ptr<AUPlugin> ap;
682 #endif
683
684         if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
685                 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
686 #ifdef LV2_SUPPORT
687         } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
688                 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
689 #endif
690 #ifdef WINDOWS_VST_SUPPORT
691         } else if ((vp = boost::dynamic_pointer_cast<WindowsVSTPlugin> (other)) != 0) {
692                 return boost::shared_ptr<Plugin> (new WindowsVSTPlugin (*vp));
693 #endif
694 #ifdef LXVST_SUPPORT
695         } else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
696                 return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
697 #endif
698 #ifdef AUDIOUNIT_SUPPORT
699         } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
700                 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
701 #endif
702         }
703
704         fatal << string_compose (_("programming error: %1"),
705                           X_("unknown plugin type in PluginInsert::plugin_factory"))
706               << endmsg;
707         abort(); /*NOTREACHED*/
708         return boost::shared_ptr<Plugin> ((Plugin*) 0);
709 }
710
711 bool
712 PluginInsert::configure_io (ChanCount in, ChanCount out)
713 {
714         Match old_match = _match;
715         ChanCount old_in = input_streams ();
716         ChanCount old_out = output_streams ();
717
718         _configured_in = in;
719         _configured_out = out;
720
721         /* set the matching method and number of plugins that we will use to meet this configuration */
722         _match = private_can_support_io_configuration (in, out);
723         if (set_count (_match.plugins) == false) {
724                 PluginIoReConfigure (); /* EMIT SIGNAL */
725                 return false;
726         }
727
728         /* configure plugins */
729         switch (_match.method) {
730         case Split:
731         case Hide:
732                 if (_plugins.front()->configure_io (_plugins.front()->get_info()->n_inputs, out) == false) {
733                         PluginIoReConfigure (); /* EMIT SIGNAL */
734                         return false;
735                 }
736                 break;
737
738         default:
739                 if (_plugins.front()->configure_io (in, out) == false) {
740                         PluginIoReConfigure (); /* EMIT SIGNAL */
741                         return false;
742                 }
743                 break;
744         }
745
746         if (  (old_match.method != _match.method && (old_match.method == Split || _match.method == Split))
747                         || old_in != in
748                         || old_out != out
749                         )
750         {
751                 PluginIoReConfigure (); /* EMIT SIGNAL */
752         }
753
754         // we don't know the analysis window size, so we must work with the
755         // current buffer size here. each request for data fills in these
756         // buffers and the analyser makes sure it gets enough data for the
757         // analysis window
758         session().ensure_buffer_set (_signal_analysis_inputs, in);
759         //_signal_analysis_inputs.set_count (in);
760
761         session().ensure_buffer_set (_signal_analysis_outputs, out);
762         //_signal_analysis_outputs.set_count (out);
763
764         // std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
765
766         return Processor::configure_io (in, out);
767 }
768
769 /** Decide whether this PluginInsert can support a given IO configuration.
770  *  To do this, we run through a set of possible solutions in rough order of
771  *  preference.
772  *
773  *  @param in Required input channel count.
774  *  @param out Filled in with the output channel count if we return true.
775  *  @return true if the given IO configuration can be supported.
776  */
777 bool
778 PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
779 {
780         return private_can_support_io_configuration (in, out).method != Impossible;
781 }
782
783 /** A private version of can_support_io_configuration which returns the method
784  *  by which the configuration can be matched, rather than just whether or not
785  *  it can be.
786  */
787 PluginInsert::Match
788 PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out)
789 {
790         if (_plugins.empty()) {
791                 return Match();
792         }
793
794         PluginInfoPtr info = _plugins.front()->get_info();
795         ChanCount in; in += inx;
796         midi_bypass.reset();
797
798         if (info->reconfigurable_io()) {
799                 /* Plugin has flexible I/O, so delegate to it */
800                 bool const r = _plugins.front()->can_support_io_configuration (in, out);
801                 if (!r) {
802                         return Match (Impossible, 0);
803                 }
804
805                 return Match (Delegate, 1);
806         }
807
808         ChanCount inputs  = info->n_inputs;
809         ChanCount outputs = info->n_outputs;
810
811         if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
812                 DEBUG_TRACE ( DEBUG::Processors, string_compose ("bypassing midi-data around %1\n", name()));
813                 midi_bypass.set(DataType::MIDI, 1);
814         }
815         if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
816                 DEBUG_TRACE ( DEBUG::Processors, string_compose ("hiding midi-port from plugin %1\n", name()));
817                 in.set(DataType::MIDI, 0);
818         }
819
820         bool no_inputs = true;
821         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
822                 if (inputs.get (*t) != 0) {
823                         no_inputs = false;
824                         break;
825                 }
826         }
827
828         if (no_inputs) {
829                 /* no inputs so we can take any input configuration since we throw it away */
830                 out = outputs + midi_bypass;
831                 return Match (NoInputs, 1);
832         }
833
834         /* Plugin inputs match requested inputs exactly */
835         if (inputs == in) {
836                 out = outputs + midi_bypass;
837                 return Match (ExactMatch, 1);
838         }
839
840         /* We may be able to run more than one copy of the plugin within this insert
841            to cope with the insert having more inputs than the plugin.
842            We allow replication only for plugins with either zero or 1 inputs and outputs
843            for every valid data type.
844         */
845
846         uint32_t f             = 0;
847         bool     can_replicate = true;
848         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
849
850                 uint32_t nin = inputs.get (*t);
851
852                 // No inputs of this type
853                 if (nin == 0 && in.get(*t) == 0) {
854                         continue;
855                 }
856
857                 if (nin != 1 || outputs.get (*t) != 1) {
858                         can_replicate = false;
859                         break;
860                 }
861
862                 // Potential factor not set yet
863                 if (f == 0) {
864                         f = in.get(*t) / nin;
865                 }
866
867                 // Factor for this type does not match another type, can not replicate
868                 if (f != (in.get(*t) / nin)) {
869                         can_replicate = false;
870                         break;
871                 }
872         }
873
874         if (can_replicate) {
875                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
876                         out.set (*t, outputs.get(*t) * f);
877                 }
878                 out += midi_bypass;
879                 return Match (Replicate, f);
880         }
881
882         /* If the processor has exactly one input of a given type, and
883            the plugin has more, we can feed the single processor input
884            to some or all of the plugin inputs.  This is rather
885            special-case-y, but the 1-to-many case is by far the
886            simplest.  How do I split thy 2 processor inputs to 3
887            plugin inputs?  Let me count the ways ...
888         */
889
890         bool can_split = true;
891         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
892
893                 bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1);
894                 bool const nothing_to_do_for_type = (in.get (*t) == 0 && inputs.get (*t) == 0);
895
896                 if (!can_split_type && !nothing_to_do_for_type) {
897                         can_split = false;
898                 }
899         }
900
901         if (can_split) {
902                 out = outputs + midi_bypass;
903                 return Match (Split, 1);
904         }
905
906         /* If the plugin has more inputs than we want, we can `hide' some of them
907            by feeding them silence.
908         */
909
910         bool could_hide = false;
911         bool cannot_hide = false;
912         ChanCount hide_channels;
913
914         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
915                 if (inputs.get(*t) > in.get(*t)) {
916                         /* there is potential to hide, since the plugin has more inputs of type t than the insert */
917                         hide_channels.set (*t, inputs.get(*t) - in.get(*t));
918                         could_hide = true;
919                 } else if (inputs.get(*t) < in.get(*t)) {
920                         /* we definitely cannot hide, since the plugin has fewer inputs of type t than the insert */
921                         cannot_hide = true;
922                 }
923         }
924
925         if (could_hide && !cannot_hide) {
926                 out = outputs + midi_bypass;
927                 return Match (Hide, 1, hide_channels);
928         }
929
930         midi_bypass.reset();
931         return Match (Impossible, 0);
932 }
933
934 XMLNode&
935 PluginInsert::get_state ()
936 {
937         return state (true);
938 }
939
940 XMLNode&
941 PluginInsert::state (bool full)
942 {
943         XMLNode& node = Processor::state (full);
944
945         node.add_property("type", _plugins[0]->state_node_name());
946         node.add_property("unique-id", _plugins[0]->unique_id());
947         node.add_property("count", string_compose("%1", _plugins.size()));
948
949         /* remember actual i/o configuration (for later placeholder
950          * in case the plugin goes missing) */
951         node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
952         node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
953
954         node.add_child_nocopy (_plugins[0]->get_state());
955
956         for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
957                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> ((*c).second);
958                 if (ac) {
959                         node.add_child_nocopy (ac->get_state());
960                 }
961         }
962
963         return node;
964 }
965
966 void
967 PluginInsert::set_control_ids (const XMLNode& node, int version)
968 {
969         const XMLNodeList& nlist = node.children();
970         XMLNodeConstIterator iter;
971         set<Evoral::Parameter>::const_iterator p;
972
973         for (iter = nlist.begin(); iter != nlist.end(); ++iter) {
974                 if ((*iter)->name() == Controllable::xml_node_name) {
975                         const XMLProperty* prop;
976
977                         if ((prop = (*iter)->property (X_("parameter"))) != 0) {
978                                 uint32_t p = atoi (prop->value());
979
980                                 /* this may create the new controllable */
981
982                                 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
983
984 #ifndef NO_PLUGIN_STATE
985                                 if (!c) {
986                                         continue;
987                                 }
988                                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
989                                 if (ac) {
990                                         ac->set_state (**iter, version);
991                                 }
992 #endif
993                         }
994                 }
995         }
996 }
997
998 int
999 PluginInsert::set_state(const XMLNode& node, int version)
1000 {
1001         XMLNodeList nlist = node.children();
1002         XMLNodeIterator niter;
1003         XMLPropertyList plist;
1004         const XMLProperty *prop;
1005         ARDOUR::PluginType type;
1006
1007         if ((prop = node.property ("type")) == 0) {
1008                 error << _("XML node describing plugin is missing the `type' field") << endmsg;
1009                 return -1;
1010         }
1011
1012         if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
1013                 type = ARDOUR::LADSPA;
1014         } else if (prop->value() == X_("lv2")) {
1015                 type = ARDOUR::LV2;
1016         } else if (prop->value() == X_("windows-vst")) {
1017                 type = ARDOUR::Windows_VST;
1018         } else if (prop->value() == X_("lxvst")) {
1019                 type = ARDOUR::LXVST;
1020         } else if (prop->value() == X_("audiounit")) {
1021                 type = ARDOUR::AudioUnit;
1022         } else {
1023                 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
1024                                   prop->value())
1025                       << endmsg;
1026                 return -1;
1027         }
1028
1029         prop = node.property ("unique-id");
1030
1031         if (prop == 0) {
1032 #ifdef WINDOWS_VST_SUPPORT
1033                 /* older sessions contain VST plugins with only an "id" field.
1034                  */
1035
1036                 if (type == ARDOUR::Windows_VST) {
1037                         prop = node.property ("id");
1038                 }
1039 #endif
1040
1041 #ifdef LXVST_SUPPORT
1042                 /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
1043
1044                 if (type == ARDOUR::LXVST) {
1045                         prop = node.property ("id");
1046                 }
1047 #endif
1048                 /* recheck  */
1049
1050                 if (prop == 0) {
1051                         error << _("Plugin has no unique ID field") << endmsg;
1052                         return -1;
1053                 }
1054         }
1055
1056         boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
1057
1058         /* treat linux and windows VST plugins equivalent if they have the same uniqueID
1059          * allow to move sessions windows <> linux */
1060 #ifdef LXVST_SUPPORT
1061         if (plugin == 0 && type == ARDOUR::Windows_VST) {
1062                 type = ARDOUR::LXVST;
1063                 plugin = find_plugin (_session, prop->value(), type);
1064         }
1065 #endif
1066
1067 #ifdef WINDOWS_VST_SUPPORT
1068         if (plugin == 0 && type == ARDOUR::LXVST) {
1069                 type = ARDOUR::Windows_VST;
1070                 plugin = find_plugin (_session, prop->value(), type);
1071         }
1072 #endif
1073
1074         if (plugin == 0) {
1075                 error << string_compose(
1076                         _("Found a reference to a plugin (\"%1\") that is unknown.\n"
1077                           "Perhaps it was removed or moved since it was last used."),
1078                         prop->value())
1079                       << endmsg;
1080                 return -1;
1081         }
1082
1083         // The name of the PluginInsert comes from the plugin, nothing else
1084         _name = plugin->get_info()->name;
1085
1086         uint32_t count = 1;
1087
1088         // Processor::set_state() will set this, but too late
1089         // for it to be available when setting up plugin
1090         // state. We can't call Processor::set_state() until
1091         // the plugins themselves are created and added.
1092
1093         set_id (node);
1094
1095         if (_plugins.empty()) {
1096                 /* if we are adding the first plugin, we will need to set
1097                    up automatable controls.
1098                 */
1099                 add_plugin (plugin);
1100                 create_automatable_parameters ();
1101                 set_control_ids (node, version);
1102         }
1103
1104         if ((prop = node.property ("count")) != 0) {
1105                 sscanf (prop->value().c_str(), "%u", &count);
1106         }
1107
1108         if (_plugins.size() != count) {
1109                 for (uint32_t n = 1; n < count; ++n) {
1110                         add_plugin (plugin_factory (plugin));
1111                 }
1112         }
1113
1114         Processor::set_state (node, version);
1115
1116         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1117
1118                 /* find the node with the type-specific node name ("lv2", "ladspa", etc)
1119                    and set all plugins to the same state.
1120                 */
1121
1122                 if ((*niter)->name() == plugin->state_node_name()) {
1123
1124                         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1125                                 (*i)->set_state (**niter, version);
1126                         }
1127
1128                         break;
1129                 }
1130         }
1131
1132         if (version < 3000) {
1133
1134                 /* Only 2.X sessions need a call to set_parameter_state() - in 3.X and above
1135                    this is all handled by Automatable
1136                 */
1137
1138                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1139                         if ((*niter)->name() == "Redirect") {
1140                                 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
1141                                 Processor::set_state (**niter, version);
1142                                 break;
1143                         }
1144                 }
1145
1146                 set_parameter_state_2X (node, version);
1147         }
1148
1149         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1150                 if (active()) {
1151                         (*i)->activate ();
1152                 } else {
1153                         (*i)->deactivate ();
1154                 }
1155         }
1156
1157         return 0;
1158 }
1159
1160 void
1161 PluginInsert::update_id (PBD::ID id)
1162 {
1163         set_id (id.to_s());
1164         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1165                 (*i)->set_insert_id (id);
1166         }
1167 }
1168
1169 void
1170 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
1171 {
1172         XMLNodeList nlist = node.children();
1173         XMLNodeIterator niter;
1174
1175         /* look for port automation node */
1176
1177         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1178
1179                 if ((*niter)->name() != port_automation_node_name) {
1180                         continue;
1181                 }
1182
1183                 XMLNodeList cnodes;
1184                 XMLProperty *cprop;
1185                 XMLNodeConstIterator iter;
1186                 XMLNode *child;
1187                 const char *port;
1188                 uint32_t port_id;
1189
1190                 cnodes = (*niter)->children ("port");
1191
1192                 for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
1193
1194                         child = *iter;
1195
1196                         if ((cprop = child->property("number")) != 0) {
1197                                 port = cprop->value().c_str();
1198                         } else {
1199                                 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
1200                                 continue;
1201                         }
1202
1203                         sscanf (port, "%" PRIu32, &port_id);
1204
1205                         if (port_id >= _plugins[0]->parameter_count()) {
1206                                 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
1207                                 continue;
1208                         }
1209
1210                         boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
1211                                         control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
1212
1213                         if (c && c->alist()) {
1214                                 if (!child->children().empty()) {
1215                                         c->alist()->set_state (*child->children().front(), version);
1216
1217                                         /* In some cases 2.X saves lists with min_yval and max_yval
1218                                            being FLT_MIN and FLT_MAX respectively.  This causes problems
1219                                            in A3 because these min/max values are used to compute
1220                                            where GUI control points should be drawn.  If we see such
1221                                            values, `correct' them to the min/max of the appropriate
1222                                            parameter.
1223                                         */
1224
1225                                         float min_y = c->alist()->get_min_y ();
1226                                         float max_y = c->alist()->get_max_y ();
1227
1228                                         ParameterDescriptor desc;
1229                                         _plugins.front()->get_parameter_descriptor (port_id, desc);
1230
1231                                         if (min_y == FLT_MIN) {
1232                                                 min_y = desc.lower;
1233                                         }
1234
1235                                         if (max_y == FLT_MAX) {
1236                                                 max_y = desc.upper;
1237                                         }
1238
1239                                         c->alist()->set_yrange (min_y, max_y);
1240                                 }
1241                         } else {
1242                                 error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
1243                         }
1244                 }
1245
1246                 /* done */
1247
1248                 break;
1249         }
1250 }
1251
1252
1253 string
1254 PluginInsert::describe_parameter (Evoral::Parameter param)
1255 {
1256         if (param.type() == PluginAutomation) {
1257                 return _plugins[0]->describe_parameter (param);
1258         } else if (param.type() == PluginPropertyAutomation) {
1259                 boost::shared_ptr<AutomationControl> c(automation_control(param));
1260                 if (c && !c->desc().label.empty()) {
1261                         return c->desc().label;
1262                 }
1263         }
1264         return Automatable::describe_parameter(param);
1265 }
1266
1267 ARDOUR::framecnt_t
1268 PluginInsert::signal_latency() const
1269 {
1270         if (_user_latency) {
1271                 return _user_latency;
1272         }
1273
1274         return _plugins[0]->signal_latency ();
1275 }
1276
1277 ARDOUR::PluginType
1278 PluginInsert::type ()
1279 {
1280        return plugin()->get_info()->type;
1281 }
1282
1283 PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
1284                                             const Evoral::Parameter&          param,
1285                                             const ParameterDescriptor&        desc,
1286                                             boost::shared_ptr<AutomationList> list)
1287         : AutomationControl (p->session(), param, desc, list, p->describe_parameter(param))
1288         , _plugin (p)
1289 {
1290         if (alist()) {
1291                 alist()->reset_default (desc.normal);
1292                 if (desc.toggled) {
1293                         list->set_interpolation(Evoral::ControlList::Discrete);
1294                 }
1295         }
1296
1297         if (desc.toggled) {
1298                 set_flags(Controllable::Toggle);
1299         }
1300 }
1301
1302 /** @param val `user' value */
1303 void
1304 PluginInsert::PluginControl::set_value (double user_val)
1305 {
1306         /* FIXME: probably should be taking out some lock here.. */
1307
1308         for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
1309                 (*i)->set_parameter (_list->parameter().id(), user_val);
1310         }
1311
1312         boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
1313         if (iasp) {
1314                 iasp->set_parameter (_list->parameter().id(), user_val);
1315         }
1316
1317         AutomationControl::set_value (user_val);
1318 }
1319
1320 XMLNode&
1321 PluginInsert::PluginControl::get_state ()
1322 {
1323         stringstream ss;
1324
1325         XMLNode& node (AutomationControl::get_state());
1326         ss << parameter().id();
1327         node.add_property (X_("parameter"), ss.str());
1328
1329         return node;
1330 }
1331
1332 /** @return `user' val */
1333 double
1334 PluginInsert::PluginControl::get_value () const
1335 {
1336         /* FIXME: probably should be taking out some lock here.. */
1337         return _plugin->get_parameter (_list->parameter());
1338 }
1339
1340 PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*                     p,
1341                                                             const Evoral::Parameter&          param,
1342                                                             const ParameterDescriptor&        desc,
1343                                                             boost::shared_ptr<AutomationList> list)
1344         : AutomationControl (p->session(), param, desc, list)
1345         , _plugin (p)
1346 {
1347         if (alist()) {
1348                 alist()->set_yrange (desc.lower, desc.upper);
1349                 alist()->reset_default (desc.normal);
1350         }
1351
1352         if (desc.toggled) {
1353                 set_flags(Controllable::Toggle);
1354         }
1355 }
1356
1357 void
1358 PluginInsert::PluginPropertyControl::set_value (double user_val)
1359 {
1360         /* Old numeric set_value(), coerce to appropriate datatype if possible.
1361            This is lossy, but better than nothing until Ardour's automation system
1362            can handle various datatypes all the way down. */
1363         const Variant value(_desc.datatype, user_val);
1364         if (value.type() == Variant::NOTHING) {
1365                 error << "set_value(double) called for non-numeric property" << endmsg;
1366                 return;
1367         }
1368
1369         for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
1370                 (*i)->set_property(_list->parameter().id(), value);
1371         }
1372
1373         _value = value;
1374         AutomationControl::set_value(user_val);
1375 }
1376
1377 XMLNode&
1378 PluginInsert::PluginPropertyControl::get_state ()
1379 {
1380         stringstream ss;
1381
1382         XMLNode& node (AutomationControl::get_state());
1383         ss << parameter().id();
1384         node.add_property (X_("property"), ss.str());
1385         node.remove_property (X_("value"));
1386
1387         return node;
1388 }
1389
1390 double
1391 PluginInsert::PluginPropertyControl::get_value () const
1392 {
1393         return _value.to_double();
1394 }
1395
1396 boost::shared_ptr<Plugin>
1397 PluginInsert::get_impulse_analysis_plugin()
1398 {
1399         boost::shared_ptr<Plugin> ret;
1400         if (_impulseAnalysisPlugin.expired()) {
1401                 ret = plugin_factory(_plugins[0]);
1402                 ret->configure_io (input_streams (), output_streams ());
1403                 _impulseAnalysisPlugin = ret;
1404         } else {
1405                 ret = _impulseAnalysisPlugin.lock();
1406         }
1407
1408         return ret;
1409 }
1410
1411 void
1412 PluginInsert::collect_signal_for_analysis (framecnt_t nframes)
1413 {
1414         // called from outside the audio thread, so this should be safe
1415         // only do audio as analysis is (currently) only for audio plugins
1416         _signal_analysis_inputs.ensure_buffers(  DataType::AUDIO, input_streams().n_audio(),  nframes);
1417         _signal_analysis_outputs.ensure_buffers( DataType::AUDIO, output_streams().n_audio(), nframes);
1418
1419         _signal_analysis_collected_nframes   = 0;
1420         _signal_analysis_collect_nframes_max = nframes;
1421 }
1422
1423 /** Add a plugin to our list */
1424 void
1425 PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
1426 {
1427         plugin->set_insert_id (this->id());
1428
1429         if (_plugins.empty()) {
1430                 /* first (and probably only) plugin instance - connect to relevant signals
1431                  */
1432
1433                 plugin->ParameterChanged.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed, this, _1, _2));
1434                 plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
1435                 plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
1436         }
1437
1438         _plugins.push_back (plugin);
1439 }
1440
1441 void
1442 PluginInsert::realtime_handle_transport_stopped ()
1443 {
1444         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1445                 (*i)->realtime_handle_transport_stopped ();
1446         }
1447 }
1448
1449 void
1450 PluginInsert::realtime_locate ()
1451 {
1452         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1453                 (*i)->realtime_locate ();
1454         }
1455 }
1456
1457 void
1458 PluginInsert::monitoring_changed ()
1459 {
1460         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1461                 (*i)->monitoring_changed ();
1462         }
1463 }
1464
1465 void
1466 PluginInsert::start_touch (uint32_t param_id)
1467 {
1468         boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
1469         if (ac) {
1470                 ac->start_touch (session().audible_frame());
1471         }
1472 }
1473
1474 void
1475 PluginInsert::end_touch (uint32_t param_id)
1476 {
1477         boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
1478         if (ac) {
1479                 ac->stop_touch (true, session().audible_frame());
1480         }
1481 }