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