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