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