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