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