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