Add a missing #define to our MSVC project (portaudio_backend)
[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 (Session::get_disable_all_loaded_plugins ()) {
850                 info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
851                 return -1;
852         }
853
854         if (Config->get_verbose_plugin_scan()) {
855                 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
856         }
857
858         find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
859
860         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
861                 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
862                 windows_vst_discover (*x, cache_only || cancelled());
863         }
864
865         if (Config->get_verbose_plugin_scan()) {
866                 info << _("--- Windows VST plugins Scan Done") << endmsg;
867         }
868
869         return ret;
870 }
871
872 static std::string dll_info (std::string path) {
873         std::string rv;
874         uint8_t buf[68];
875         uint16_t type = 0;
876         off_t pe_hdr_off = 0;
877
878         int fd = g_open(path.c_str(), O_RDONLY, 0444);
879
880         if (fd < 0) {
881                 return _("cannot open dll"); // TODO strerror()
882         }
883
884         if (68 != read (fd, buf, 68)) {
885                 rv = _("invalid dll, file too small");
886                 goto errorout;
887         }
888         if (buf[0] != 'M' && buf[1] != 'Z') {
889                 rv = _("not a dll");
890                 goto errorout;
891         }
892
893         pe_hdr_off = *((int32_t*) &buf[60]);
894         if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
895                 rv = _("cannot determine dll type");
896                 goto errorout;
897         }
898         if (6 != read (fd, buf, 6)) {
899                 rv = _("cannot read dll PE header");
900                 goto errorout;
901         }
902
903         if (buf[0] != 'P' && buf[1] != 'E') {
904                 rv = _("invalid dll PE header");
905                 goto errorout;
906         }
907
908         type = *((uint16_t*) &buf[4]);
909         switch (type) {
910                 case 0x014c:
911                         rv = _("i386 (32-bit)");
912                         break;
913                 case  0x0200:
914                         rv = _("Itanium");
915                         break;
916                 case 0x8664:
917                         rv = _("x64 (64-bit)");
918                         break;
919                 case 0:
920                         rv = _("Native Architecture");
921                         break;
922                 default:
923                         rv = _("Unknown Architecture");
924                         break;
925         }
926 errorout:
927         assert (rv.length() > 0);
928         close (fd);
929         return rv;
930 }
931
932 int
933 PluginManager::windows_vst_discover (string path, bool cache_only)
934 {
935         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
936
937         if (Config->get_verbose_plugin_scan()) {
938                 if (cache_only) {
939                         info << string_compose (_(" *  %1 (cache only)"), path) << endmsg;
940                 } else {
941                         info << string_compose (_(" *  %1 - %2"), path, dll_info (path)) << endmsg;
942                 }
943         }
944
945         _cancel_timeout = false;
946         vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
947                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
948
949         // TODO  get extended error messae from vstfx_get_info_fst() e.g  blacklisted, 32/64bit compat,
950         // .err file scanner output etc.
951
952         if (finfos->empty()) {
953                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
954                 if (Config->get_verbose_plugin_scan()) {
955                         info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
956                 }
957                 return -1;
958         }
959
960         uint32_t discovered = 0;
961         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
962                 VSTInfo* finfo = *x;
963                 char buf[32];
964
965                 if (!finfo->canProcessReplacing) {
966                         warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
967                                                          finfo->name, PROGRAM_NAME)
968                                 << endl;
969                         continue;
970                 }
971
972                 PluginInfoPtr info (new WindowsVSTPluginInfo);
973
974                 /* what a joke freeware VST is */
975
976                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
977                         info->name = PBD::basename_nosuffix (path);
978                 } else {
979                         info->name = finfo->name;
980                 }
981
982
983                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
984                 info->unique_id = buf;
985                 info->category = "VST";
986                 info->path = path;
987                 info->creator = finfo->creator;
988                 info->index = 0;
989                 info->n_inputs.set_audio (finfo->numInputs);
990                 info->n_outputs.set_audio (finfo->numOutputs);
991                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
992                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
993                 info->type = ARDOUR::Windows_VST;
994
995                 // TODO: check dup-IDs (lxvst AND windows vst)
996                 bool duplicate = false;
997
998                 if (!_windows_vst_plugin_info->empty()) {
999                         for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
1000                                 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
1001                                         warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1002                                         duplicate = true;
1003                                         break;
1004                                 }
1005                         }
1006                 }
1007
1008                 if (!duplicate) {
1009                         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1010                         _windows_vst_plugin_info->push_back (info);
1011                         discovered++;
1012                         if (Config->get_verbose_plugin_scan()) {
1013                                 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1014                         }
1015                 }
1016         }
1017
1018         vstfx_free_info_list (finfos);
1019         return discovered > 0 ? 0 : -1;
1020 }
1021
1022 #endif // WINDOWS_VST_SUPPORT
1023
1024 #ifdef MACVST_SUPPORT
1025 void
1026 PluginManager::mac_vst_refresh (bool cache_only)
1027 {
1028         if (_mac_vst_plugin_info) {
1029                 _mac_vst_plugin_info->clear ();
1030         } else {
1031                 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1032         }
1033
1034         mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1035 }
1036
1037 static bool mac_vst_filter (const string& str, void *)
1038 {
1039         if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
1040                 return false;
1041         }
1042         string plist = Glib::build_filename (str, "Contents", "Info.plist");
1043         if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1044                 return false;
1045         }
1046         return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1047 }
1048
1049 int
1050 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1051 {
1052         vector<string> plugin_objects;
1053         vector<string>::iterator x;
1054
1055         if (Session::get_disable_all_loaded_plugins ()) {
1056                 info << _("Disabled MacVST scan (safe mode)") << endmsg;
1057                 return -1;
1058         }
1059
1060         find_paths_matching_filter (plugin_objects, path, mac_vst_filter, 0, true, true, true);
1061
1062         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1063                 ARDOUR::PluginScanMessage(_("MacVST"), *x, !cache_only && !cancelled());
1064                 mac_vst_discover (*x, cache_only || cancelled());
1065         }
1066         return 0;
1067 }
1068
1069 int
1070 PluginManager::mac_vst_discover (string path, bool cache_only)
1071 {
1072         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1073
1074         _cancel_timeout = false;
1075
1076         vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1077                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1078
1079         if (finfos->empty()) {
1080                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1081                 return -1;
1082         }
1083
1084         uint32_t discovered = 0;
1085         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1086                 VSTInfo* finfo = *x;
1087                 char buf[32];
1088
1089                 if (!finfo->canProcessReplacing) {
1090                         warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1091                                                          finfo->name, PROGRAM_NAME)
1092                                 << endl;
1093                         continue;
1094                 }
1095
1096                 PluginInfoPtr info (new MacVSTPluginInfo);
1097
1098                 info->name = finfo->name;
1099
1100                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1101                 info->unique_id = buf;
1102                 info->category = "MacVST";
1103                 info->path = path;
1104                 info->creator = finfo->creator;
1105                 info->index = 0;
1106                 info->n_inputs.set_audio (finfo->numInputs);
1107                 info->n_outputs.set_audio (finfo->numOutputs);
1108                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1109                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1110                 info->type = ARDOUR::MacVST;
1111
1112                 bool duplicate = false;
1113                 if (!_mac_vst_plugin_info->empty()) {
1114                         for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1115                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1116                                         warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1117                                         duplicate = true;
1118                                         break;
1119                                 }
1120                         }
1121                 }
1122
1123                 if (!duplicate) {
1124                         _mac_vst_plugin_info->push_back (info);
1125                         discovered++;
1126                 }
1127         }
1128
1129         vstfx_free_info_list (finfos);
1130         return discovered > 0 ? 0 : -1;
1131 }
1132
1133 #endif // MAC_VST_SUPPORT
1134
1135 #ifdef LXVST_SUPPORT
1136
1137 void
1138 PluginManager::lxvst_refresh (bool cache_only)
1139 {
1140         if (_lxvst_plugin_info) {
1141                 _lxvst_plugin_info->clear ();
1142         } else {
1143                 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1144         }
1145
1146         lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1147 }
1148
1149 static bool lxvst_filter (const string& str, void *)
1150 {
1151         /* Not a dotfile, has a prefix before a period, suffix is "so" */
1152
1153         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1154 }
1155
1156 int
1157 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1158 {
1159         vector<string> plugin_objects;
1160         vector<string>::iterator x;
1161         int ret = 0;
1162
1163         if (Session::get_disable_all_loaded_plugins ()) {
1164                 info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
1165                 return -1;
1166         }
1167
1168 #ifndef NDEBUG
1169         (void) path;
1170 #endif
1171
1172         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1173
1174         find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1175
1176         for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1177                 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1178                 lxvst_discover (*x, cache_only || cancelled());
1179         }
1180
1181         return ret;
1182 }
1183
1184 int
1185 PluginManager::lxvst_discover (string path, bool cache_only)
1186 {
1187         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1188
1189         _cancel_timeout = false;
1190         vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1191                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1192
1193         if (finfos->empty()) {
1194                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1195                 return -1;
1196         }
1197
1198         uint32_t discovered = 0;
1199         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1200                 VSTInfo* finfo = *x;
1201                 char buf[32];
1202
1203                 if (!finfo->canProcessReplacing) {
1204                         warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1205                                                          finfo->name, PROGRAM_NAME)
1206                                 << endl;
1207                         continue;
1208                 }
1209
1210                 PluginInfoPtr info(new LXVSTPluginInfo);
1211
1212                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1213                         info->name = PBD::basename_nosuffix (path);
1214                 } else {
1215                         info->name = finfo->name;
1216                 }
1217
1218
1219                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1220                 info->unique_id = buf;
1221                 info->category = "linuxVSTs";
1222                 info->path = path;
1223                 info->creator = finfo->creator;
1224                 info->index = 0;
1225                 info->n_inputs.set_audio (finfo->numInputs);
1226                 info->n_outputs.set_audio (finfo->numOutputs);
1227                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1228                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1229                 info->type = ARDOUR::LXVST;
1230
1231                                         /* Make sure we don't find the same plugin in more than one place along
1232                          the LXVST_PATH We can't use a simple 'find' because the path is included
1233                          in the PluginInfo, and that is the one thing we can be sure MUST be
1234                          different if a duplicate instance is found.  So we just compare the type
1235                          and unique ID (which for some VSTs isn't actually unique...)
1236                 */
1237
1238                 // TODO: check dup-IDs with windowsVST, too
1239                 bool duplicate = false;
1240                 if (!_lxvst_plugin_info->empty()) {
1241                         for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1242                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1243                                         warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1244                                         duplicate = true;
1245                                         break;
1246                                 }
1247                         }
1248                 }
1249
1250                 if (!duplicate) {
1251                         _lxvst_plugin_info->push_back (info);
1252                         discovered++;
1253                 }
1254         }
1255
1256         vstfx_free_info_list (finfos);
1257         return discovered > 0 ? 0 : -1;
1258 }
1259
1260 #endif // LXVST_SUPPORT
1261
1262
1263 PluginManager::PluginStatusType
1264 PluginManager::get_status (const PluginInfoPtr& pi) const
1265 {
1266         PluginStatus ps (pi->type, pi->unique_id);
1267         PluginStatusList::const_iterator i =  find (statuses.begin(), statuses.end(), ps);
1268         if (i ==  statuses.end() ) {
1269                 return Normal;
1270         } else {
1271                 return i->status;
1272         }
1273 }
1274
1275 void
1276 PluginManager::save_statuses ()
1277 {
1278         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1279         stringstream ofs;
1280
1281         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1282                 switch ((*i).type) {
1283                 case LADSPA:
1284                         ofs << "LADSPA";
1285                         break;
1286                 case AudioUnit:
1287                         ofs << "AudioUnit";
1288                         break;
1289                 case LV2:
1290                         ofs << "LV2";
1291                         break;
1292                 case Windows_VST:
1293                         ofs << "Windows-VST";
1294                         break;
1295                 case LXVST:
1296                         ofs << "LXVST";
1297                         break;
1298                 case MacVST:
1299                         ofs << "MacVST";
1300                         break;
1301                 case Lua:
1302                         ofs << "Lua";
1303                         break;
1304                 }
1305
1306                 ofs << ' ';
1307
1308                 switch ((*i).status) {
1309                 case Normal:
1310                         ofs << "Normal";
1311                         break;
1312                 case Favorite:
1313                         ofs << "Favorite";
1314                         break;
1315                 case Hidden:
1316                         ofs << "Hidden";
1317                         break;
1318                 }
1319
1320                 ofs << ' ';
1321                 ofs << (*i).unique_id;;
1322                 ofs << endl;
1323         }
1324         g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1325         PluginStatusesChanged (); /* EMIT SIGNAL */
1326 }
1327
1328 void
1329 PluginManager::load_statuses ()
1330 {
1331         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1332         gchar *fbuf = NULL;
1333         if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL))  {
1334                 return;
1335         }
1336         stringstream ifs (fbuf);
1337         g_free (fbuf);
1338
1339         std::string stype;
1340         std::string sstatus;
1341         std::string id;
1342         PluginType type;
1343         PluginStatusType status;
1344         char buf[1024];
1345
1346         while (ifs) {
1347
1348                 ifs >> stype;
1349                 if (!ifs) {
1350                         break;
1351
1352                 }
1353
1354                 ifs >> sstatus;
1355                 if (!ifs) {
1356                         break;
1357
1358                 }
1359
1360                 /* rest of the line is the plugin ID */
1361
1362                 ifs.getline (buf, sizeof (buf), '\n');
1363                 if (!ifs) {
1364                         break;
1365                 }
1366
1367                 if (sstatus == "Normal") {
1368                         status = Normal;
1369                 } else if (sstatus == "Favorite") {
1370                         status = Favorite;
1371                 } else if (sstatus == "Hidden") {
1372                         status = Hidden;
1373                 } else {
1374                         error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1375                                   << endmsg;
1376                         statuses.clear ();
1377                         break;
1378                 }
1379
1380                 if (stype == "LADSPA") {
1381                         type = LADSPA;
1382                 } else if (stype == "AudioUnit") {
1383                         type = AudioUnit;
1384                 } else if (stype == "LV2") {
1385                         type = LV2;
1386                 } else if (stype == "Windows-VST") {
1387                         type = Windows_VST;
1388                 } else if (stype == "LXVST") {
1389                         type = LXVST;
1390                 } else if (stype == "MacVST") {
1391                         type = MacVST;
1392                 } else if (stype == "Lua") {
1393                         type = Lua;
1394                 } else {
1395                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1396                               << endmsg;
1397                         continue;
1398                 }
1399
1400                 id = buf;
1401                 strip_whitespace_edges (id);
1402                 set_status (type, id, status);
1403         }
1404 }
1405
1406 void
1407 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1408 {
1409         PluginStatus ps (t, id, status);
1410         statuses.erase (ps);
1411
1412         if (status == Normal) {
1413                 return;
1414         }
1415
1416         statuses.insert (ps);
1417 }
1418
1419 const ARDOUR::PluginInfoList&
1420 PluginManager::windows_vst_plugin_info ()
1421 {
1422 #ifdef WINDOWS_VST_SUPPORT
1423         if (!_windows_vst_plugin_info) {
1424                 windows_vst_refresh ();
1425         }
1426         return *_windows_vst_plugin_info;
1427 #else
1428         return _empty_plugin_info;
1429 #endif
1430 }
1431
1432 const ARDOUR::PluginInfoList&
1433 PluginManager::mac_vst_plugin_info ()
1434 {
1435 #ifdef MACVST_SUPPORT
1436         assert(_mac_vst_plugin_info);
1437         return *_mac_vst_plugin_info;
1438 #else
1439         return _empty_plugin_info;
1440 #endif
1441 }
1442
1443 const ARDOUR::PluginInfoList&
1444 PluginManager::lxvst_plugin_info ()
1445 {
1446 #ifdef LXVST_SUPPORT
1447         assert(_lxvst_plugin_info);
1448         return *_lxvst_plugin_info;
1449 #else
1450         return _empty_plugin_info;
1451 #endif
1452 }
1453
1454 const ARDOUR::PluginInfoList&
1455 PluginManager::ladspa_plugin_info ()
1456 {
1457         assert(_ladspa_plugin_info);
1458         return *_ladspa_plugin_info;
1459 }
1460
1461 const ARDOUR::PluginInfoList&
1462 PluginManager::lv2_plugin_info ()
1463 {
1464 #ifdef LV2_SUPPORT
1465         assert(_lv2_plugin_info);
1466         return *_lv2_plugin_info;
1467 #else
1468         return _empty_plugin_info;
1469 #endif
1470 }
1471
1472 const ARDOUR::PluginInfoList&
1473 PluginManager::au_plugin_info ()
1474 {
1475 #ifdef AUDIOUNIT_SUPPORT
1476         if (_au_plugin_info) {
1477                 return *_au_plugin_info;
1478         }
1479 #endif
1480         return _empty_plugin_info;
1481 }
1482
1483 const ARDOUR::PluginInfoList&
1484 PluginManager::lua_plugin_info ()
1485 {
1486         assert(_lua_plugin_info);
1487         return *_lua_plugin_info;
1488 }