1 /*
2 * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
4 * Copyright (C) 2006 Jesse Chappell <jesse@essej.net>
5 * Copyright (C) 2007-2014 David Robillard <d@drobilla.net>
6 * Copyright (C) 2007-2017 Tim Mayberry <mojofunk@gmail.com>
7 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
8 * Copyright (C) 2013-2015 John Emmas <john@creativepost.co.uk>
9 * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26 #ifdef WAF_BUILD
27 #include "libardour-config.h"
28 #endif
29
30 #include <vector>
31 #include <string>
32
33 #include <cstdlib>
34 #include <cstdio> // so libraptor doesn't complain
35 #include <cmath>
36 #ifndef COMPILER_MSVC
37 #include <dirent.h>
38 #endif
39 #include <sys/stat.h>
40 #include <cerrno>
41 #include <utility>
42
43 #ifdef HAVE_LRDF
44 #include <lrdf.h>
45 #endif
46
47 #include "pbd/compose.h"
48 #include "pbd/error.h"
49 #include "pbd/xml++.h"
50
51 #include "ardour/buffer_set.h"
52 #include "ardour/chan_count.h"
53 #include "ardour/chan_mapping.h"
54 #include "ardour/data_type.h"
55 #include "ardour/luaproc.h"
56 #include "ardour/lv2_plugin.h"
57 #include "ardour/midi_buffer.h"
58 #include "ardour/midi_state_tracker.h"
59 #include "ardour/plugin.h"
60 #include "ardour/plugin_manager.h"
61 #include "ardour/port.h"
62 #include "ardour/session.h"
63 #include "ardour/types.h"
64
65 #ifdef AUDIOUNIT_SUPPORT
66 #include "ardour/audio_unit.h"
67 #endif
68
69 #include "pbd/stl_delete.h"
70
71 #include "pbd/i18n.h"
72 #include <locale.h>
73
74 using namespace std;
75 using namespace ARDOUR;
76 using namespace PBD;
77
78 namespace ARDOUR { class AudioEngine; }
79
80 PBD::Signal3<void, std::string, Plugin*, bool> Plugin::PresetsChanged;
81
82 bool
needs_midi_input() const83 PluginInfo::needs_midi_input () const
84 {
85 return (n_inputs.n_midi() != 0);
86 }
87
Plugin(AudioEngine & e,Session & s)88 Plugin::Plugin (AudioEngine& e, Session& s)
89 : _engine (e)
90 , _session (s)
91 , _cycles (0)
92 , _owner (0)
93 , _for_impulse_analysis (false)
94 , _have_presets (false)
95 , _have_pending_stop_events (false)
96 , _parameter_changed_since_last_preset (false)
97 , _immediate_events(6096) // FIXME: size?
98 {
99 _pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
100 PresetsChanged.connect_same_thread(_preset_connection, boost::bind (&Plugin::invalidate_preset_cache, this, _1, _2, _3));
101 }
102
Plugin(const Plugin & other)103 Plugin::Plugin (const Plugin& other)
104 : StatefulDestructible()
105 , HasLatency()
106 , _engine (other._engine)
107 , _session (other._session)
108 , _info (other._info)
109 , _cycles (0)
110 , _owner (other._owner)
111 , _for_impulse_analysis (false)
112 , _have_presets (false)
113 , _have_pending_stop_events (false)
114 , _last_preset (other._last_preset)
115 , _parameter_changed_since_last_preset (false)
116 , _immediate_events(6096) // FIXME: size?
117 {
118 _pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
119
120 PresetsChanged.connect_same_thread(_preset_connection, boost::bind (&Plugin::invalidate_preset_cache, this, _1, _2, _3));
121 }
122
~Plugin()123 Plugin::~Plugin ()
124 {
125 }
126
127 void
remove_preset(string name)128 Plugin::remove_preset (string name)
129 {
130 Plugin::PresetRecord const * p = preset_by_label (name);
131 if (!p) {
132 PBD::error << _("Trying to remove nonexistent preset.") << endmsg;
133 return;
134 }
135 if (!p->user) {
136 PBD::error << _("Cannot remove plugin factory preset.") << endmsg;
137 return;
138 }
139
140 do_remove_preset (name);
141 _presets.erase (p->uri);
142
143 _last_preset.uri = "";
144 _parameter_changed_since_last_preset = false;
145 _have_presets = false;
146 PresetsChanged (unique_id(), this, false); /* EMIT SIGNAL */
147 PresetRemoved (); /* EMIT SIGNAL */
148 }
149
150 Plugin::PresetRecord
save_preset(string name)151 Plugin::save_preset (string name)
152 {
153 Plugin::PresetRecord const* p = preset_by_label (name);
154 if (p && !p->user) {
155 PBD::error << _("A factory presets with given name already exists.") << endmsg;
156 return Plugin::PresetRecord ();
157 }
158
159 string const uri = do_save_preset (name);
160
161 if (uri.empty()) {
162 /* save failed, clean up preset */
163 do_remove_preset (name);
164 PBD::error << _("Failed to save plugin preset.") << endmsg;
165 return Plugin::PresetRecord ();
166 }
167
168 if (p) {
169 _presets.erase (p->uri);
170 _parameter_changed_since_last_preset = false;
171 }
172
173 _presets.insert (make_pair (uri, PresetRecord (uri, name)));
174 _have_presets = false;
175 PresetsChanged (unique_id(), this, true); /* EMIT SIGNAL */
176 PresetAdded (); /* EMIT SIGNAL */
177
178 return PresetRecord (uri, name);
179 }
180
181 void
invalidate_preset_cache(std::string const & id,Plugin * plugin,bool added)182 Plugin::invalidate_preset_cache (std::string const& id, Plugin* plugin, bool added)
183 {
184 if (this == plugin || id != unique_id ()) {
185 return;
186 }
187
188 // TODO: use a shared cache in _info (via PluginInfo::get_presets)
189
190 _presets.clear ();
191 _have_presets = false;
192
193 if (added) {
194 PresetAdded (); /* EMIT SIGNAL */
195 } else {
196 PresetRemoved (); /* EMIT SIGNAL */
197 }
198 }
199
200 PluginPtr
find_plugin(Session & session,string identifier,PluginType type)201 ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
202 {
203 PluginManager& mgr (PluginManager::instance());
204 PluginInfoList plugs;
205
206 switch (type) {
207 case ARDOUR::Lua:
208 plugs = mgr.lua_plugin_info();
209 break;
210
211 case ARDOUR::LADSPA:
212 plugs = mgr.ladspa_plugin_info();
213 break;
214
215 case ARDOUR::LV2:
216 plugs = mgr.lv2_plugin_info();
217 break;
218
219 #ifdef WINDOWS_VST_SUPPORT
220 case ARDOUR::Windows_VST:
221 plugs = mgr.windows_vst_plugin_info();
222 break;
223 #endif
224
225 #ifdef LXVST_SUPPORT
226 case ARDOUR::LXVST:
227 plugs = mgr.lxvst_plugin_info();
228 break;
229 #endif
230
231 #ifdef MACVST_SUPPORT
232 case ARDOUR::MacVST:
233 plugs = mgr.mac_vst_plugin_info();
234 break;
235 #endif
236
237 #ifdef VST3_SUPPORT
238 case ARDOUR::VST3:
239 plugs = mgr.vst3_plugin_info();
240 break;
241 #endif
242
243 #ifdef AUDIOUNIT_SUPPORT
244 case ARDOUR::AudioUnit:
245 plugs = mgr.au_plugin_info();
246 break;
247 #endif
248
249 default:
250 return PluginPtr ((Plugin *) 0);
251 }
252
253 PluginInfoList::iterator i;
254
255 for (i = plugs.begin(); i != plugs.end(); ++i) {
256 if (identifier == (*i)->unique_id){
257 return (*i)->load (session);
258 }
259 }
260
261 #ifdef WINDOWS_VST_SUPPORT
262 /* hmm, we didn't find it. could be because in older versions of Ardour.
263 we used to store the name of a VST plugin, not its unique ID. so try
264 again.
265 */
266
267 for (i = plugs.begin(); i != plugs.end(); ++i) {
268 if (identifier == (*i)->name){
269 return (*i)->load (session);
270 }
271 }
272 #endif
273
274 #ifdef LXVST_SUPPORT
275 /* hmm, we didn't find it. could be because in older versions of Ardour.
276 we used to store the name of a VST plugin, not its unique ID. so try
277 again.
278 */
279
280 for (i = plugs.begin(); i != plugs.end(); ++i) {
281 if (identifier == (*i)->name){
282 return (*i)->load (session);
283 }
284 }
285 #endif
286
287 return PluginPtr ();
288 }
289
290 ChanCount
output_streams() const291 Plugin::output_streams () const
292 {
293 /* LADSPA & VST should not get here because they do not
294 return "infinite" i/o counts.
295 */
296 return ChanCount::ZERO;
297 }
298
299 ChanCount
input_streams() const300 Plugin::input_streams () const
301 {
302 /* LADSPA & VST should not get here because they do not
303 return "infinite" i/o counts.
304 */
305 return ChanCount::ZERO;
306 }
307
308 Plugin::IOPortDescription
describe_io_port(ARDOUR::DataType dt,bool input,uint32_t id) const309 Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
310 {
311 std::stringstream ss;
312 switch (dt) {
313 case DataType::AUDIO:
314 ss << _("Audio") << " ";
315 break;
316 case DataType::MIDI:
317 ss << _("Midi") << " ";
318 break;
319 default:
320 ss << _("?") << " ";
321 break;
322 }
323 if (input) {
324 ss << _("In") << " ";
325 } else {
326 ss << _("Out") << " ";
327 }
328
329 std::stringstream gn;
330 gn << ss.str();
331
332 ss << (id + 1);
333 gn << (id / 2 + 1) << " L/R";
334
335 Plugin::IOPortDescription iod (ss.str());
336 iod.group_name = gn.str();
337 iod.group_channel = id % 2;
338 return iod;
339 }
340
341 PluginOutputConfiguration
possible_output() const342 Plugin::possible_output () const
343 {
344 PluginOutputConfiguration oc;
345 if (_info) {
346 oc.insert (_info->n_outputs.n_audio ());
347 }
348 return oc;
349 }
350
351 const Plugin::PresetRecord *
preset_by_label(const string & label)352 Plugin::preset_by_label (const string& label)
353 {
354 if (!_have_presets) {
355 find_presets ();
356 _have_presets = true;
357 }
358
359 // FIXME: O(n)
360 for (map<string, PresetRecord>::const_iterator i = _presets.begin(); i != _presets.end(); ++i) {
361 if (i->second.label == label) {
362 return &i->second;
363 }
364 }
365
366 return 0;
367 }
368
369 const Plugin::PresetRecord *
preset_by_uri(const string & uri)370 Plugin::preset_by_uri (const string& uri)
371 {
372 if (uri.empty ()) {
373 return 0;
374 }
375 if (!_have_presets) {
376 find_presets ();
377 _have_presets = true;
378 }
379
380 map<string, PresetRecord>::const_iterator pr = _presets.find (uri);
381 if (pr != _presets.end()) {
382 return &pr->second;
383 } else {
384 return 0;
385 }
386 }
387
388 bool
write_immediate_event(Evoral::EventType event_type,size_t size,const uint8_t * buf)389 Plugin::write_immediate_event (Evoral::EventType event_type, size_t size, const uint8_t* buf)
390 {
391 if (!Evoral::midi_event_is_valid (buf, size)) {
392 return false;
393 }
394 return (_immediate_events.write (0, event_type, size, buf) == size);
395 }
396
397 int
connect_and_run(BufferSet & bufs,samplepos_t,samplepos_t,double,ChanMapping const &,ChanMapping const &,pframes_t nframes,samplecnt_t)398 Plugin::connect_and_run (BufferSet& bufs,
399 samplepos_t /*start*/, samplepos_t /*end*/, double /*speed*/,
400 ChanMapping const& /*in_map*/, ChanMapping const& /*out_map*/,
401 pframes_t nframes, samplecnt_t /*offset*/)
402 {
403 if (bufs.count().n_midi() > 0) {
404
405 if (_immediate_events.read_space() && nframes > 0) {
406 _immediate_events.read (bufs.get_midi (0), 0, 1, nframes - 1, true);
407 }
408
409 /* Track notes that we are sending to the plugin */
410 const MidiBuffer& b = bufs.get_midi (0);
411
412 _tracker.track (b.begin(), b.end());
413
414 if (_have_pending_stop_events) {
415 /* Transmit note-offs that are pending from the last transport stop */
416 bufs.merge_from (_pending_stop_events, 0);
417 _have_pending_stop_events = false;
418 }
419 }
420
421 return 0;
422 }
423
424 void
realtime_handle_transport_stopped()425 Plugin::realtime_handle_transport_stopped ()
426 {
427 resolve_midi ();
428 }
429
430 void
realtime_locate(bool for_loop_end)431 Plugin::realtime_locate (bool for_loop_end)
432 {
433 if (!for_loop_end) {
434 resolve_midi ();
435 }
436 }
437
438 void
monitoring_changed()439 Plugin::monitoring_changed ()
440 {
441 resolve_midi ();
442 }
443
444 void
resolve_midi()445 Plugin::resolve_midi ()
446 {
447 /* Create note-offs for any active notes and put them in _pending_stop_events, to be picked
448 up on the next call to connect_and_run ().
449 */
450
451 _pending_stop_events.get_midi(0).clear ();
452 _tracker.resolve_notes (_pending_stop_events.get_midi (0), 0);
453 _have_pending_stop_events = true;
454 }
455
456 vector<Plugin::PresetRecord>
get_presets()457 Plugin::get_presets ()
458 {
459 vector<PresetRecord> p;
460
461 if (!_have_presets) {
462 find_presets ();
463 _have_presets = true;
464 }
465
466 for (map<string, PresetRecord>::const_iterator i = _presets.begin(); i != _presets.end(); ++i) {
467 p.push_back (i->second);
468 }
469
470 return p;
471 }
472
473 bool
load_preset(PresetRecord r)474 Plugin::load_preset (PresetRecord r)
475 {
476 _last_preset = r;
477 _parameter_changed_since_last_preset = false;
478
479 _session.set_dirty ();
480 PresetLoaded (); /* EMIT SIGNAL */
481 return true;
482 }
483
484 void
clear_preset()485 Plugin::clear_preset ()
486 {
487 _last_preset.uri = "";
488 _last_preset.label = "";
489 _parameter_changed_since_last_preset = false;
490
491 _session.set_dirty ();
492 PresetLoaded (); /* EMIT SIGNAL */
493 }
494
495 void
set_parameter(uint32_t,float,sampleoffset_t)496 Plugin::set_parameter (uint32_t /* which */, float /* value */, sampleoffset_t /* when */)
497 {
498 _parameter_changed_since_last_preset = true;
499 PresetDirty (); /* EMIT SIGNAL */
500 }
501
502 void
parameter_changed_externally(uint32_t which,float)503 Plugin::parameter_changed_externally (uint32_t which, float /* value */)
504 {
505 _parameter_changed_since_last_preset = true;
506 _session.set_dirty ();
507 ParameterChangedExternally (which, get_parameter (which)); /* EMIT SIGNAL */
508 PresetDirty (); /* EMIT SIGNAL */
509 }
510
511 void
state_changed()512 Plugin::state_changed ()
513 {
514 _parameter_changed_since_last_preset = true;
515 _session.set_dirty ();
516 PresetDirty (); /* EMIT SIGNAL */
517 }
518
519 int
set_state(const XMLNode & node,int)520 Plugin::set_state (const XMLNode& node, int /*version*/)
521 {
522 std::string preset_uri;
523 const Plugin::PresetRecord* r = 0;
524 if (node.get_property (X_("last-preset-uri"), preset_uri)) {
525 r = preset_by_uri (preset_uri);
526 }
527 if (r) {
528 _last_preset = *r;
529 node.get_property (X_("parameter-changed-since-last-preset"), _parameter_changed_since_last_preset); // XXX
530 } else {
531 _last_preset.uri = "";
532 _last_preset.valid = false;
533 }
534 return 0;
535 }
536
537 XMLNode &
get_state()538 Plugin::get_state ()
539 {
540 XMLNode* root = new XMLNode (state_node_name ());
541
542 root->set_property (X_("last-preset-uri"), _last_preset.uri);
543 root->set_property (X_("last-preset-label"), _last_preset.label);
544 root->set_property (X_("parameter-changed-since-last-preset"), _parameter_changed_since_last_preset);
545
546 add_state (root);
547
548 return *root;
549 }
550
551 std::string
parameter_label(uint32_t which) const552 Plugin::parameter_label (uint32_t which) const
553 {
554 if (which >= parameter_count ()) {
555 return "";
556 }
557 ParameterDescriptor pd;
558 get_parameter_descriptor (which, pd);
559 return pd.label;
560 }
561
562 bool
is_effect() const563 PluginInfo::is_effect () const
564 {
565 return (!is_instrument () && !is_utility () && !is_analyzer ());
566 }
567
568 bool
is_instrument() const569 PluginInfo::is_instrument () const
570 {
571 if (category == "Instrument") {
572 return true;
573 }
574
575 // second check: if we have midi input and audio output, we're likely an instrument
576 return (n_inputs.n_midi() != 0) && (n_outputs.n_audio() > 0) && (n_inputs.n_audio() == 0);
577 }
578
579 bool
is_utility() const580 PluginInfo::is_utility () const
581 {
582 /* XXX beware of translations, e.g. LV2 categories */
583 return (category == "Utility" || category == "MIDI" || category == "Generator");
584 }
585
586 bool
is_analyzer() const587 PluginInfo::is_analyzer () const
588 {
589 return (category == "Analyser" || category == "Anaylsis" || category == "Analyzer");
590 }
591