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