detect VST midi-in/midi-out ports separately.
[ardour.git] / libs / ardour / plugin_manager.cc
1 /*
2     Copyright (C) 2000-2006 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 <stdint.h>
25
26 #include <sys/types.h>
27 #include <cstdio>
28 #include <cstdlib>
29 #include <fstream>
30
31 #ifdef HAVE_LRDF
32 #include <lrdf.h>
33 #endif
34
35 #ifdef WINDOWS_VST_SUPPORT
36 #include "ardour/vst_info_file.h"
37 #include "fst.h"
38 #include "pbd/basename.h"
39 #include <cstring>
40 #endif // WINDOWS_VST_SUPPORT
41
42 #ifdef LXVST_SUPPORT
43 #include "ardour/vst_info_file.h"
44 #include "ardour/linux_vst_support.h"
45 #include "pbd/basename.h"
46 #include <cstring>
47 #endif //LXVST_SUPPORT
48
49 #include <glib/gstdio.h>
50 #include <glibmm/miscutils.h>
51 #include <glibmm/pattern.h>
52
53 #include "pbd/pathscanner.h"
54 #include "pbd/whitespace.h"
55 #include "pbd/file_utils.h"
56
57 #include "ardour/debug.h"
58 #include "ardour/filesystem_paths.h"
59 #include "ardour/ladspa.h"
60 #include "ardour/ladspa_plugin.h"
61 #include "ardour/plugin.h"
62 #include "ardour/plugin_manager.h"
63 #include "ardour/rc_configuration.h"
64
65 #include "ardour/ladspa_search_path.h"
66 #include "ardour/vst_search_path.h"
67
68 #ifdef LV2_SUPPORT
69 #include "ardour/lv2_plugin.h"
70 #endif
71
72 #ifdef WINDOWS_VST_SUPPORT
73 #include "ardour/windows_vst_plugin.h"
74 #endif
75
76 #ifdef LXVST_SUPPORT
77 #include "ardour/lxvst_plugin.h"
78 #endif
79
80 #ifdef AUDIOUNIT_SUPPORT
81 #include "ardour/audio_unit.h"
82 #include <Carbon/Carbon.h>
83 #endif
84
85 #include "pbd/error.h"
86 #include "pbd/stl_delete.h"
87
88 #include "i18n.h"
89
90 #include "ardour/debug.h"
91
92 using namespace ARDOUR;
93 using namespace PBD;
94 using namespace std;
95
96 PluginManager* PluginManager::_instance = 0;
97 std::string PluginManager::scanner_bin_path = "";
98
99 PluginManager&
100 PluginManager::instance()
101 {
102         if (!_instance) {
103                 _instance = new PluginManager;
104         }
105         return *_instance;
106 }
107
108 PluginManager::PluginManager ()
109         : _windows_vst_plugin_info(0)
110         , _lxvst_plugin_info(0)
111         , _ladspa_plugin_info(0)
112         , _lv2_plugin_info(0)
113         , _au_plugin_info(0)
114         , cancel_scan(false)
115 {
116         char* s;
117         string lrdf_path;
118
119         if (!PBD::find_file_in_search_path (
120                                 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst")),
121                                 "ardour-vst-scanner", scanner_bin_path)) {
122                 PBD::warning << "VST scanner app not found.'" << endmsg;
123         }
124
125         load_statuses ();
126
127         if ((s = getenv ("LADSPA_RDF_PATH"))){
128                 lrdf_path = s;
129         }
130
131         if (lrdf_path.length() == 0) {
132                 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
133         }
134
135         add_lrdf_data(lrdf_path);
136         add_ladspa_presets();
137 #ifdef WINDOWS_VST_SUPPORT
138         if (Config->get_use_windows_vst ()) {
139                 add_windows_vst_presets ();
140         }
141 #endif /* WINDOWS_VST_SUPPORT */
142
143 #ifdef LXVST_SUPPORT
144         if (Config->get_use_lxvst()) {
145                 add_lxvst_presets();
146         }
147 #endif /* Native LinuxVST support*/
148
149         if ((s = getenv ("VST_PATH"))) {
150                 windows_vst_path = s;
151         } else if ((s = getenv ("VST_PLUGINS"))) {
152                 windows_vst_path = s;
153         }
154
155         if (windows_vst_path.length() == 0) {
156                 windows_vst_path = vst_search_path ();
157         }
158
159         if ((s = getenv ("LXVST_PATH"))) {
160                 lxvst_path = s;
161         } else if ((s = getenv ("LXVST_PLUGINS"))) {
162                 lxvst_path = s;
163         }
164
165         if (lxvst_path.length() == 0) {
166                 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
167                         "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
168                         "/usr/lib/vst:/usr/local/lib/vst";
169         }
170
171         /* first time setup, use 'default' path */
172         if (Config->get_plugin_path_lxvst() == X_("@default@")) {
173                 Config->set_plugin_path_lxvst(get_default_lxvst_path());
174         }
175         if (Config->get_plugin_path_vst() == X_("@default@")) {
176                 Config->set_plugin_path_vst(get_default_windows_vst_path());
177         }
178
179         if (_instance == 0) {
180                 _instance = this;
181         }
182
183         BootMessage (_("Discovering Plugins"));
184 }
185
186
187 PluginManager::~PluginManager()
188 {
189 }
190
191 void
192 PluginManager::refresh (bool cache_only)
193 {
194         DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
195         cancel_scan = false;
196
197         BootMessage (_("Scanning LADSPA Plugins"));
198         ladspa_refresh ();
199 #ifdef LV2_SUPPORT
200         BootMessage (_("Scanning LV2 Plugins"));
201         lv2_refresh ();
202 #endif
203 #ifdef WINDOWS_VST_SUPPORT
204         if (Config->get_use_windows_vst()) {
205                 BootMessage (_("Scanning Windows VST Plugins"));
206                 windows_vst_refresh (cache_only);
207         }
208 #endif // WINDOWS_VST_SUPPORT
209
210 #ifdef LXVST_SUPPORT
211         if(Config->get_use_lxvst()) {
212                 BootMessage (_("Scanning Linux VST Plugins"));
213                 lxvst_refresh(cache_only);
214         }
215 #endif //Native linuxVST SUPPORT
216
217 #ifdef AUDIOUNIT_SUPPORT
218         BootMessage (_("Scanning AU Plugins"));
219         au_refresh ();
220 #endif
221
222         BootMessage (_("Plugin Scan Complete..."));
223         PluginListChanged (); /* EMIT SIGNAL */
224         PluginScanMessage(X_("closeme"), "", false);
225         cancel_scan = false;
226 }
227
228 void
229 PluginManager::cancel_plugin_scan ()
230 {
231         cancel_scan = true;
232 }
233
234 void
235 PluginManager::clear_vst_cache ()
236 {
237         // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
238 #ifdef WINDOWS_VST_SUPPORT
239         {
240                 PathScanner scanner;
241                 vector<string *> *fsi_files;
242
243                 fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsi$", true, true, -1, false);
244                 if (fsi_files) {
245                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
246                                 ::g_unlink((*i)->c_str());
247                         }
248                 }
249                 vector_delete(fsi_files);
250         }
251 #endif
252
253 #ifdef LXVST_SUPPORT
254         {
255                 PathScanner scanner;
256                 vector<string *> *fsi_files;
257                 fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsi$", true, true, -1, false);
258                 if (fsi_files) {
259                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
260                                 ::g_unlink((*i)->c_str());
261                         }
262                 }
263                 vector_delete(fsi_files);
264         }
265 #endif
266
267 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
268         {
269                 string personal = get_personal_vst_info_cache_dir();
270                 PathScanner scanner;
271                 vector<string *> *fsi_files;
272                 fsi_files = scanner (personal, "\\.fsi$", true, true, -1, false);
273                 if (fsi_files) {
274                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
275                                 ::g_unlink((*i)->c_str());
276                         }
277                 }
278                 vector_delete(fsi_files);
279         }
280 #endif
281 }
282
283 void
284 PluginManager::clear_vst_blacklist ()
285 {
286 #ifdef WINDOWS_VST_SUPPORT
287         {
288                 PathScanner scanner;
289                 vector<string *> *fsi_files;
290
291                 fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsb$", true, true, -1, false);
292                 if (fsi_files) {
293                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
294                                 ::g_unlink((*i)->c_str());
295                         }
296                 }
297                 vector_delete(fsi_files);
298         }
299 #endif
300
301 #ifdef LXVST_SUPPORT
302         {
303                 PathScanner scanner;
304                 vector<string *> *fsi_files;
305                 fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsb$", true, true, -1, false);
306                 if (fsi_files) {
307                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
308                                 ::g_unlink((*i)->c_str());
309                         }
310                 }
311                 vector_delete(fsi_files);
312         }
313 #endif
314
315 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
316         {
317                 string personal = get_personal_vst_blacklist_dir();
318
319                 PathScanner scanner;
320                 vector<string *> *fsi_files;
321                 fsi_files = scanner (personal, "\\.fsb$", true, true, -1, false);
322                 if (fsi_files) {
323                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
324                                 ::g_unlink((*i)->c_str());
325                         }
326                 }
327                 vector_delete(fsi_files);
328         }
329 #endif
330 }
331
332 void
333 PluginManager::ladspa_refresh ()
334 {
335         if (_ladspa_plugin_info) {
336                 _ladspa_plugin_info->clear ();
337         } else {
338                 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
339         }
340
341         /* allow LADSPA_PATH to augment, not override standard locations */
342
343         /* Only add standard locations to ladspa_path if it doesn't
344          * already contain them. Check for trailing G_DIR_SEPARATOR too.
345          */
346
347         vector<string> ladspa_modules;
348
349         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
350
351         Glib::PatternSpec so_extension_pattern("*.so");
352         Glib::PatternSpec dylib_extension_pattern("*.dylib");
353         Glib::PatternSpec dll_extension_pattern("*.dll");
354
355         find_matching_files_in_search_path (ladspa_search_path (),
356                                             so_extension_pattern, ladspa_modules);
357
358         find_matching_files_in_search_path (ladspa_search_path (),
359                                             dylib_extension_pattern, ladspa_modules);
360
361         find_matching_files_in_search_path (ladspa_search_path (),
362                                             dll_extension_pattern, ladspa_modules);
363
364         for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
365                 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
366                 ladspa_discover (*i);
367         }
368 }
369
370 static bool rdf_filter (const string &str, void* /*arg*/)
371 {
372         return str[0] != '.' &&
373                    ((str.find(".rdf")  == (str.length() - 4)) ||
374             (str.find(".rdfs") == (str.length() - 5)) ||
375                     (str.find(".n3")   == (str.length() - 3)) ||
376                     (str.find(".ttl")  == (str.length() - 4)));
377 }
378
379 void
380 PluginManager::add_ladspa_presets()
381 {
382         add_presets ("ladspa");
383 }
384
385 void
386 PluginManager::add_windows_vst_presets()
387 {
388         add_presets ("windows-vst");
389 }
390
391 void
392 PluginManager::add_lxvst_presets()
393 {
394         add_presets ("lxvst");
395 }
396
397 void
398 PluginManager::add_presets(string domain)
399 {
400 #ifdef HAVE_LRDF
401         PathScanner scanner;
402         vector<string *> *presets;
403         vector<string *>::iterator x;
404
405         char* envvar;
406         if ((envvar = getenv ("HOME")) == 0) {
407                 return;
408         }
409
410         string path = string_compose("%1/.%2/rdf", envvar, domain);
411         presets = scanner (path, rdf_filter, 0, false, true);
412
413         if (presets) {
414                 for (x = presets->begin(); x != presets->end (); ++x) {
415                         string file = "file:" + **x;
416                         if (lrdf_read_file(file.c_str())) {
417                                 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
418                         }
419                 }
420
421                 vector_delete (presets);
422         }
423 #endif
424 }
425
426 void
427 PluginManager::add_lrdf_data (const string &path)
428 {
429 #ifdef HAVE_LRDF
430         PathScanner scanner;
431         vector<string *>* rdf_files;
432         vector<string *>::iterator x;
433
434         rdf_files = scanner (path, rdf_filter, 0, false, true);
435
436         if (rdf_files) {
437                 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
438                         const string uri(string("file://") + **x);
439
440                         if (lrdf_read_file(uri.c_str())) {
441                                 warning << "Could not parse rdf file: " << uri << endmsg;
442                         }
443                 }
444
445                 vector_delete (rdf_files);
446         }
447 #endif
448 }
449
450 int
451 PluginManager::ladspa_discover (string path)
452 {
453         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
454
455         Glib::Module module(path);
456         const LADSPA_Descriptor *descriptor;
457         LADSPA_Descriptor_Function dfunc;
458         void* func = 0;
459
460         if (!module) {
461                 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
462                         path, Glib::Module::get_last_error()) << endmsg;
463                 return -1;
464         }
465
466
467         if (!module.get_symbol("ladspa_descriptor", func)) {
468                 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
469                 error << Glib::Module::get_last_error() << endmsg;
470                 return -1;
471         }
472
473         dfunc = (LADSPA_Descriptor_Function)func;
474
475         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
476
477         for (uint32_t i = 0; ; ++i) {
478                 if ((descriptor = dfunc (i)) == 0) {
479                         break;
480                 }
481
482                 if (!ladspa_plugin_whitelist.empty()) {
483                         if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
484                                 continue;
485                         }
486                 }
487
488                 PluginInfoPtr info(new LadspaPluginInfo);
489                 info->name = descriptor->Name;
490                 info->category = get_ladspa_category(descriptor->UniqueID);
491                 info->creator = descriptor->Maker;
492                 info->path = path;
493                 info->index = i;
494                 info->n_inputs = ChanCount();
495                 info->n_outputs = ChanCount();
496                 info->type = ARDOUR::LADSPA;
497
498                 char buf[32];
499                 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
500                 info->unique_id = buf;
501
502                 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
503                         if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
504                                 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
505                                         info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
506                                 }
507                                 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
508                                         info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
509                                 }
510                         }
511                 }
512
513                 if(_ladspa_plugin_info->empty()){
514                         _ladspa_plugin_info->push_back (info);
515                 }
516
517                 //Ensure that the plugin is not already in the plugin list.
518
519                 bool found = false;
520
521                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
522                         if(0 == info->unique_id.compare((*i)->unique_id)){
523                               found = true;
524                         }
525                 }
526
527                 if(!found){
528                     _ladspa_plugin_info->push_back (info);
529                 }
530
531                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
532         }
533
534 // GDB WILL NOT LIKE YOU IF YOU DO THIS
535 //      dlclose (module);
536
537         return 0;
538 }
539
540 string
541 PluginManager::get_ladspa_category (uint32_t plugin_id)
542 {
543 #ifdef HAVE_LRDF
544         char buf[256];
545         lrdf_statement pattern;
546
547         snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
548         pattern.subject = buf;
549         pattern.predicate = const_cast<char*>(RDF_TYPE);
550         pattern.object = 0;
551         pattern.object_type = lrdf_uri;
552
553         lrdf_statement* matches1 = lrdf_matches (&pattern);
554
555         if (!matches1) {
556                 return "Unknown";
557         }
558
559         pattern.subject = matches1->object;
560         pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
561         pattern.object = 0;
562         pattern.object_type = lrdf_literal;
563
564         lrdf_statement* matches2 = lrdf_matches (&pattern);
565         lrdf_free_statements(matches1);
566
567         if (!matches2) {
568                 return ("Unknown");
569         }
570
571         string label = matches2->object;
572         lrdf_free_statements(matches2);
573
574         /* Kludge LADSPA class names to be singular and match LV2 class names.
575            This avoids duplicate plugin menus for every class, which is necessary
576            to make the plugin category menu at all usable, but is obviously a
577            filthy kludge.
578
579            In the short term, lrdf could be updated so the labels match and a new
580            release made. To support both specs, we should probably be mapping the
581            URIs to the same category in code and perhaps tweaking that hierarchy
582            dynamically to suit the user. Personally, I (drobilla) think that time
583            is better spent replacing the little-used LRDF.
584
585            In the longer term, we will abandon LRDF entirely in favour of LV2 and
586            use that class hierarchy. Aside from fixing this problem properly, that
587            will also allow for translated labels. SWH plugins have been LV2 for
588            ages; TAP needs porting. I don't know of anything else with LRDF data.
589         */
590         if (label == "Utilities") {
591                 return "Utility";
592         } else if (label == "Pitch shifters") {
593                 return "Pitch Shifter";
594         } else if (label != "Dynamics" && label != "Chorus"
595                    &&label[label.length() - 1] == 's'
596                    && label[label.length() - 2] != 's') {
597                 return label.substr(0, label.length() - 1);
598         } else {
599                 return label;
600         }
601 #else
602                 return ("Unknown");
603 #endif
604 }
605
606 #ifdef LV2_SUPPORT
607 void
608 PluginManager::lv2_refresh ()
609 {
610         DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
611         delete _lv2_plugin_info;
612         _lv2_plugin_info = LV2PluginInfo::discover();
613 }
614 #endif
615
616 #ifdef AUDIOUNIT_SUPPORT
617 void
618 PluginManager::au_refresh ()
619 {
620         DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
621         delete _au_plugin_info;
622         _au_plugin_info = AUPluginInfo::discover();
623 }
624
625 #endif
626
627 #ifdef WINDOWS_VST_SUPPORT
628
629 void
630 PluginManager::windows_vst_refresh (bool cache_only)
631 {
632         if (_windows_vst_plugin_info) {
633                 _windows_vst_plugin_info->clear ();
634         } else {
635                 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
636         }
637
638         windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
639 }
640
641 static bool windows_vst_filter (const string& str, void * /*arg*/)
642 {
643         /* Not a dotfile, has a prefix before a period, suffix is "dll" */
644
645         return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
646 }
647
648 int
649 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
650 {
651         PathScanner scanner;
652         vector<string *> *plugin_objects;
653         vector<string *>::iterator x;
654         int ret = 0;
655
656         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
657
658         plugin_objects = scanner (Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
659
660         if (plugin_objects) {
661                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
662                         ARDOUR::PluginScanMessage(_("VST"), **x, !cache_only && !cancelled());
663                         windows_vst_discover (**x, cache_only || cancelled());
664                 }
665
666                 vector_delete (plugin_objects);
667         }
668
669         return ret;
670 }
671
672 int
673 PluginManager::windows_vst_discover (string path, bool cache_only)
674 {
675         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
676
677         vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
678                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
679
680         if (finfos->empty()) {
681                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
682                 return -1;
683         }
684
685         uint32_t discovered = 0;
686         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
687                 VSTInfo* finfo = *x;
688                 char buf[32];
689
690                 if (!finfo->canProcessReplacing) {
691                         warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
692                                                          finfo->name, PROGRAM_NAME)
693                                 << endl;
694                         continue;
695                 }
696
697                 PluginInfoPtr info (new WindowsVSTPluginInfo);
698
699                 /* what a joke freeware VST is */
700
701                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
702                         info->name = PBD::basename_nosuffix (path);
703                 } else {
704                         info->name = finfo->name;
705                 }
706
707
708                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
709                 info->unique_id = buf;
710                 info->category = "VST";
711                 info->path = path;
712                 info->creator = finfo->creator;
713                 info->index = 0;
714                 info->n_inputs.set_audio (finfo->numInputs);
715                 info->n_outputs.set_audio (finfo->numOutputs);
716                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
717                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
718                 info->type = ARDOUR::Windows_VST;
719
720                 // TODO: check dup-IDs (lxvst AND windows vst)
721                 bool duplicate = false;
722
723                 if (!_windows_vst_plugin_info->empty()) {
724                         for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
725                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
726                                         warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
727                                         duplicate = true;
728                                         break;
729                                 }
730                         }
731                 }
732
733                 if (!duplicate) {
734                         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
735                         _windows_vst_plugin_info->push_back (info);
736                         discovered++;
737                 }
738         }
739
740         vstfx_free_info_list (finfos);
741         return discovered > 0 ? 0 : -1;
742 }
743
744 #endif // WINDOWS_VST_SUPPORT
745
746 #ifdef LXVST_SUPPORT
747
748 void
749 PluginManager::lxvst_refresh (bool cache_only)
750 {
751         if (_lxvst_plugin_info) {
752                 _lxvst_plugin_info->clear ();
753         } else {
754                 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
755         }
756
757         lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
758 }
759
760 static bool lxvst_filter (const string& str, void *)
761 {
762         /* Not a dotfile, has a prefix before a period, suffix is "so" */
763
764         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
765 }
766
767 int
768 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
769 {
770         PathScanner scanner;
771         vector<string *> *plugin_objects;
772         vector<string *>::iterator x;
773         int ret = 0;
774
775 #ifndef NDEBUG
776         (void) path;
777 #endif
778
779         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
780
781         plugin_objects = scanner (Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
782
783         if (plugin_objects) {
784                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
785                         ARDOUR::PluginScanMessage(_("LXVST"), **x, !cache_only && !cancelled());
786                         lxvst_discover (**x, cache_only || cancelled());
787                 }
788
789                 vector_delete (plugin_objects);
790         }
791
792         return ret;
793 }
794
795 int
796 PluginManager::lxvst_discover (string path, bool cache_only)
797 {
798         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
799
800         vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
801                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
802
803         if (finfos->empty()) {
804                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
805                 return -1;
806         }
807
808         uint32_t discovered = 0;
809         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
810                 VSTInfo* finfo = *x;
811                 char buf[32];
812
813                 if (!finfo->canProcessReplacing) {
814                         warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
815                                                          finfo->name, PROGRAM_NAME)
816                                 << endl;
817                         continue;
818                 }
819
820                 PluginInfoPtr info(new LXVSTPluginInfo);
821
822                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
823                         info->name = PBD::basename_nosuffix (path);
824                 } else {
825                         info->name = finfo->name;
826                 }
827
828
829                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
830                 info->unique_id = buf;
831                 info->category = "linuxVSTs";
832                 info->path = path;
833                 info->creator = finfo->creator;
834                 info->index = 0;
835                 info->n_inputs.set_audio (finfo->numInputs);
836                 info->n_outputs.set_audio (finfo->numOutputs);
837                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
838                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
839                 info->type = ARDOUR::LXVST;
840
841                                         /* Make sure we don't find the same plugin in more than one place along
842                          the LXVST_PATH We can't use a simple 'find' because the path is included
843                          in the PluginInfo, and that is the one thing we can be sure MUST be
844                          different if a duplicate instance is found.  So we just compare the type
845                          and unique ID (which for some VSTs isn't actually unique...)
846                 */
847
848                 // TODO: check dup-IDs with windowsVST, too
849                 bool duplicate = false;
850                 if (!_lxvst_plugin_info->empty()) {
851                         for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
852                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
853                                         warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
854                                         duplicate = true;
855                                         break;
856                                 }
857                         }
858                 }
859
860                 if (!duplicate) {
861                         _lxvst_plugin_info->push_back (info);
862                         discovered++;
863                 }
864         }
865
866         vstfx_free_info_list (finfos);
867         return discovered > 0 ? 0 : -1;
868 }
869
870 #endif // LXVST_SUPPORT
871
872
873 PluginManager::PluginStatusType
874 PluginManager::get_status (const PluginInfoPtr& pi)
875 {
876         PluginStatus ps (pi->type, pi->unique_id);
877         PluginStatusList::const_iterator i =  find (statuses.begin(), statuses.end(), ps);
878         if (i ==  statuses.end() ) {
879                 return Normal;
880         } else {
881                 return i->status;
882         }
883 }
884
885 void
886 PluginManager::save_statuses ()
887 {
888         ofstream ofs;
889         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
890
891         ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
892
893         if (!ofs) {
894                 return;
895         }
896
897         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
898                 switch ((*i).type) {
899                 case LADSPA:
900                         ofs << "LADSPA";
901                         break;
902                 case AudioUnit:
903                         ofs << "AudioUnit";
904                         break;
905                 case LV2:
906                         ofs << "LV2";
907                         break;
908                 case Windows_VST:
909                         ofs << "Windows-VST";
910                         break;
911                 case LXVST:
912                         ofs << "LXVST";
913                         break;
914                 }
915
916                 ofs << ' ';
917
918                 switch ((*i).status) {
919                 case Normal:
920                         ofs << "Normal";
921                         break;
922                 case Favorite:
923                         ofs << "Favorite";
924                         break;
925                 case Hidden:
926                         ofs << "Hidden";
927                         break;
928                 }
929
930                 ofs << ' ';
931                 ofs << (*i).unique_id;;
932                 ofs << endl;
933         }
934
935         ofs.close ();
936 }
937
938 void
939 PluginManager::load_statuses ()
940 {
941         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
942         ifstream ifs (path.c_str());
943
944         if (!ifs) {
945                 return;
946         }
947
948         std::string stype;
949         std::string sstatus;
950         std::string id;
951         PluginType type;
952         PluginStatusType status;
953         char buf[1024];
954
955         while (ifs) {
956
957                 ifs >> stype;
958                 if (!ifs) {
959                         break;
960
961                 }
962
963                 ifs >> sstatus;
964                 if (!ifs) {
965                         break;
966
967                 }
968
969                 /* rest of the line is the plugin ID */
970
971                 ifs.getline (buf, sizeof (buf), '\n');
972                 if (!ifs) {
973                         break;
974                 }
975
976                 if (sstatus == "Normal") {
977                         status = Normal;
978                 } else if (sstatus == "Favorite") {
979                         status = Favorite;
980                 } else if (sstatus == "Hidden") {
981                         status = Hidden;
982                 } else {
983                         error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
984                                   << endmsg;
985                         statuses.clear ();
986                         break;
987                 }
988
989                 if (stype == "LADSPA") {
990                         type = LADSPA;
991                 } else if (stype == "AudioUnit") {
992                         type = AudioUnit;
993                 } else if (stype == "LV2") {
994                         type = LV2;
995                 } else if (stype == "Windows-VST") {
996                         type = Windows_VST;
997                 } else if (stype == "LXVST") {
998                         type = LXVST;
999                 } else {
1000                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1001                               << endmsg;
1002                         continue;
1003                 }
1004
1005                 id = buf;
1006                 strip_whitespace_edges (id);
1007                 set_status (type, id, status);
1008         }
1009
1010         ifs.close ();
1011 }
1012
1013 void
1014 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1015 {
1016         PluginStatus ps (t, id, status);
1017         statuses.erase (ps);
1018
1019         if (status == Normal) {
1020                 return;
1021         }
1022
1023         statuses.insert (ps);
1024 }
1025
1026 ARDOUR::PluginInfoList&
1027 PluginManager::windows_vst_plugin_info ()
1028 {
1029 #ifdef WINDOWS_VST_SUPPORT
1030         if (!_windows_vst_plugin_info) {
1031                 windows_vst_refresh ();
1032         }
1033         return *_windows_vst_plugin_info;
1034 #else
1035         return _empty_plugin_info;
1036 #endif
1037 }
1038
1039 ARDOUR::PluginInfoList&
1040 PluginManager::lxvst_plugin_info ()
1041 {
1042 #ifdef LXVST_SUPPORT
1043         assert(_lxvst_plugin_info);
1044         return *_lxvst_plugin_info;
1045 #else
1046         return _empty_plugin_info;
1047 #endif
1048 }
1049
1050 ARDOUR::PluginInfoList&
1051 PluginManager::ladspa_plugin_info ()
1052 {
1053         assert(_ladspa_plugin_info);
1054         return *_ladspa_plugin_info;
1055 }
1056
1057 ARDOUR::PluginInfoList&
1058 PluginManager::lv2_plugin_info ()
1059 {
1060 #ifdef LV2_SUPPORT
1061         assert(_lv2_plugin_info);
1062         return *_lv2_plugin_info;
1063 #else
1064         return _empty_plugin_info;
1065 #endif
1066 }
1067
1068 ARDOUR::PluginInfoList&
1069 PluginManager::au_plugin_info ()
1070 {
1071 #ifdef AUDIOUNIT_SUPPORT
1072         assert(_au_plugin_info);
1073         return *_au_plugin_info;
1074 #else
1075         return _empty_plugin_info;
1076 #endif
1077 }