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