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