910b2cd6dceacc45aeeb51a0396b11862746b50a
[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 nonexistant 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)) {
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         node.add_child_nocopy (_plugins[0]->get_state());
949
950         for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
951                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> ((*c).second);
952                 if (ac) {
953                         node.add_child_nocopy (ac->get_state());
954                 }
955         }
956
957         return node;
958 }
959
960 void
961 PluginInsert::set_control_ids (const XMLNode& node, int version)
962 {
963         const XMLNodeList& nlist = node.children();
964         XMLNodeConstIterator iter;
965         set<Evoral::Parameter>::const_iterator p;
966
967         for (iter = nlist.begin(); iter != nlist.end(); ++iter) {
968                 if ((*iter)->name() == Controllable::xml_node_name) {
969                         const XMLProperty* prop;
970
971                         if ((prop = (*iter)->property (X_("parameter"))) != 0) {
972                                 uint32_t p = atoi (prop->value());
973
974                                 /* this may create the new controllable */
975
976                                 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
977
978 #ifndef NO_PLUGIN_STATE
979                                 if (!c) {
980                                         continue;
981                                 }
982                                 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
983                                 if (ac) {
984                                         ac->set_state (**iter, version);
985                                 }
986 #endif
987                         }
988                 }
989         }
990 }
991
992 int
993 PluginInsert::set_state(const XMLNode& node, int version)
994 {
995         XMLNodeList nlist = node.children();
996         XMLNodeIterator niter;
997         XMLPropertyList plist;
998         const XMLProperty *prop;
999         ARDOUR::PluginType type;
1000
1001         if ((prop = node.property ("type")) == 0) {
1002                 error << _("XML node describing plugin is missing the `type' field") << endmsg;
1003                 return -1;
1004         }
1005
1006         if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
1007                 type = ARDOUR::LADSPA;
1008         } else if (prop->value() == X_("lv2")) {
1009                 type = ARDOUR::LV2;
1010         } else if (prop->value() == X_("windows-vst")) {
1011                 type = ARDOUR::Windows_VST;
1012         } else if (prop->value() == X_("lxvst")) {
1013                 type = ARDOUR::LXVST;
1014         } else if (prop->value() == X_("audiounit")) {
1015                 type = ARDOUR::AudioUnit;
1016         } else {
1017                 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
1018                                   prop->value())
1019                       << endmsg;
1020                 return -1;
1021         }
1022
1023         prop = node.property ("unique-id");
1024
1025         if (prop == 0) {
1026 #ifdef WINDOWS_VST_SUPPORT
1027                 /* older sessions contain VST plugins with only an "id" field.
1028                  */
1029
1030                 if (type == ARDOUR::Windows_VST) {
1031                         prop = node.property ("id");
1032                 }
1033 #endif
1034
1035 #ifdef LXVST_SUPPORT
1036                 /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
1037
1038                 if (type == ARDOUR::LXVST) {
1039                         prop = node.property ("id");
1040                 }
1041 #endif
1042                 /* recheck  */
1043
1044                 if (prop == 0) {
1045                         error << _("Plugin has no unique ID field") << endmsg;
1046                         return -1;
1047                 }
1048         }
1049
1050         boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
1051
1052         /* treat linux and windows VST plugins equivalent if they have the same uniqueID
1053          * allow to move sessions windows <> linux */
1054 #ifdef LXVST_SUPPORT
1055         if (plugin == 0 && type == ARDOUR::Windows_VST) {
1056                 type = ARDOUR::LXVST;
1057                 plugin = find_plugin (_session, prop->value(), type);
1058         }
1059 #endif
1060
1061 #ifdef WINDOWS_VST_SUPPORT
1062         if (plugin == 0 && type == ARDOUR::LXVST) {
1063                 type = ARDOUR::Windows_VST;
1064                 plugin = find_plugin (_session, prop->value(), type);
1065         }
1066 #endif
1067
1068         if (plugin == 0) {
1069                 error << string_compose(
1070                         _("Found a reference to a plugin (\"%1\") that is unknown.\n"
1071                           "Perhaps it was removed or moved since it was last used."),
1072                         prop->value())
1073                       << endmsg;
1074                 return -1;
1075         }
1076
1077         // The name of the PluginInsert comes from the plugin, nothing else
1078         _name = plugin->get_info()->name;
1079
1080         uint32_t count = 1;
1081
1082         // Processor::set_state() will set this, but too late
1083         // for it to be available when setting up plugin
1084         // state. We can't call Processor::set_state() until
1085         // the plugins themselves are created and added.
1086
1087         set_id (node);
1088
1089         if (_plugins.empty()) {
1090                 /* if we are adding the first plugin, we will need to set
1091                    up automatable controls.
1092                 */
1093                 add_plugin (plugin);
1094                 create_automatable_parameters ();
1095                 set_control_ids (node, version);
1096         }
1097
1098         if ((prop = node.property ("count")) != 0) {
1099                 sscanf (prop->value().c_str(), "%u", &count);
1100         }
1101
1102         if (_plugins.size() != count) {
1103                 for (uint32_t n = 1; n < count; ++n) {
1104                         add_plugin (plugin_factory (plugin));
1105                 }
1106         }
1107
1108         Processor::set_state (node, version);
1109
1110         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1111
1112                 /* find the node with the type-specific node name ("lv2", "ladspa", etc)
1113                    and set all plugins to the same state.
1114                 */
1115
1116                 if ((*niter)->name() == plugin->state_node_name()) {
1117
1118                         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1119                                 (*i)->set_state (**niter, version);
1120                         }
1121
1122                         break;
1123                 }
1124         }
1125
1126         if (version < 3000) {
1127
1128                 /* Only 2.X sessions need a call to set_parameter_state() - in 3.X and above
1129                    this is all handled by Automatable
1130                 */
1131
1132                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1133                         if ((*niter)->name() == "Redirect") {
1134                                 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
1135                                 Processor::set_state (**niter, version);
1136                                 break;
1137                         }
1138                 }
1139
1140                 set_parameter_state_2X (node, version);
1141         }
1142
1143         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1144                 if (active()) {
1145                         (*i)->activate ();
1146                 } else {
1147                         (*i)->deactivate ();
1148                 }
1149         }
1150
1151         return 0;
1152 }
1153
1154 void
1155 PluginInsert::update_id (PBD::ID id)
1156 {
1157         set_id (id.to_s());
1158         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1159                 (*i)->set_insert_id (id);
1160         }
1161 }
1162
1163 void
1164 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
1165 {
1166         XMLNodeList nlist = node.children();
1167         XMLNodeIterator niter;
1168
1169         /* look for port automation node */
1170
1171         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1172
1173                 if ((*niter)->name() != port_automation_node_name) {
1174                         continue;
1175                 }
1176
1177                 XMLNodeList cnodes;
1178                 XMLProperty *cprop;
1179                 XMLNodeConstIterator iter;
1180                 XMLNode *child;
1181                 const char *port;
1182                 uint32_t port_id;
1183
1184                 cnodes = (*niter)->children ("port");
1185
1186                 for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
1187
1188                         child = *iter;
1189
1190                         if ((cprop = child->property("number")) != 0) {
1191                                 port = cprop->value().c_str();
1192                         } else {
1193                                 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
1194                                 continue;
1195                         }
1196
1197                         sscanf (port, "%" PRIu32, &port_id);
1198
1199                         if (port_id >= _plugins[0]->parameter_count()) {
1200                                 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
1201                                 continue;
1202                         }
1203
1204                         boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
1205                                         control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
1206
1207                         if (c && c->alist()) {
1208                                 if (!child->children().empty()) {
1209                                         c->alist()->set_state (*child->children().front(), version);
1210
1211                                         /* In some cases 2.X saves lists with min_yval and max_yval
1212                                            being FLT_MIN and FLT_MAX respectively.  This causes problems
1213                                            in A3 because these min/max values are used to compute
1214                                            where GUI control points should be drawn.  If we see such
1215                                            values, `correct' them to the min/max of the appropriate
1216                                            parameter.
1217                                         */
1218
1219                                         float min_y = c->alist()->get_min_y ();
1220                                         float max_y = c->alist()->get_max_y ();
1221
1222                                         ParameterDescriptor desc;
1223                                         _plugins.front()->get_parameter_descriptor (port_id, desc);
1224
1225                                         if (min_y == FLT_MIN) {
1226                                                 min_y = desc.lower;
1227                                         }
1228
1229                                         if (max_y == FLT_MAX) {
1230                                                 max_y = desc.upper;
1231                                         }
1232
1233                                         c->alist()->set_yrange (min_y, max_y);
1234                                 }
1235                         } else {
1236                                 error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
1237                         }
1238                 }
1239
1240                 /* done */
1241
1242                 break;
1243         }
1244 }
1245
1246
1247 string
1248 PluginInsert::describe_parameter (Evoral::Parameter param)
1249 {
1250         if (param.type() == PluginAutomation) {
1251                 return _plugins[0]->describe_parameter (param);
1252         } else if (param.type() == PluginPropertyAutomation) {
1253                 boost::shared_ptr<AutomationControl> c(automation_control(param));
1254                 if (c && !c->desc().label.empty()) {
1255                         return c->desc().label;
1256                 }
1257         }
1258         return Automatable::describe_parameter(param);
1259 }
1260
1261 ARDOUR::framecnt_t
1262 PluginInsert::signal_latency() const
1263 {
1264         if (_user_latency) {
1265                 return _user_latency;
1266         }
1267
1268         return _plugins[0]->signal_latency ();
1269 }
1270
1271 ARDOUR::PluginType
1272 PluginInsert::type ()
1273 {
1274        return plugin()->get_info()->type;
1275 }
1276
1277 PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
1278                                             const Evoral::Parameter&          param,
1279                                             const ParameterDescriptor&        desc,
1280                                             boost::shared_ptr<AutomationList> list)
1281         : AutomationControl (p->session(), param, desc, list, p->describe_parameter(param))
1282         , _plugin (p)
1283 {
1284         if (alist()) {
1285                 alist()->reset_default (desc.normal);
1286                 if (desc.toggled) {
1287                         list->set_interpolation(Evoral::ControlList::Discrete);
1288                 }
1289         }
1290
1291         if (desc.toggled) {
1292                 set_flags(Controllable::Toggle);
1293         }
1294 }
1295
1296 /** @param val `user' value */
1297 void
1298 PluginInsert::PluginControl::set_value (double user_val)
1299 {
1300         /* FIXME: probably should be taking out some lock here.. */
1301
1302         for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
1303                 (*i)->set_parameter (_list->parameter().id(), user_val);
1304         }
1305
1306         boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
1307         if (iasp) {
1308                 iasp->set_parameter (_list->parameter().id(), user_val);
1309         }
1310
1311         AutomationControl::set_value (user_val);
1312 }
1313
1314 XMLNode&
1315 PluginInsert::PluginControl::get_state ()
1316 {
1317         stringstream ss;
1318
1319         XMLNode& node (AutomationControl::get_state());
1320         ss << parameter().id();
1321         node.add_property (X_("parameter"), ss.str());
1322
1323         return node;
1324 }
1325
1326 /** @return `user' val */
1327 double
1328 PluginInsert::PluginControl::get_value () const
1329 {
1330         /* FIXME: probably should be taking out some lock here.. */
1331         return _plugin->get_parameter (_list->parameter());
1332 }
1333
1334 PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*                     p,
1335                                                             const Evoral::Parameter&          param,
1336                                                             const ParameterDescriptor&        desc,
1337                                                             boost::shared_ptr<AutomationList> list)
1338         : AutomationControl (p->session(), param, desc, list)
1339         , _plugin (p)
1340 {
1341         if (alist()) {
1342                 alist()->set_yrange (desc.lower, desc.upper);
1343                 alist()->reset_default (desc.normal);
1344         }
1345
1346         if (desc.toggled) {
1347                 set_flags(Controllable::Toggle);
1348         }
1349 }
1350
1351 void
1352 PluginInsert::PluginPropertyControl::set_value (double user_val)
1353 {
1354         /* Old numeric set_value(), coerce to appropriate datatype if possible.
1355            This is lossy, but better than nothing until Ardour's automation system
1356            can handle various datatypes all the way down. */
1357         const Variant value(_desc.datatype, user_val);
1358         if (value.type() == Variant::NOTHING) {
1359                 error << "set_value(double) called for non-numeric property" << endmsg;
1360                 return;
1361         }
1362
1363         for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
1364                 (*i)->set_property(_list->parameter().id(), value);
1365         }
1366
1367         _value = value;
1368         AutomationControl::set_value(user_val);
1369 }
1370
1371 XMLNode&
1372 PluginInsert::PluginPropertyControl::get_state ()
1373 {
1374         stringstream ss;
1375
1376         XMLNode& node (AutomationControl::get_state());
1377         ss << parameter().id();
1378         node.add_property (X_("property"), ss.str());
1379         node.remove_property (X_("value"));
1380
1381         return node;
1382 }
1383
1384 double
1385 PluginInsert::PluginPropertyControl::get_value () const
1386 {
1387         return _value.to_double();
1388 }
1389
1390 boost::shared_ptr<Plugin>
1391 PluginInsert::get_impulse_analysis_plugin()
1392 {
1393         boost::shared_ptr<Plugin> ret;
1394         if (_impulseAnalysisPlugin.expired()) {
1395                 ret = plugin_factory(_plugins[0]);
1396                 ret->configure_io (input_streams (), output_streams ());
1397                 _impulseAnalysisPlugin = ret;
1398         } else {
1399                 ret = _impulseAnalysisPlugin.lock();
1400         }
1401
1402         return ret;
1403 }
1404
1405 void
1406 PluginInsert::collect_signal_for_analysis (framecnt_t nframes)
1407 {
1408         // called from outside the audio thread, so this should be safe
1409         // only do audio as analysis is (currently) only for audio plugins
1410         _signal_analysis_inputs.ensure_buffers(  DataType::AUDIO, input_streams().n_audio(),  nframes);
1411         _signal_analysis_outputs.ensure_buffers( DataType::AUDIO, output_streams().n_audio(), nframes);
1412
1413         _signal_analysis_collected_nframes   = 0;
1414         _signal_analysis_collect_nframes_max = nframes;
1415 }
1416
1417 /** Add a plugin to our list */
1418 void
1419 PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
1420 {
1421         plugin->set_insert_id (this->id());
1422         
1423         if (_plugins.empty()) {
1424                 /* first (and probably only) plugin instance - connect to relevant signals 
1425                  */
1426
1427                 plugin->ParameterChanged.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed, this, _1, _2));
1428                 plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
1429                 plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
1430         }
1431
1432         _plugins.push_back (plugin);
1433 }
1434
1435 void
1436 PluginInsert::realtime_handle_transport_stopped ()
1437 {
1438         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1439                 (*i)->realtime_handle_transport_stopped ();
1440         }
1441 }
1442
1443 void
1444 PluginInsert::realtime_locate ()
1445 {
1446         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1447                 (*i)->realtime_locate ();
1448         }
1449 }
1450
1451 void
1452 PluginInsert::monitoring_changed ()
1453 {
1454         for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1455                 (*i)->monitoring_changed ();
1456         }
1457 }
1458
1459 void
1460 PluginInsert::start_touch (uint32_t param_id)
1461 {
1462         boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
1463         if (ac) {
1464                 ac->start_touch (session().audible_frame());
1465         }
1466 }
1467
1468 void
1469 PluginInsert::end_touch (uint32_t param_id)
1470 {
1471         boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
1472         if (ac) {
1473                 ac->stop_touch (true, session().audible_frame());
1474         }
1475 }