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