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