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