Conditionally remove possibly unused functions.
[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 #ifdef HAVE_LRDF
374 static bool rdf_filter (const string &str, void* /*arg*/)
375 {
376         return str[0] != '.' &&
377                    ((str.find(".rdf")  == (str.length() - 4)) ||
378             (str.find(".rdfs") == (str.length() - 5)) ||
379                     (str.find(".n3")   == (str.length() - 3)) ||
380                     (str.find(".ttl")  == (str.length() - 4)));
381 }
382 #endif
383
384 void
385 PluginManager::add_ladspa_presets()
386 {
387         add_presets ("ladspa");
388 }
389
390 void
391 PluginManager::add_windows_vst_presets()
392 {
393         add_presets ("windows-vst");
394 }
395
396 void
397 PluginManager::add_lxvst_presets()
398 {
399         add_presets ("lxvst");
400 }
401
402 void
403 PluginManager::add_presets(string domain)
404 {
405 #ifdef HAVE_LRDF
406         vector<string> presets;
407         vector<string>::iterator x;
408
409         char* envvar;
410         if ((envvar = getenv ("HOME")) == 0) {
411                 return;
412         }
413
414         string path = string_compose("%1/.%2/rdf", envvar, domain);
415         find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
416
417         for (x = presets.begin(); x != presets.end (); ++x) {
418                 string file = "file:" + *x;
419                 if (lrdf_read_file(file.c_str())) {
420                         warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
421                 }
422         }
423
424 #endif
425 }
426
427 void
428 PluginManager::add_lrdf_data (const string &path)
429 {
430 #ifdef HAVE_LRDF
431         vector<string> rdf_files;
432         vector<string>::iterator x;
433
434         find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
435
436         for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
437                 const string uri(string("file://") + *x);
438
439                 if (lrdf_read_file(uri.c_str())) {
440                         warning << "Could not parse rdf file: " << uri << endmsg;
441                 }
442         }
443 #endif
444 }
445
446 int
447 PluginManager::ladspa_discover (string path)
448 {
449         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
450
451         Glib::Module module(path);
452         const LADSPA_Descriptor *descriptor;
453         LADSPA_Descriptor_Function dfunc;
454         void* func = 0;
455
456         if (!module) {
457                 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
458                         path, Glib::Module::get_last_error()) << endmsg;
459                 return -1;
460         }
461
462
463         if (!module.get_symbol("ladspa_descriptor", func)) {
464                 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
465                 error << Glib::Module::get_last_error() << endmsg;
466                 return -1;
467         }
468
469         dfunc = (LADSPA_Descriptor_Function)func;
470
471         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
472
473         for (uint32_t i = 0; ; ++i) {
474                 if ((descriptor = dfunc (i)) == 0) {
475                         break;
476                 }
477
478                 if (!ladspa_plugin_whitelist.empty()) {
479                         if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
480                                 continue;
481                         }
482                 }
483
484                 PluginInfoPtr info(new LadspaPluginInfo);
485                 info->name = descriptor->Name;
486                 info->category = get_ladspa_category(descriptor->UniqueID);
487                 info->creator = descriptor->Maker;
488                 info->path = path;
489                 info->index = i;
490                 info->n_inputs = ChanCount();
491                 info->n_outputs = ChanCount();
492                 info->type = ARDOUR::LADSPA;
493
494                 char buf[32];
495                 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
496                 info->unique_id = buf;
497
498                 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
499                         if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
500                                 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
501                                         info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
502                                 }
503                                 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
504                                         info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
505                                 }
506                         }
507                 }
508
509                 if(_ladspa_plugin_info->empty()){
510                         _ladspa_plugin_info->push_back (info);
511                 }
512
513                 //Ensure that the plugin is not already in the plugin list.
514
515                 bool found = false;
516
517                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
518                         if(0 == info->unique_id.compare((*i)->unique_id)){
519                               found = true;
520                         }
521                 }
522
523                 if(!found){
524                     _ladspa_plugin_info->push_back (info);
525                 }
526
527                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
528         }
529
530 // GDB WILL NOT LIKE YOU IF YOU DO THIS
531 //      dlclose (module);
532
533         return 0;
534 }
535
536 string
537 PluginManager::get_ladspa_category (uint32_t plugin_id)
538 {
539 #ifdef HAVE_LRDF
540         char buf[256];
541         lrdf_statement pattern;
542
543         snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
544         pattern.subject = buf;
545         pattern.predicate = const_cast<char*>(RDF_TYPE);
546         pattern.object = 0;
547         pattern.object_type = lrdf_uri;
548
549         lrdf_statement* matches1 = lrdf_matches (&pattern);
550
551         if (!matches1) {
552                 return "Unknown";
553         }
554
555         pattern.subject = matches1->object;
556         pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
557         pattern.object = 0;
558         pattern.object_type = lrdf_literal;
559
560         lrdf_statement* matches2 = lrdf_matches (&pattern);
561         lrdf_free_statements(matches1);
562
563         if (!matches2) {
564                 return ("Unknown");
565         }
566
567         string label = matches2->object;
568         lrdf_free_statements(matches2);
569
570         /* Kludge LADSPA class names to be singular and match LV2 class names.
571            This avoids duplicate plugin menus for every class, which is necessary
572            to make the plugin category menu at all usable, but is obviously a
573            filthy kludge.
574
575            In the short term, lrdf could be updated so the labels match and a new
576            release made. To support both specs, we should probably be mapping the
577            URIs to the same category in code and perhaps tweaking that hierarchy
578            dynamically to suit the user. Personally, I (drobilla) think that time
579            is better spent replacing the little-used LRDF.
580
581            In the longer term, we will abandon LRDF entirely in favour of LV2 and
582            use that class hierarchy. Aside from fixing this problem properly, that
583            will also allow for translated labels. SWH plugins have been LV2 for
584            ages; TAP needs porting. I don't know of anything else with LRDF data.
585         */
586         if (label == "Utilities") {
587                 return "Utility";
588         } else if (label == "Pitch shifters") {
589                 return "Pitch Shifter";
590         } else if (label != "Dynamics" && label != "Chorus"
591                    &&label[label.length() - 1] == 's'
592                    && label[label.length() - 2] != 's') {
593                 return label.substr(0, label.length() - 1);
594         } else {
595                 return label;
596         }
597 #else
598                 return ("Unknown");
599 #endif
600 }
601
602 #ifdef LV2_SUPPORT
603 void
604 PluginManager::lv2_refresh ()
605 {
606         DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
607         delete _lv2_plugin_info;
608         _lv2_plugin_info = LV2PluginInfo::discover();
609 }
610 #endif
611
612 #ifdef AUDIOUNIT_SUPPORT
613 void
614 PluginManager::au_refresh (bool cache_only)
615 {
616         DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
617         if (cache_only && !Config->get_discover_audio_units ()) {
618                 return;
619         }
620         delete _au_plugin_info;
621
622         // disable automatic scan in case we crash
623         Config->set_discover_audio_units (false);
624         Config->save_state();
625
626         _au_plugin_info = AUPluginInfo::discover();
627
628         // successful scan re-enabled automatic discovery
629         Config->set_discover_audio_units (true);
630         Config->save_state();
631 }
632
633 #endif
634
635 #ifdef WINDOWS_VST_SUPPORT
636
637 void
638 PluginManager::windows_vst_refresh (bool cache_only)
639 {
640         if (_windows_vst_plugin_info) {
641                 _windows_vst_plugin_info->clear ();
642         } else {
643                 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
644         }
645
646         windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
647 }
648
649 static bool windows_vst_filter (const string& str, void * /*arg*/)
650 {
651         /* Not a dotfile, has a prefix before a period, suffix is "dll" */
652
653         return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
654 }
655
656 int
657 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
658 {
659         vector<string> plugin_objects;
660         vector<string>::iterator x;
661         int ret = 0;
662
663         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
664
665         find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
666
667         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
668                 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
669                 windows_vst_discover (*x, cache_only || cancelled());
670         }
671
672         return ret;
673 }
674
675 int
676 PluginManager::windows_vst_discover (string path, bool cache_only)
677 {
678         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
679
680         _cancel_timeout = false;
681         vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
682                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
683
684         if (finfos->empty()) {
685                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
686                 return -1;
687         }
688
689         uint32_t discovered = 0;
690         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
691                 VSTInfo* finfo = *x;
692                 char buf[32];
693
694                 if (!finfo->canProcessReplacing) {
695                         warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
696                                                          finfo->name, PROGRAM_NAME)
697                                 << endl;
698                         continue;
699                 }
700
701                 PluginInfoPtr info (new WindowsVSTPluginInfo);
702
703                 /* what a joke freeware VST is */
704
705                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
706                         info->name = PBD::basename_nosuffix (path);
707                 } else {
708                         info->name = finfo->name;
709                 }
710
711
712                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
713                 info->unique_id = buf;
714                 info->category = "VST";
715                 info->path = path;
716                 info->creator = finfo->creator;
717                 info->index = 0;
718                 info->n_inputs.set_audio (finfo->numInputs);
719                 info->n_outputs.set_audio (finfo->numOutputs);
720                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
721                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
722                 info->type = ARDOUR::Windows_VST;
723
724                 // TODO: check dup-IDs (lxvst AND windows vst)
725                 bool duplicate = false;
726
727                 if (!_windows_vst_plugin_info->empty()) {
728                         for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
729                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
730                                         warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
731                                         duplicate = true;
732                                         break;
733                                 }
734                         }
735                 }
736
737                 if (!duplicate) {
738                         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
739                         _windows_vst_plugin_info->push_back (info);
740                         discovered++;
741                 }
742         }
743
744         vstfx_free_info_list (finfos);
745         return discovered > 0 ? 0 : -1;
746 }
747
748 #endif // WINDOWS_VST_SUPPORT
749
750 #ifdef LXVST_SUPPORT
751
752 void
753 PluginManager::lxvst_refresh (bool cache_only)
754 {
755         if (_lxvst_plugin_info) {
756                 _lxvst_plugin_info->clear ();
757         } else {
758                 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
759         }
760
761         lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
762 }
763
764 static bool lxvst_filter (const string& str, void *)
765 {
766         /* Not a dotfile, has a prefix before a period, suffix is "so" */
767
768         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
769 }
770
771 int
772 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
773 {
774         vector<string> plugin_objects;
775         vector<string>::iterator x;
776         int ret = 0;
777
778 #ifndef NDEBUG
779         (void) path;
780 #endif
781
782         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
783
784         find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
785
786         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
787                 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
788                 lxvst_discover (*x, cache_only || cancelled());
789         }
790
791         return ret;
792 }
793
794 int
795 PluginManager::lxvst_discover (string path, bool cache_only)
796 {
797         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
798
799         _cancel_timeout = false;
800         vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
801                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
802
803         if (finfos->empty()) {
804                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
805                 return -1;
806         }
807
808         uint32_t discovered = 0;
809         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
810                 VSTInfo* finfo = *x;
811                 char buf[32];
812
813                 if (!finfo->canProcessReplacing) {
814                         warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
815                                                          finfo->name, PROGRAM_NAME)
816                                 << endl;
817                         continue;
818                 }
819
820                 PluginInfoPtr info(new LXVSTPluginInfo);
821
822                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
823                         info->name = PBD::basename_nosuffix (path);
824                 } else {
825                         info->name = finfo->name;
826                 }
827
828
829                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
830                 info->unique_id = buf;
831                 info->category = "linuxVSTs";
832                 info->path = path;
833                 info->creator = finfo->creator;
834                 info->index = 0;
835                 info->n_inputs.set_audio (finfo->numInputs);
836                 info->n_outputs.set_audio (finfo->numOutputs);
837                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
838                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
839                 info->type = ARDOUR::LXVST;
840
841                                         /* Make sure we don't find the same plugin in more than one place along
842                          the LXVST_PATH We can't use a simple 'find' because the path is included
843                          in the PluginInfo, and that is the one thing we can be sure MUST be
844                          different if a duplicate instance is found.  So we just compare the type
845                          and unique ID (which for some VSTs isn't actually unique...)
846                 */
847
848                 // TODO: check dup-IDs with windowsVST, too
849                 bool duplicate = false;
850                 if (!_lxvst_plugin_info->empty()) {
851                         for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
852                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
853                                         warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
854                                         duplicate = true;
855                                         break;
856                                 }
857                         }
858                 }
859
860                 if (!duplicate) {
861                         _lxvst_plugin_info->push_back (info);
862                         discovered++;
863                 }
864         }
865
866         vstfx_free_info_list (finfos);
867         return discovered > 0 ? 0 : -1;
868 }
869
870 #endif // LXVST_SUPPORT
871
872
873 PluginManager::PluginStatusType
874 PluginManager::get_status (const PluginInfoPtr& pi)
875 {
876         PluginStatus ps (pi->type, pi->unique_id);
877         PluginStatusList::const_iterator i =  find (statuses.begin(), statuses.end(), ps);
878         if (i ==  statuses.end() ) {
879                 return Normal;
880         } else {
881                 return i->status;
882         }
883 }
884
885 void
886 PluginManager::save_statuses ()
887 {
888         ofstream ofs;
889         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
890
891         ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
892
893         if (!ofs) {
894                 return;
895         }
896
897         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
898                 switch ((*i).type) {
899                 case LADSPA:
900                         ofs << "LADSPA";
901                         break;
902                 case AudioUnit:
903                         ofs << "AudioUnit";
904                         break;
905                 case LV2:
906                         ofs << "LV2";
907                         break;
908                 case Windows_VST:
909                         ofs << "Windows-VST";
910                         break;
911                 case LXVST:
912                         ofs << "LXVST";
913                         break;
914                 }
915
916                 ofs << ' ';
917
918                 switch ((*i).status) {
919                 case Normal:
920                         ofs << "Normal";
921                         break;
922                 case Favorite:
923                         ofs << "Favorite";
924                         break;
925                 case Hidden:
926                         ofs << "Hidden";
927                         break;
928                 }
929
930                 ofs << ' ';
931                 ofs << (*i).unique_id;;
932                 ofs << endl;
933         }
934
935         ofs.close ();
936 }
937
938 void
939 PluginManager::load_statuses ()
940 {
941         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
942         ifstream ifs (path.c_str());
943
944         if (!ifs) {
945                 return;
946         }
947
948         std::string stype;
949         std::string sstatus;
950         std::string id;
951         PluginType type;
952         PluginStatusType status;
953         char buf[1024];
954
955         while (ifs) {
956
957                 ifs >> stype;
958                 if (!ifs) {
959                         break;
960
961                 }
962
963                 ifs >> sstatus;
964                 if (!ifs) {
965                         break;
966
967                 }
968
969                 /* rest of the line is the plugin ID */
970
971                 ifs.getline (buf, sizeof (buf), '\n');
972                 if (!ifs) {
973                         break;
974                 }
975
976                 if (sstatus == "Normal") {
977                         status = Normal;
978                 } else if (sstatus == "Favorite") {
979                         status = Favorite;
980                 } else if (sstatus == "Hidden") {
981                         status = Hidden;
982                 } else {
983                         error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
984                                   << endmsg;
985                         statuses.clear ();
986                         break;
987                 }
988
989                 if (stype == "LADSPA") {
990                         type = LADSPA;
991                 } else if (stype == "AudioUnit") {
992                         type = AudioUnit;
993                 } else if (stype == "LV2") {
994                         type = LV2;
995                 } else if (stype == "Windows-VST") {
996                         type = Windows_VST;
997                 } else if (stype == "LXVST") {
998                         type = LXVST;
999                 } else {
1000                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1001                               << endmsg;
1002                         continue;
1003                 }
1004
1005                 id = buf;
1006                 strip_whitespace_edges (id);
1007                 set_status (type, id, status);
1008         }
1009
1010         ifs.close ();
1011 }
1012
1013 void
1014 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1015 {
1016         PluginStatus ps (t, id, status);
1017         statuses.erase (ps);
1018
1019         if (status == Normal) {
1020                 return;
1021         }
1022
1023         statuses.insert (ps);
1024 }
1025
1026 ARDOUR::PluginInfoList&
1027 PluginManager::windows_vst_plugin_info ()
1028 {
1029 #ifdef WINDOWS_VST_SUPPORT
1030         if (!_windows_vst_plugin_info) {
1031                 windows_vst_refresh ();
1032         }
1033         return *_windows_vst_plugin_info;
1034 #else
1035         return _empty_plugin_info;
1036 #endif
1037 }
1038
1039 ARDOUR::PluginInfoList&
1040 PluginManager::lxvst_plugin_info ()
1041 {
1042 #ifdef LXVST_SUPPORT
1043         assert(_lxvst_plugin_info);
1044         return *_lxvst_plugin_info;
1045 #else
1046         return _empty_plugin_info;
1047 #endif
1048 }
1049
1050 ARDOUR::PluginInfoList&
1051 PluginManager::ladspa_plugin_info ()
1052 {
1053         assert(_ladspa_plugin_info);
1054         return *_ladspa_plugin_info;
1055 }
1056
1057 ARDOUR::PluginInfoList&
1058 PluginManager::lv2_plugin_info ()
1059 {
1060 #ifdef LV2_SUPPORT
1061         assert(_lv2_plugin_info);
1062         return *_lv2_plugin_info;
1063 #else
1064         return _empty_plugin_info;
1065 #endif
1066 }
1067
1068 ARDOUR::PluginInfoList&
1069 PluginManager::au_plugin_info ()
1070 {
1071 #ifdef AUDIOUNIT_SUPPORT
1072         if (_au_plugin_info) {
1073                 return *_au_plugin_info;
1074         }
1075 #endif
1076         return _empty_plugin_info;
1077 }