0dfd73e2721259b5b15c9b951afe50917aabfb44
[ardour.git] / libs / ardour / plugin_manager.cc
1 /*
2  * Copyright (C) 2000-2018 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
5  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2012-2015 Tim Mayberry <mojofunk@gmail.com>
7  * Copyright (C) 2014-2018 John Emmas <john@creativepost.co.uk>
8  * Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
9  * Copyright (C) 2018 Ben Loftis <ben@harrisonconsoles.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #ifdef WAF_BUILD
27 #include "libardour-config.h"
28 #endif
29
30 #include <stdint.h>
31
32 #include <sys/types.h>
33 #include <cstdio>
34 #include <cstdlib>
35
36 #include <glib.h>
37 #include "pbd/gstdio_compat.h"
38
39 #ifdef HAVE_LRDF
40 #include <lrdf.h>
41 #endif
42
43 #ifdef WINDOWS_VST_SUPPORT
44 #include "ardour/vst_info_file.h"
45 #include "fst.h"
46 #include "pbd/basename.h"
47 #include <cstring>
48
49 // dll-info
50 #include <sys/stat.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <stdint.h>
54
55 #endif // WINDOWS_VST_SUPPORT
56
57 #ifdef LXVST_SUPPORT
58 #include "ardour/vst_info_file.h"
59 #include "ardour/linux_vst_support.h"
60 #include "pbd/basename.h"
61 #include <cstring>
62 #endif //LXVST_SUPPORT
63
64 #ifdef MACVST_SUPPORT
65 #include "ardour/vst_info_file.h"
66 #include "ardour/mac_vst_support.h"
67 #include "ardour/mac_vst_plugin.h"
68 #include "pbd/basename.h"
69 #include "pbd/pathexpand.h"
70 #include <cstring>
71 #endif //MACVST_SUPPORT
72
73 #include <glibmm/miscutils.h>
74 #include <glibmm/pattern.h>
75 #include <glibmm/fileutils.h>
76 #include <glibmm/miscutils.h>
77
78 #include "pbd/convert.h"
79 #include "pbd/file_utils.h"
80 #include "pbd/tokenizer.h"
81 #include "pbd/whitespace.h"
82
83 #include "ardour/directory_names.h"
84 #include "ardour/debug.h"
85 #include "ardour/filesystem_paths.h"
86 #include "ardour/ladspa.h"
87 #include "ardour/ladspa_plugin.h"
88 #include "ardour/luascripting.h"
89 #include "ardour/luaproc.h"
90 #include "ardour/plugin.h"
91 #include "ardour/plugin_manager.h"
92 #include "ardour/rc_configuration.h"
93
94 #include "ardour/search_paths.h"
95
96 #ifdef LV2_SUPPORT
97 #include "ardour/lv2_plugin.h"
98 #endif
99
100 #ifdef WINDOWS_VST_SUPPORT
101 #include "ardour/windows_vst_plugin.h"
102 #endif
103
104 #ifdef LXVST_SUPPORT
105 #include "ardour/lxvst_plugin.h"
106 #endif
107
108 #ifdef AUDIOUNIT_SUPPORT
109 #include "ardour/audio_unit.h"
110 #include <Carbon/Carbon.h>
111 #endif
112
113 #include "pbd/error.h"
114 #include "pbd/stl_delete.h"
115
116 #include "pbd/i18n.h"
117
118 #include "ardour/debug.h"
119
120 using namespace ARDOUR;
121 using namespace PBD;
122 using namespace std;
123
124 PluginManager* PluginManager::_instance = 0;
125 std::string PluginManager::scanner_bin_path = "";
126
127 PluginManager&
128 PluginManager::instance()
129 {
130         if (!_instance) {
131                 _instance = new PluginManager;
132         }
133         return *_instance;
134 }
135
136 PluginManager::PluginManager ()
137         : _windows_vst_plugin_info(0)
138         , _lxvst_plugin_info(0)
139         , _mac_vst_plugin_info(0)
140         , _ladspa_plugin_info(0)
141         , _lv2_plugin_info(0)
142         , _au_plugin_info(0)
143         , _lua_plugin_info(0)
144         , _cancel_scan(false)
145         , _cancel_timeout(false)
146 {
147         char* s;
148         string lrdf_path;
149
150 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
151         // source-tree (ardev, etc)
152         PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
153
154 #ifdef PLATFORM_WINDOWS
155         // on windows the .exe needs to be in the same folder with libardour.dll
156         vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
157 #else
158         // on Unices additional internal-use binaries are deployed to $libdir
159         vstsp += ARDOUR::ardour_dll_directory();
160 #endif
161
162         if (!PBD::find_file (vstsp,
163 #ifdef PLATFORM_WINDOWS
164     #ifdef DEBUGGABLE_SCANNER_APP
165         #if defined(DEBUG) || defined(_DEBUG)
166                                 "ardour-vst-scannerD.exe"
167         #else
168                                 "ardour-vst-scannerRDC.exe"
169         #endif
170     #else
171                                 "ardour-vst-scanner.exe"
172     #endif
173 #else
174                                 "ardour-vst-scanner"
175 #endif
176                                 , scanner_bin_path)) {
177                 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
178         }
179 #endif
180
181         load_statuses ();
182
183         load_tags ();
184
185         if ((s = getenv ("LADSPA_RDF_PATH"))){
186                 lrdf_path = s;
187         }
188
189         if (lrdf_path.length() == 0) {
190                 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
191         }
192
193         add_lrdf_data(lrdf_path);
194         add_ladspa_presets();
195 #ifdef WINDOWS_VST_SUPPORT
196         if (Config->get_use_windows_vst ()) {
197                 add_windows_vst_presets ();
198         }
199 #endif /* WINDOWS_VST_SUPPORT */
200
201 #ifdef LXVST_SUPPORT
202         if (Config->get_use_lxvst()) {
203                 add_lxvst_presets();
204         }
205 #endif /* Native LinuxVST support*/
206
207 #ifdef MACVST_SUPPORT
208         if (Config->get_use_macvst ()) {
209                 add_mac_vst_presets ();
210         }
211 #endif
212
213         if ((s = getenv ("VST_PATH"))) {
214                 windows_vst_path = s;
215         } else if ((s = getenv ("VST_PLUGINS"))) {
216                 windows_vst_path = s;
217         }
218
219         if (windows_vst_path.length() == 0) {
220                 windows_vst_path = vst_search_path ();
221         }
222
223         if ((s = getenv ("LXVST_PATH"))) {
224                 lxvst_path = s;
225         } else if ((s = getenv ("LXVST_PLUGINS"))) {
226                 lxvst_path = s;
227         }
228
229         if (lxvst_path.length() == 0) {
230                 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
231                         "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
232                         "/usr/lib/vst:/usr/local/lib/vst";
233         }
234
235         /* first time setup, use 'default' path */
236         if (Config->get_plugin_path_lxvst() == X_("@default@")) {
237                 Config->set_plugin_path_lxvst(get_default_lxvst_path());
238         }
239         if (Config->get_plugin_path_vst() == X_("@default@")) {
240                 Config->set_plugin_path_vst(get_default_windows_vst_path());
241         }
242
243         if (_instance == 0) {
244                 _instance = this;
245         }
246
247         BootMessage (_("Discovering Plugins"));
248
249         LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
250 }
251
252
253 PluginManager::~PluginManager()
254 {
255         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
256                 // don't bother, just exit quickly.
257                 delete _windows_vst_plugin_info;
258                 delete _lxvst_plugin_info;
259                 delete _mac_vst_plugin_info;
260                 delete _ladspa_plugin_info;
261                 delete _lv2_plugin_info;
262                 delete _au_plugin_info;
263                 delete _lua_plugin_info;
264         }
265 }
266
267 void
268 PluginManager::refresh (bool cache_only)
269 {
270         Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
271
272         if (!lm.locked()) {
273                 return;
274         }
275
276         DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
277         _cancel_scan = false;
278
279         BootMessage (_("Scanning LADSPA Plugins"));
280         ladspa_refresh ();
281         BootMessage (_("Scanning Lua DSP Processors"));
282         lua_refresh ();
283 #ifdef LV2_SUPPORT
284         BootMessage (_("Scanning LV2 Plugins"));
285         lv2_refresh ();
286
287         if (Config->get_conceal_lv1_if_lv2_exists()) {
288                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
289                         for (PluginInfoList::const_iterator j = _lv2_plugin_info->begin(); j != _lv2_plugin_info->end(); ++j) {
290                                 if ((*i)->creator == (*j)->creator && (*i)->name == (*j)->name) {
291                                         PluginStatus ps (LADSPA, (*i)->unique_id, Concealed);
292                                         if (find (statuses.begin(), statuses.end(), ps) == statuses.end()) {
293                                                 statuses.erase (ps);
294                                                 statuses.insert (ps);
295                                         }
296                                 }
297                         }
298                 }
299         } else {
300                 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end();) {
301                         PluginStatusList::iterator j = i++;
302                         if ((*j).status == Concealed) {
303                                 statuses.erase (j);
304                         }
305                 }
306         }
307 #endif
308 #ifdef WINDOWS_VST_SUPPORT
309         if (Config->get_use_windows_vst()) {
310                 if (cache_only) {
311                         BootMessage (_("Scanning Windows VST Plugins"));
312                 } else {
313                         BootMessage (_("Discovering Windows VST Plugins"));
314                 }
315                 windows_vst_refresh (cache_only);
316         }
317 #endif // WINDOWS_VST_SUPPORT
318
319 #ifdef LXVST_SUPPORT
320         if(Config->get_use_lxvst()) {
321                 if (cache_only) {
322                         BootMessage (_("Scanning Linux VST Plugins"));
323                 } else {
324                         BootMessage (_("Discovering Linux VST Plugins"));
325                 }
326                 lxvst_refresh(cache_only);
327         }
328 #endif //Native linuxVST SUPPORT
329
330 #ifdef MACVST_SUPPORT
331         if(Config->get_use_macvst ()) {
332                 if (cache_only) {
333                         BootMessage (_("Scanning Mac VST Plugins"));
334                 } else {
335                         BootMessage (_("Discovering Mac VST Plugins"));
336                 }
337                 mac_vst_refresh (cache_only);
338         } else if (_mac_vst_plugin_info) {
339                 _mac_vst_plugin_info->clear ();
340         } else {
341                 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
342         }
343 #endif //Native Mac VST SUPPORT
344
345 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
346                 if (!cache_only) {
347                         string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
348                         if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
349                                 gchar *bl = NULL;
350                                 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
351                                         if (Config->get_verbose_plugin_scan()) {
352                                                 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
353                                         } else {
354                                                 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
355                                         }
356                                         g_free (bl);
357                                 }
358                         }
359                 }
360 #endif
361
362 #ifdef AUDIOUNIT_SUPPORT
363         if (cache_only) {
364                 BootMessage (_("Scanning AU Plugins"));
365         } else {
366                 BootMessage (_("Discovering AU Plugins"));
367         }
368         au_refresh (cache_only);
369 #endif
370
371         BootMessage (_("Plugin Scan Complete..."));
372         PluginListChanged (); /* EMIT SIGNAL */
373         PluginScanMessage(X_("closeme"), "", false);
374         _cancel_scan = false;
375 }
376
377 void
378 PluginManager::cancel_plugin_scan ()
379 {
380         _cancel_scan = true;
381 }
382
383 void
384 PluginManager::cancel_plugin_timeout ()
385 {
386         _cancel_timeout = true;
387 }
388
389 void
390 PluginManager::clear_vst_cache ()
391 {
392 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
393 #ifdef WINDOWS_VST_SUPPORT
394         {
395                 vector<string> fsi_files;
396                 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
397                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
398                         ::g_unlink(i->c_str());
399                 }
400         }
401         {
402                 vector<string> fsi_files;
403                 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
404                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
405                         ::g_unlink(i->c_str());
406                 }
407         }
408         {
409                 vector<string> fsi_files;
410                 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
411                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
412                         ::g_unlink(i->c_str());
413                 }
414         }
415 #endif
416
417 #ifdef LXVST_SUPPORT
418         {
419                 vector<string> fsi_files;
420                 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
421                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
422                         ::g_unlink(i->c_str());
423                 }
424         }
425         {
426                 vector<string> fsi_files;
427                 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
428                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
429                         ::g_unlink(i->c_str());
430                 }
431         }
432         {
433                 vector<string> fsi_files;
434                 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
435                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
436                         ::g_unlink(i->c_str());
437                 }
438         }
439 #endif
440 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
441         {
442                 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
443                 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
444                         PBD::remove_directory (dir);
445                 }
446         }
447 #endif
448 #endif // old cache cleanup
449
450 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
451         {
452                 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
453                 vector<string> fsi_files;
454                 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
455                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
456                         ::g_unlink(i->c_str());
457                 }
458         }
459 #endif
460 }
461
462 void
463 PluginManager::clear_vst_blacklist ()
464 {
465 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
466
467 #ifdef WINDOWS_VST_SUPPORT
468         {
469                 vector<string> fsi_files;
470                 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
471                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
472                         ::g_unlink(i->c_str());
473                 }
474         }
475 #endif
476
477 #ifdef LXVST_SUPPORT
478         {
479                 vector<string> fsi_files;
480                 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
481                 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
482                         ::g_unlink(i->c_str());
483                 }
484         }
485 #endif
486 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
487         {
488                 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
489                 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
490                         PBD::remove_directory (dir);
491                 }
492         }
493 #endif
494
495 #endif // old blacklist cleanup
496
497 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
498         {
499                 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
500                 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
501                         ::g_unlink (fn.c_str());
502                 }
503         }
504 #endif
505
506 }
507
508 void
509 PluginManager::clear_au_cache ()
510 {
511 #ifdef AUDIOUNIT_SUPPORT
512         AUPluginInfo::clear_cache ();
513 #endif
514 }
515
516 void
517 PluginManager::clear_au_blacklist ()
518 {
519 #ifdef AUDIOUNIT_SUPPORT
520         string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
521         if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
522                 ::g_unlink(fn.c_str());
523         }
524 #endif
525 }
526
527 void
528 PluginManager::lua_refresh ()
529 {
530         if (_lua_plugin_info) {
531                 _lua_plugin_info->clear ();
532         } else {
533                 _lua_plugin_info = new ARDOUR::PluginInfoList ();
534         }
535         ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
536         for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
537                 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
538                 _lua_plugin_info->push_back (lpi);
539                 set_tags (lpi->type, lpi->unique_id, lpi->category, lpi->name, FromPlug);
540         }
541 }
542
543 void
544 PluginManager::lua_refresh_cb ()
545 {
546         Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
547         if (!lm.locked()) {
548                 return;
549         }
550         lua_refresh ();
551         PluginListChanged (); /* EMIT SIGNAL */
552 }
553
554 void
555 PluginManager::ladspa_refresh ()
556 {
557         if (_ladspa_plugin_info) {
558                 _ladspa_plugin_info->clear ();
559         } else {
560                 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
561         }
562
563         /* allow LADSPA_PATH to augment, not override standard locations */
564
565         /* Only add standard locations to ladspa_path if it doesn't
566          * already contain them. Check for trailing G_DIR_SEPARATOR too.
567          */
568
569         vector<string> ladspa_modules;
570
571         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
572
573         find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
574         find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
575         find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
576
577         for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
578                 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
579                 ladspa_discover (*i);
580         }
581 }
582
583 #ifdef HAVE_LRDF
584 static bool rdf_filter (const string &str, void* /*arg*/)
585 {
586         return str[0] != '.' &&
587                    ((str.find(".rdf")  == (str.length() - 4)) ||
588             (str.find(".rdfs") == (str.length() - 5)) ||
589                     (str.find(".n3")   == (str.length() - 3)) ||
590                     (str.find(".ttl")  == (str.length() - 4)));
591 }
592 #endif
593
594 void
595 PluginManager::add_ladspa_presets()
596 {
597         add_presets ("ladspa");
598 }
599
600 void
601 PluginManager::add_windows_vst_presets()
602 {
603         add_presets ("windows-vst");
604 }
605
606 void
607 PluginManager::add_mac_vst_presets()
608 {
609         add_presets ("mac-vst");
610 }
611
612 void
613 PluginManager::add_lxvst_presets()
614 {
615         add_presets ("lxvst");
616 }
617
618 void
619 PluginManager::add_presets(string domain)
620 {
621 #ifdef HAVE_LRDF
622         vector<string> presets;
623         vector<string>::iterator x;
624
625         char* envvar;
626         if ((envvar = getenv ("HOME")) == 0) {
627                 return;
628         }
629
630         string path = string_compose("%1/.%2/rdf", envvar, domain);
631         find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
632
633         for (x = presets.begin(); x != presets.end (); ++x) {
634                 string file = "file:" + *x;
635                 if (lrdf_read_file(file.c_str())) {
636                         warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
637                 }
638         }
639
640 #endif
641 }
642
643 void
644 PluginManager::add_lrdf_data (const string &path)
645 {
646 #ifdef HAVE_LRDF
647         vector<string> rdf_files;
648         vector<string>::iterator x;
649
650         find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
651
652         for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
653                 const string uri(string("file://") + *x);
654
655                 if (lrdf_read_file(uri.c_str())) {
656                         warning << "Could not parse rdf file: " << uri << endmsg;
657                 }
658         }
659 #endif
660 }
661
662 int
663 PluginManager::ladspa_discover (string path)
664 {
665         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
666
667         Glib::Module module (path);
668         const LADSPA_Descriptor *descriptor;
669         LADSPA_Descriptor_Function dfunc;
670         void* func = 0;
671
672         if (!module) {
673                 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
674                         path, Glib::Module::get_last_error()) << endmsg;
675                 return -1;
676         }
677
678
679         if (!module.get_symbol("ladspa_descriptor", func)) {
680                 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
681                 error << Glib::Module::get_last_error() << endmsg;
682                 return -1;
683         }
684
685         dfunc = (LADSPA_Descriptor_Function)func;
686
687         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
688
689         for (uint32_t i = 0; ; ++i) {
690                 /* if a ladspa plugin allocates memory here
691                  * it is never free()ed (or plugin-dependent only when unloading).
692                  * For some plugins memory allocated is incremental, we should
693                  * avoid re-scanning plugins and file bug reports.
694                  */
695                 if ((descriptor = dfunc (i)) == 0) {
696                         break;
697                 }
698
699                 if (!ladspa_plugin_whitelist.empty()) {
700                         if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
701                                 continue;
702                         }
703                 }
704
705                 PluginInfoPtr info(new LadspaPluginInfo);
706                 info->name = descriptor->Name;
707                 info->category = get_ladspa_category(descriptor->UniqueID);
708                 info->path = path;
709                 info->index = i;
710                 info->n_inputs = ChanCount();
711                 info->n_outputs = ChanCount();
712                 info->type = ARDOUR::LADSPA;
713
714                 string::size_type pos = 0;
715                 string creator = descriptor->Maker;
716                 /* stupid LADSPA creator strings */
717 #ifdef PLATFORM_WINDOWS
718                 while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
719 #else
720                 while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
721 #endif
722
723                 /* If there were too few characters to create a
724                  * meaningful name, mark this creator as 'Unknown'
725                  */
726                 if (creator.length() < 2 || pos < 3) {
727                         info->creator = "Unknown";
728                 } else{
729                         info->creator = creator.substr (0, pos);
730                         strip_whitespace_edges (info->creator);
731                 }
732
733                 char buf[32];
734                 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
735                 info->unique_id = buf;
736
737                 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
738                         if (LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n])) {
739                                 if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n])) {
740                                         info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
741                                 }
742                                 else if (LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n])) {
743                                         info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
744                                 }
745                         }
746                 }
747
748                 if(_ladspa_plugin_info->empty()){
749                         _ladspa_plugin_info->push_back (info);
750                 }
751
752                 //Ensure that the plugin is not already in the plugin list.
753
754                 bool found = false;
755
756                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
757                         if(0 == info->unique_id.compare((*i)->unique_id)){
758                                 found = true;
759                         }
760                 }
761
762                 if(!found){
763                         _ladspa_plugin_info->push_back (info);
764                         set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
765                 }
766
767                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
768         }
769
770         return 0;
771 }
772
773 string
774 PluginManager::get_ladspa_category (uint32_t plugin_id)
775 {
776 #ifdef HAVE_LRDF
777         char buf[256];
778         lrdf_statement pattern;
779
780         snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
781         pattern.subject = buf;
782         pattern.predicate = const_cast<char*>(RDF_TYPE);
783         pattern.object = 0;
784         pattern.object_type = lrdf_uri;
785
786         lrdf_statement* matches1 = lrdf_matches (&pattern);
787
788         if (!matches1) {
789                 return "Unknown";
790         }
791
792         pattern.subject = matches1->object;
793         pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
794         pattern.object = 0;
795         pattern.object_type = lrdf_literal;
796
797         lrdf_statement* matches2 = lrdf_matches (&pattern);
798         lrdf_free_statements(matches1);
799
800         if (!matches2) {
801                 return ("Unknown");
802         }
803
804         string label = matches2->object;
805         lrdf_free_statements(matches2);
806
807         /* Kludge LADSPA class names to be singular and match LV2 class names.
808            This avoids duplicate plugin menus for every class, which is necessary
809            to make the plugin category menu at all usable, but is obviously a
810            filthy kludge.
811
812            In the short term, lrdf could be updated so the labels match and a new
813            release made. To support both specs, we should probably be mapping the
814            URIs to the same category in code and perhaps tweaking that hierarchy
815            dynamically to suit the user. Personally, I (drobilla) think that time
816            is better spent replacing the little-used LRDF.
817
818            In the longer term, we will abandon LRDF entirely in favour of LV2 and
819            use that class hierarchy. Aside from fixing this problem properly, that
820            will also allow for translated labels. SWH plugins have been LV2 for
821            ages; TAP needs porting. I don't know of anything else with LRDF data.
822         */
823         if (label == "Utilities") {
824                 return "Utility";
825         } else if (label == "Pitch shifters") {
826                 return "Pitch Shifter";
827         } else if (label != "Dynamics" && label != "Chorus"
828                    &&label[label.length() - 1] == 's'
829                    && label[label.length() - 2] != 's') {
830                 return label.substr(0, label.length() - 1);
831         } else {
832                 return label;
833         }
834 #else
835                 return ("Unknown");
836 #endif
837 }
838
839 #ifdef LV2_SUPPORT
840 void
841 PluginManager::lv2_refresh ()
842 {
843         DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
844         delete _lv2_plugin_info;
845         _lv2_plugin_info = LV2PluginInfo::discover();
846
847         for (PluginInfoList::iterator i = _lv2_plugin_info->begin(); i != _lv2_plugin_info->end(); ++i) {
848                 set_tags ((*i)->type, (*i)->unique_id, (*i)->category, (*i)->name, FromPlug);
849         }
850 }
851 #endif
852
853 #ifdef AUDIOUNIT_SUPPORT
854 void
855 PluginManager::au_refresh (bool cache_only)
856 {
857         DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
858
859         // disable automatic discovery in case we crash
860         bool discover_at_start = Config->get_discover_audio_units ();
861         Config->set_discover_audio_units (false);
862         Config->save_state();
863
864         delete _au_plugin_info;
865         _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
866
867         // successful scan re-enabled automatic discovery if it was set
868         Config->set_discover_audio_units (discover_at_start);
869         Config->save_state();
870
871         for (PluginInfoList::iterator i = _au_plugin_info->begin(); i != _au_plugin_info->end(); ++i) {
872                 set_tags ((*i)->type, (*i)->unique_id, (*i)->category, (*i)->name, FromPlug);
873         }
874 }
875
876 #endif
877
878 #ifdef WINDOWS_VST_SUPPORT
879
880 void
881 PluginManager::windows_vst_refresh (bool cache_only)
882 {
883         if (_windows_vst_plugin_info) {
884                 _windows_vst_plugin_info->clear ();
885         } else {
886                 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
887         }
888
889         windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
890 }
891
892 static bool windows_vst_filter (const string& str, void * /*arg*/)
893 {
894         /* Not a dotfile, has a prefix before a period, suffix is "dll" */
895         return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
896 }
897
898 int
899 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
900 {
901         vector<string> plugin_objects;
902         vector<string>::iterator x;
903         int ret = 0;
904
905         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
906
907         if (Session::get_disable_all_loaded_plugins ()) {
908                 info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
909                 return -1;
910         }
911
912         if (Config->get_verbose_plugin_scan()) {
913                 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
914         }
915
916         find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
917
918         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
919                 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
920                 windows_vst_discover (*x, cache_only || cancelled());
921         }
922
923         if (Config->get_verbose_plugin_scan()) {
924                 info << _("--- Windows VST plugins Scan Done") << endmsg;
925         }
926
927         return ret;
928 }
929
930 static std::string dll_info (std::string path) {
931         std::string rv;
932         uint8_t buf[68];
933         uint16_t type = 0;
934         off_t pe_hdr_off = 0;
935
936         int fd = g_open(path.c_str(), O_RDONLY, 0444);
937
938         if (fd < 0) {
939                 return _("cannot open dll"); // TODO strerror()
940         }
941
942         if (68 != read (fd, buf, 68)) {
943                 rv = _("invalid dll, file too small");
944                 goto errorout;
945         }
946         if (buf[0] != 'M' && buf[1] != 'Z') {
947                 rv = _("not a dll");
948                 goto errorout;
949         }
950
951         pe_hdr_off = *((int32_t*) &buf[60]);
952         if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
953                 rv = _("cannot determine dll type");
954                 goto errorout;
955         }
956         if (6 != read (fd, buf, 6)) {
957                 rv = _("cannot read dll PE header");
958                 goto errorout;
959         }
960
961         if (buf[0] != 'P' && buf[1] != 'E') {
962                 rv = _("invalid dll PE header");
963                 goto errorout;
964         }
965
966         type = *((uint16_t*) &buf[4]);
967         switch (type) {
968                 case 0x014c:
969                         rv = _("i386 (32-bit)");
970                         break;
971                 case  0x0200:
972                         rv = _("Itanium");
973                         break;
974                 case 0x8664:
975                         rv = _("x64 (64-bit)");
976                         break;
977                 case 0:
978                         rv = _("Native Architecture");
979                         break;
980                 default:
981                         rv = _("Unknown Architecture");
982                         break;
983         }
984 errorout:
985         assert (rv.length() > 0);
986         close (fd);
987         return rv;
988 }
989
990 int
991 PluginManager::windows_vst_discover (string path, bool cache_only)
992 {
993         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
994
995         if (Config->get_verbose_plugin_scan()) {
996                 if (cache_only) {
997                         info << string_compose (_(" *  %1 (cache only)"), path) << endmsg;
998                 } else {
999                         info << string_compose (_(" *  %1 - %2"), path, dll_info (path)) << endmsg;
1000                 }
1001         }
1002
1003         _cancel_timeout = false;
1004         vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
1005                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1006
1007         // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
1008         // .err file scanner output etc.
1009
1010         if (finfos->empty()) {
1011                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
1012                 if (Config->get_verbose_plugin_scan()) {
1013                         info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
1014                 }
1015                 return -1;
1016         }
1017
1018         uint32_t discovered = 0;
1019         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1020                 VSTInfo* finfo = *x;
1021
1022                 if (!finfo->canProcessReplacing) {
1023                         warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
1024                                                          finfo->name, PROGRAM_NAME)
1025                                 << endl;
1026                         continue;
1027                 }
1028
1029                 PluginInfoPtr info (new WindowsVSTPluginInfo (finfo));
1030                 info->path = path;
1031
1032                 /* what a joke freeware VST is */
1033                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1034                         info->name = PBD::basename_nosuffix (path);
1035                 }
1036
1037                 /* if we don't have any tags for this plugin, make some up. */
1038                 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1039
1040                 // TODO: check dup-IDs (lxvst AND windows vst)
1041                 bool duplicate = false;
1042
1043                 if (!_windows_vst_plugin_info->empty()) {
1044                         for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
1045                                 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
1046                                         warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1047                                         duplicate = true;
1048                                         break;
1049                                 }
1050                         }
1051                 }
1052
1053                 if (!duplicate) {
1054                         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1055                         _windows_vst_plugin_info->push_back (info);
1056                         discovered++;
1057                         if (Config->get_verbose_plugin_scan()) {
1058                                 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1059                         }
1060                 }
1061         }
1062
1063         vstfx_free_info_list (finfos);
1064         return discovered > 0 ? 0 : -1;
1065 }
1066
1067 #endif // WINDOWS_VST_SUPPORT
1068
1069 #ifdef MACVST_SUPPORT
1070 void
1071 PluginManager::mac_vst_refresh (bool cache_only)
1072 {
1073         if (_mac_vst_plugin_info) {
1074                 _mac_vst_plugin_info->clear ();
1075         } else {
1076                 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1077         }
1078
1079         mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1080 }
1081
1082 static bool mac_vst_filter (const string& str)
1083 {
1084         string plist = Glib::build_filename (str, "Contents", "Info.plist");
1085         if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1086                 return false;
1087         }
1088         return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1089 }
1090
1091 int
1092 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1093 {
1094         if (Session::get_disable_all_loaded_plugins ()) {
1095                 info << _("Disabled MacVST scan (safe mode)") << endmsg;
1096                 return -1;
1097         }
1098
1099         Searchpath paths (path);
1100         /* customized version of run_functor_for_paths() */
1101         for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1102                 string expanded_path = path_expand (*i);
1103                 if (!Glib::file_test (expanded_path, Glib::FILE_TEST_IS_DIR)) continue;
1104                 try {
1105                         Glib::Dir dir(expanded_path);
1106                         for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
1107                                 string fullpath = Glib::build_filename (expanded_path, *di);
1108
1109                                 /* we're only interested in bundles */
1110                                 if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
1111                                         continue;
1112                                 }
1113
1114                                 if (mac_vst_filter (fullpath)) {
1115                                         ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled());
1116                                         mac_vst_discover (fullpath, cache_only || cancelled());
1117                                         continue;
1118                                 }
1119
1120                                 /* don't descend into AU bundles in the VST dir */
1121                                 if (fullpath[0] == '.' || (fullpath.length() > 10 && strings_equal_ignore_case (".component", fullpath.substr(fullpath.length() - 10)))) {
1122                                         continue;
1123                                 }
1124
1125                                 /* recurse */
1126                                 mac_vst_discover_from_path (fullpath, cache_only);
1127                         }
1128                 } catch (Glib::FileError& err) { }
1129         }
1130
1131         return 0;
1132 }
1133
1134 int
1135 PluginManager::mac_vst_discover (string path, bool cache_only)
1136 {
1137         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1138
1139         _cancel_timeout = false;
1140
1141         vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1142                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1143
1144         if (finfos->empty()) {
1145                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1146                 return -1;
1147         }
1148
1149         uint32_t discovered = 0;
1150         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1151                 VSTInfo* finfo = *x;
1152
1153                 if (!finfo->canProcessReplacing) {
1154                         warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1155                                                          finfo->name, PROGRAM_NAME)
1156                                 << endl;
1157                         continue;
1158                 }
1159
1160                 PluginInfoPtr info (new MacVSTPluginInfo (finfo));
1161                 info->path = path;
1162
1163                 /* if we don't have any tags for this plugin, make some up. */
1164                 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1165
1166                 bool duplicate = false;
1167                 if (!_mac_vst_plugin_info->empty()) {
1168                         for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1169                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1170                                         warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1171                                         duplicate = true;
1172                                         break;
1173                                 }
1174                         }
1175                 }
1176
1177                 if (!duplicate) {
1178                         _mac_vst_plugin_info->push_back (info);
1179                         discovered++;
1180                 }
1181         }
1182
1183         vstfx_free_info_list (finfos);
1184         return discovered > 0 ? 0 : -1;
1185 }
1186
1187 #endif // MAC_VST_SUPPORT
1188
1189 #ifdef LXVST_SUPPORT
1190
1191 void
1192 PluginManager::lxvst_refresh (bool cache_only)
1193 {
1194         if (_lxvst_plugin_info) {
1195                 _lxvst_plugin_info->clear ();
1196         } else {
1197                 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1198         }
1199
1200         lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1201 }
1202
1203 static bool lxvst_filter (const string& str, void *)
1204 {
1205         /* Not a dotfile, has a prefix before a period, suffix is "so" */
1206
1207         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1208 }
1209
1210 int
1211 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1212 {
1213         vector<string> plugin_objects;
1214         vector<string>::iterator x;
1215         int ret = 0;
1216
1217         if (Session::get_disable_all_loaded_plugins ()) {
1218                 info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
1219                 return -1;
1220         }
1221
1222 #ifndef NDEBUG
1223         (void) path;
1224 #endif
1225
1226         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1227
1228         find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1229
1230         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1231                 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1232                 lxvst_discover (*x, cache_only || cancelled());
1233         }
1234
1235         return ret;
1236 }
1237
1238 int
1239 PluginManager::lxvst_discover (string path, bool cache_only)
1240 {
1241         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1242
1243         _cancel_timeout = false;
1244         vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1245                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1246
1247         if (finfos->empty()) {
1248                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1249                 return -1;
1250         }
1251
1252         uint32_t discovered = 0;
1253         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1254                 VSTInfo* finfo = *x;
1255
1256                 if (!finfo->canProcessReplacing) {
1257                         warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1258                                                          finfo->name, PROGRAM_NAME)
1259                                 << endl;
1260                         continue;
1261                 }
1262
1263                 PluginInfoPtr info(new LXVSTPluginInfo (finfo));
1264                 info->path = path;
1265
1266                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1267                         info->name = PBD::basename_nosuffix (path);
1268                 }
1269
1270                 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1271
1272                 /* Make sure we don't find the same plugin in more than one place along
1273                  * the LXVST_PATH We can't use a simple 'find' because the path is included
1274                  * in the PluginInfo, and that is the one thing we can be sure MUST be
1275                  * different if a duplicate instance is found. So we just compare the type
1276                  * and unique ID (which for some VSTs isn't actually unique...)
1277                  */
1278
1279                 // TODO: check dup-IDs with windowsVST, too
1280                 bool duplicate = false;
1281                 if (!_lxvst_plugin_info->empty()) {
1282                         for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1283                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1284                                         warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1285                                         duplicate = true;
1286                                         break;
1287                                 }
1288                         }
1289                 }
1290
1291                 if (!duplicate) {
1292                         _lxvst_plugin_info->push_back (info);
1293                         discovered++;
1294                 }
1295         }
1296
1297         vstfx_free_info_list (finfos);
1298         return discovered > 0 ? 0 : -1;
1299 }
1300
1301 #endif // LXVST_SUPPORT
1302
1303
1304 PluginManager::PluginStatusType
1305 PluginManager::get_status (const PluginInfoPtr& pi) const
1306 {
1307         PluginStatus ps (pi->type, pi->unique_id);
1308         PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1309         if (i == statuses.end()) {
1310                 return Normal;
1311         } else {
1312                 return i->status;
1313         }
1314 }
1315
1316 void
1317 PluginManager::save_statuses ()
1318 {
1319         std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_statuses");
1320         stringstream ofs;
1321
1322         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1323                 if ((*i).status == Concealed) {
1324                         continue;
1325                 }
1326                 switch ((*i).type) {
1327                 case LADSPA:
1328                         ofs << "LADSPA";
1329                         break;
1330                 case AudioUnit:
1331                         ofs << "AudioUnit";
1332                         break;
1333                 case LV2:
1334                         ofs << "LV2";
1335                         break;
1336                 case Windows_VST:
1337                         ofs << "Windows-VST";
1338                         break;
1339                 case LXVST:
1340                         ofs << "LXVST";
1341                         break;
1342                 case MacVST:
1343                         ofs << "MacVST";
1344                         break;
1345                 case Lua:
1346                         ofs << "Lua";
1347                         break;
1348                 }
1349
1350                 ofs << ' ';
1351
1352                 switch ((*i).status) {
1353                 case Normal:
1354                         ofs << "Normal";
1355                         break;
1356                 case Favorite:
1357                         ofs << "Favorite";
1358                         break;
1359                 case Hidden:
1360                         ofs << "Hidden";
1361                         break;
1362                 case Concealed:
1363                         ofs << "Hidden";
1364                         assert (0);
1365                         break;
1366                 }
1367
1368                 ofs << ' ';
1369
1370                 ofs << (*i).unique_id;;
1371                 ofs << endl;
1372         }
1373         g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1374 }
1375
1376 void
1377 PluginManager::load_statuses ()
1378 {
1379         std::string path;
1380         find_file (plugin_metadata_search_path(), "plugin_statuses", path); // note: if no user folder is found, this will find the resources path
1381         gchar *fbuf = NULL;
1382         if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1383                 return;
1384         }
1385         stringstream ifs (fbuf);
1386         g_free (fbuf);
1387
1388         std::string stype;
1389         std::string sstatus;
1390         std::string id;
1391         PluginType type;
1392         PluginStatusType status;
1393         char buf[1024];
1394
1395         while (ifs) {
1396
1397                 ifs >> stype;
1398                 if (!ifs) {
1399                         break;
1400
1401                 }
1402
1403                 ifs >> sstatus;
1404                 if (!ifs) {
1405                         break;
1406                 }
1407
1408                 /* rest of the line is the plugin ID */
1409
1410                 ifs.getline (buf, sizeof (buf), '\n');
1411                 if (!ifs) {
1412                         break;
1413                 }
1414
1415                 if (sstatus == "Normal") {
1416                         status = Normal;
1417                 } else if (sstatus == "Favorite") {
1418                         status = Favorite;
1419                 } else if (sstatus == "Hidden") {
1420                         status = Hidden;
1421                 } else {
1422                         error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus) << endmsg;
1423                         statuses.clear ();
1424                         break;
1425                 }
1426
1427                 if (stype == "LADSPA") {
1428                         type = LADSPA;
1429                 } else if (stype == "AudioUnit") {
1430                         type = AudioUnit;
1431                 } else if (stype == "LV2") {
1432                         type = LV2;
1433                 } else if (stype == "Windows-VST") {
1434                         type = Windows_VST;
1435                 } else if (stype == "LXVST") {
1436                         type = LXVST;
1437                 } else if (stype == "MacVST") {
1438                         type = MacVST;
1439                 } else if (stype == "Lua") {
1440                         type = Lua;
1441                 } else {
1442                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1443                               << endmsg;
1444                         continue;
1445                 }
1446
1447                 id = buf;
1448                 strip_whitespace_edges (id);
1449                 set_status (type, id, status);
1450         }
1451 }
1452
1453 void
1454 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1455 {
1456         PluginStatus ps (t, id, status);
1457         statuses.erase (ps);
1458
1459         if (status != Normal && status != Concealed) {
1460                 statuses.insert (ps);
1461         }
1462
1463         PluginStatusChanged (t, id, status); /* EMIT SIGNAL */
1464 }
1465
1466 PluginType
1467 PluginManager::to_generic_vst (const PluginType t)
1468 {
1469         switch (t) {
1470                 case Windows_VST:
1471                 case LXVST:
1472                 case MacVST:
1473                         return LXVST;
1474                 default:
1475                         break;
1476         }
1477         return t;
1478 }
1479
1480 struct SortByTag {
1481         bool operator() (std::string a, std::string b) {
1482                 return a.compare (b) < 0;
1483         }
1484 };
1485
1486 vector<std::string>
1487 PluginManager::get_tags (const PluginInfoPtr& pi) const
1488 {
1489         vector<std::string> tags;
1490
1491         PluginTag ps (to_generic_vst(pi->type), pi->unique_id, "", "", FromPlug);
1492         PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1493         if (i != ptags.end ()) {
1494                 PBD::tokenize (i->tags, string(" "), std::back_inserter (tags), true);
1495                 SortByTag sorter;
1496                 sort (tags.begin(), tags.end(), sorter);
1497         }
1498         return tags;
1499 }
1500
1501 std::string
1502 PluginManager::get_tags_as_string (PluginInfoPtr const& pi) const
1503 {
1504         std::string ret;
1505
1506         vector<std::string> tags = get_tags(pi);
1507         for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1508                 if (t != tags.begin ()) {
1509                         ret.append(" ");
1510                 }
1511                 ret.append(*t);
1512         }
1513
1514         return ret;
1515 }
1516
1517 std::string
1518 PluginManager::user_plugin_metadata_dir () const
1519 {
1520         std::string dir = Glib::build_filename (user_config_directory(), plugin_metadata_dir_name);
1521         g_mkdir_with_parents (dir.c_str(), 0744);
1522         return dir;
1523 }
1524
1525 bool
1526 PluginManager::load_plugin_order_file (XMLNode &n) const
1527 {
1528         std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_order");
1529
1530         info << string_compose (_("Loading plugin order file %1"), path) << endmsg;
1531         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1532                 return false;
1533         }
1534
1535         XMLTree tree;
1536         if (tree.read (path)) {
1537                 n = *(tree.root());
1538                 return true;
1539         } else {
1540                 error << string_compose (_("Cannot parse Plugin Order info from %1"), path) << endmsg;
1541                 return false;
1542         }
1543 }
1544
1545
1546 void
1547 PluginManager::save_plugin_order_file (XMLNode &elem) const
1548 {
1549         std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_order");
1550
1551         info << string_compose (_("Saving plugin order file %1"), path) << endmsg;
1552
1553         XMLTree tree;
1554         tree.set_root (&elem);
1555         if (!tree.write (path)) {
1556                 error << string_compose (_("Could not save Plugin Order info to %1"), path) << endmsg;
1557         }
1558         tree.set_root (0); // note: must disconnect the elem from XMLTree, or it will try to delete memory it didn't allocate
1559 }
1560
1561
1562 void
1563 PluginManager::save_tags ()
1564 {
1565         std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_tags");
1566         XMLNode* root = new XMLNode (X_("PluginTags"));
1567
1568         for (PluginTagList::iterator i = ptags.begin(); i != ptags.end(); ++i) {
1569 #ifdef MIXBUS
1570                 if ((*i).type == LADSPA) {
1571                         uint32_t id = atoi ((*i).unique_id);
1572                         if (id >= 9300 && id <= 9399) {
1573                                 continue; /* do not write mixbus channelstrip ladspa's in the tagfile */
1574                         }
1575                 }
1576 #endif
1577                 if ((*i).tagtype == FromFactoryFile || (*i).tagtype == FromUserFile) {
1578                         /* user file should contain only plugins that are (a) newly user-tagged or (b) previously unknown */
1579                         continue;
1580                 }
1581                 XMLNode* node = new XMLNode (X_("Plugin"));
1582                 node->set_property (X_("type"), to_generic_vst ((*i).type));
1583                 node->set_property (X_("id"), (*i).unique_id);
1584                 node->set_property (X_("tags"), (*i).tags);
1585                 node->set_property (X_("name"), (*i).name);
1586                 if ((*i).tagtype >= FromUserFile) {
1587                         node->set_property (X_("user-set"), "1");
1588                 }
1589                 root->add_child_nocopy (*node);
1590         }
1591
1592         XMLTree tree;
1593         tree.set_root (root);
1594         if (!tree.write (path)) {
1595                 error << string_compose (_("Could not save Plugin Tags info to %1"), path) << endmsg;
1596         }
1597 }
1598
1599 void
1600 PluginManager::load_tags ()
1601 {
1602         vector<std::string> tmp;
1603         find_files_matching_pattern (tmp, plugin_metadata_search_path (), "plugin_tags");
1604
1605         for (vector<std::string>::const_reverse_iterator p = tmp.rbegin ();
1606                         p != (vector<std::string>::const_reverse_iterator)tmp.rend(); ++p) {
1607                 std::string path = *p;
1608                 info << string_compose (_("Loading plugin meta data file %1"), path) << endmsg;
1609                 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1610                         return;
1611                 }
1612
1613                 XMLTree tree;
1614                 if (!tree.read (path)) {
1615                         error << string_compose (_("Cannot parse plugin tag info from %1"), path) << endmsg;
1616                         return;
1617                 }
1618
1619                 for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) {
1620                         PluginType type;
1621                         string id;
1622                         string tags;
1623                         string name;
1624                         bool user_set;
1625                         if (!(*i)->get_property (X_("type"), type) ||
1626                                         !(*i)->get_property (X_("id"), id) ||
1627                                         !(*i)->get_property (X_("tags"), tags) ||
1628                                         !(*i)->get_property (X_("name"), name)) {
1629                         }
1630                         if (!(*i)->get_property (X_("user-set"), user_set)) {
1631                                 user_set = false;
1632                         }
1633                         strip_whitespace_edges (tags);
1634                         set_tags (type, id, tags, name, user_set ? FromUserFile : FromFactoryFile);
1635                 }
1636         }
1637 }
1638
1639 void
1640 PluginManager::set_tags (PluginType t, string id, string tag, std::string name, TagType ttype)
1641 {
1642         string sanitized = sanitize_tag (tag);
1643
1644         PluginTag ps (to_generic_vst (t), id, sanitized, name, ttype);
1645         PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1646         if (i == ptags.end()) {
1647                 ptags.insert (ps);
1648         } else if ((uint32_t) ttype >= (uint32_t) (*i).tagtype) { // only overwrite if we are more important than the existing. Gui > UserFile > FactoryFile > Plugin
1649                 ptags.erase (ps);
1650                 ptags.insert (ps);
1651         }
1652         if (ttype == FromGui) {
1653                 PluginTagChanged (t, id, sanitized); /* EMIT SIGNAL */
1654         }
1655 }
1656
1657 void
1658 PluginManager::reset_tags (PluginInfoPtr const& pi)
1659 {
1660         PluginTag ps (pi->type, pi->unique_id, pi->category, pi->name, FromPlug);
1661
1662         PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1663         if (i != ptags.end()) {
1664                 ptags.erase (ps);
1665                 ptags.insert (ps);
1666         }
1667 }
1668
1669 std::string
1670 PluginManager::sanitize_tag (const std::string to_sanitize) const
1671 {
1672         if (to_sanitize.empty ()) {
1673                 return "";
1674         }
1675         string sanitized = to_sanitize;
1676         vector<string> tags;
1677         if (!PBD::tokenize (sanitized, string(" ,\n"), std::back_inserter (tags), true)) {
1678 #ifndef NDEBUG
1679                 cerr << _("PluginManager::sanitize_tag could not tokenize string: ") << sanitized << endmsg;
1680 #endif
1681                 return "";
1682         }
1683
1684         /* convert tokens to lower-case, space-separated list */
1685         sanitized = "";
1686         for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1687                 if (t != tags.begin ()) {
1688                         sanitized.append(" ");
1689                 }
1690                 sanitized.append (downcase (*t));
1691         }
1692
1693         return sanitized;
1694 }
1695
1696 std::vector<std::string>
1697 PluginManager::get_all_tags (TagFilter tag_filter) const
1698 {
1699         std::vector<std::string> ret;
1700
1701         PluginTagList::const_iterator pt;
1702         for (pt = ptags.begin(); pt != ptags.end(); ++pt) {
1703                 if ((*pt).tags.empty ()) {
1704                         continue;
1705                 }
1706
1707                 /* if favorites_only then we need to check the info ptr and maybe skip */
1708                 if (tag_filter == OnlyFavorites) {
1709                         PluginStatus stat ((*pt).type, (*pt).unique_id);
1710                         PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), stat);
1711                         if ((i != statuses.end()) && (i->status == Favorite)) {
1712                                 /* it's a favorite! */
1713                         } else {
1714                                 continue;
1715                         }
1716                 }
1717                 if (tag_filter == NoHidden) {
1718                         PluginStatus stat ((*pt).type, (*pt).unique_id);
1719                         PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), stat);
1720                         if ((i != statuses.end()) && ((i->status == Hidden) || (i->status == Concealed))) {
1721                                 continue;
1722                         }
1723                 }
1724
1725                 /* parse each plugin's tag string into separate tags */
1726                 vector<string> tags;
1727                 if (!PBD::tokenize ((*pt).tags, string(" "), std::back_inserter (tags), true)) {
1728 #ifndef NDEBUG
1729                         cerr << _("PluginManager: Could not tokenize string: ") << (*pt).tags << endmsg;
1730 #endif
1731                         continue;
1732                 }
1733
1734                 /* maybe add the tags we've found */
1735                 for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1736                         /* if this tag isn't already in the list, add it */
1737                         vector<string>::iterator i = find (ret.begin(), ret.end(), *t);
1738                         if (i == ret.end()) {
1739                                 ret.push_back (*t);
1740                         }
1741                 }
1742         }
1743
1744         /* sort in alphabetical order */
1745         SortByTag sorter;
1746         sort (ret.begin(), ret.end(), sorter);
1747
1748         return ret;
1749 }
1750
1751
1752 const ARDOUR::PluginInfoList&
1753 PluginManager::windows_vst_plugin_info ()
1754 {
1755 #ifdef WINDOWS_VST_SUPPORT
1756         if (!_windows_vst_plugin_info) {
1757                 windows_vst_refresh ();
1758         }
1759         return *_windows_vst_plugin_info;
1760 #else
1761         return _empty_plugin_info;
1762 #endif
1763 }
1764
1765 const ARDOUR::PluginInfoList&
1766 PluginManager::mac_vst_plugin_info ()
1767 {
1768 #ifdef MACVST_SUPPORT
1769         assert(_mac_vst_plugin_info);
1770         return *_mac_vst_plugin_info;
1771 #else
1772         return _empty_plugin_info;
1773 #endif
1774 }
1775
1776 const ARDOUR::PluginInfoList&
1777 PluginManager::lxvst_plugin_info ()
1778 {
1779 #ifdef LXVST_SUPPORT
1780         assert(_lxvst_plugin_info);
1781         return *_lxvst_plugin_info;
1782 #else
1783         return _empty_plugin_info;
1784 #endif
1785 }
1786
1787 const ARDOUR::PluginInfoList&
1788 PluginManager::ladspa_plugin_info ()
1789 {
1790         assert(_ladspa_plugin_info);
1791         return *_ladspa_plugin_info;
1792 }
1793
1794 const ARDOUR::PluginInfoList&
1795 PluginManager::lv2_plugin_info ()
1796 {
1797 #ifdef LV2_SUPPORT
1798         assert(_lv2_plugin_info);
1799         return *_lv2_plugin_info;
1800 #else
1801         return _empty_plugin_info;
1802 #endif
1803 }
1804
1805 const ARDOUR::PluginInfoList&
1806 PluginManager::au_plugin_info ()
1807 {
1808 #ifdef AUDIOUNIT_SUPPORT
1809         if (_au_plugin_info) {
1810                 return *_au_plugin_info;
1811         }
1812 #endif
1813         return _empty_plugin_info;
1814 }
1815
1816 const ARDOUR::PluginInfoList&
1817 PluginManager::lua_plugin_info ()
1818 {
1819         assert(_lua_plugin_info);
1820         return *_lua_plugin_info;
1821 }