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