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