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