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