2 Copyright (C) 2000-2006 Paul Davis
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.
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.
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.
21 #include "libardour-config.h"
26 #include <sys/types.h>
35 #ifdef WINDOWS_VST_SUPPORT
36 #include "ardour/vst_info_file.h"
38 #include "pbd/basename.h"
40 #endif // WINDOWS_VST_SUPPORT
43 #include "ardour/vst_info_file.h"
44 #include "ardour/linux_vst_support.h"
45 #include "pbd/basename.h"
47 #endif //LXVST_SUPPORT
49 #include <glib/gstdio.h>
50 #include <glibmm/miscutils.h>
51 #include <glibmm/pattern.h>
53 #include "pbd/pathscanner.h"
54 #include "pbd/whitespace.h"
55 #include "pbd/file_utils.h"
57 #include "ardour/debug.h"
58 #include "ardour/filesystem_paths.h"
59 #include "ardour/ladspa.h"
60 #include "ardour/ladspa_plugin.h"
61 #include "ardour/plugin.h"
62 #include "ardour/plugin_manager.h"
63 #include "ardour/rc_configuration.h"
65 #include "ardour/ladspa_search_path.h"
68 #include "ardour/lv2_plugin.h"
71 #ifdef WINDOWS_VST_SUPPORT
72 #include "ardour/windows_vst_plugin.h"
76 #include "ardour/lxvst_plugin.h"
79 #ifdef AUDIOUNIT_SUPPORT
80 #include "ardour/audio_unit.h"
81 #include <Carbon/Carbon.h>
84 #include "pbd/error.h"
85 #include "pbd/stl_delete.h"
89 #include "ardour/debug.h"
91 using namespace ARDOUR;
95 PluginManager* PluginManager::_instance = 0;
96 std::string PluginManager::scanner_bin_path = "";
99 PluginManager::instance()
102 _instance = new PluginManager;
107 PluginManager::PluginManager ()
108 : _windows_vst_plugin_info(0)
109 , _lxvst_plugin_info(0)
110 , _ladspa_plugin_info(0)
111 , _lv2_plugin_info(0)
118 if (!PBD::find_file_in_search_path (
119 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst")),
120 "ardour-vst-scanner", scanner_bin_path)) {
121 PBD::warning << "VST scanner app not found.'" << endmsg;
126 if ((s = getenv ("LADSPA_RDF_PATH"))){
130 if (lrdf_path.length() == 0) {
131 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
134 add_lrdf_data(lrdf_path);
135 add_ladspa_presets();
136 #ifdef WINDOWS_VST_SUPPORT
137 if (Config->get_use_windows_vst ()) {
138 add_windows_vst_presets ();
140 #endif /* WINDOWS_VST_SUPPORT */
143 if (Config->get_use_lxvst()) {
146 #endif /* Native LinuxVST support*/
148 if ((s = getenv ("VST_PATH"))) {
149 windows_vst_path = s;
150 } else if ((s = getenv ("VST_PLUGINS"))) {
151 windows_vst_path = s;
154 if ((s = getenv ("LXVST_PATH"))) {
156 } else if ((s = getenv ("LXVST_PLUGINS"))) {
160 if (_instance == 0) {
164 /* the plugin manager is constructed too early to use Profile */
166 if (getenv ("ARDOUR_SAE")) {
167 ladspa_plugin_whitelist.push_back (1203); // single band parametric
168 ladspa_plugin_whitelist.push_back (1772); // caps compressor
169 ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter
170 ladspa_plugin_whitelist.push_back (1075); // simple RMS expander
171 ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s)
172 ladspa_plugin_whitelist.push_back (1216); // gverb
173 ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
176 BootMessage (_("Discovering Plugins"));
180 PluginManager::~PluginManager()
186 PluginManager::refresh (bool cache_only)
188 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
189 BootMessage (_("Discovering Plugins"));
196 #ifdef WINDOWS_VST_SUPPORT
197 if (Config->get_use_windows_vst()) {
198 windows_vst_refresh ();
200 #endif // WINDOWS_VST_SUPPORT
203 if(Config->get_use_lxvst()) {
206 #endif //Native linuxVST SUPPORT
208 #ifdef AUDIOUNIT_SUPPORT
212 PluginListChanged (); /* EMIT SIGNAL */
213 PluginScanMessage(X_("closeme"), "");
218 PluginManager::cancel_plugin_scan ()
224 PluginManager::clear_vst_cache ()
226 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
227 #ifdef WINDOWS_VST_SUPPORT
230 vector<string *> *fsi_files;
232 fsi_files = scanner (windows_vst_path, "\\.fsi$", true, true, -1, false);
234 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
235 ::g_unlink((*i)->c_str());
238 vector_delete(fsi_files);
245 vector<string *> *fsi_files;
246 fsi_files = scanner (lxvst_path, "\\.fsi$", true, true, -1, false);
248 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
249 ::g_unlink((*i)->c_str());
252 vector_delete(fsi_files);
256 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
258 string personal = get_personal_vst_info_cache_dir();
260 vector<string *> *fsi_files;
261 fsi_files = scanner (personal, "\\.fsi$", true, true, -1, false);
263 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
264 ::g_unlink((*i)->c_str());
267 vector_delete(fsi_files);
273 PluginManager::clear_vst_blacklist ()
275 #ifdef WINDOWS_VST_SUPPORT
278 vector<string *> *fsi_files;
280 fsi_files = scanner (windows_vst_path, "\\.fsb$", true, true, -1, false);
282 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
283 ::g_unlink((*i)->c_str());
286 vector_delete(fsi_files);
293 vector<string *> *fsi_files;
294 fsi_files = scanner (lxvst_path, "\\.fsb$", true, true, -1, false);
296 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
297 ::g_unlink((*i)->c_str());
300 vector_delete(fsi_files);
304 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
306 string personal = get_personal_vst_blacklist_dir();
309 vector<string *> *fsi_files;
310 fsi_files = scanner (personal, "\\.fsb$", true, true, -1, false);
312 for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
313 ::g_unlink((*i)->c_str());
316 vector_delete(fsi_files);
322 PluginManager::ladspa_refresh ()
324 if (_ladspa_plugin_info) {
325 _ladspa_plugin_info->clear ();
327 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
330 /* allow LADSPA_PATH to augment, not override standard locations */
332 /* Only add standard locations to ladspa_path if it doesn't
333 * already contain them. Check for trailing G_DIR_SEPARATOR too.
336 vector<string> ladspa_modules;
338 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
340 Glib::PatternSpec so_extension_pattern("*.so");
341 Glib::PatternSpec dylib_extension_pattern("*.dylib");
342 Glib::PatternSpec dll_extension_pattern("*.dll");
344 find_matching_files_in_search_path (ladspa_search_path (),
345 so_extension_pattern, ladspa_modules);
347 find_matching_files_in_search_path (ladspa_search_path (),
348 dylib_extension_pattern, ladspa_modules);
350 find_matching_files_in_search_path (ladspa_search_path (),
351 dll_extension_pattern, ladspa_modules);
353 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
354 ARDOUR::PluginScanMessage(_("LADSPA"), *i);
355 ladspa_discover (*i);
359 static bool rdf_filter (const string &str, void* /*arg*/)
361 return str[0] != '.' &&
362 ((str.find(".rdf") == (str.length() - 4)) ||
363 (str.find(".rdfs") == (str.length() - 5)) ||
364 (str.find(".n3") == (str.length() - 3)) ||
365 (str.find(".ttl") == (str.length() - 4)));
369 PluginManager::add_ladspa_presets()
371 add_presets ("ladspa");
375 PluginManager::add_windows_vst_presets()
377 add_presets ("windows-vst");
381 PluginManager::add_lxvst_presets()
383 add_presets ("lxvst");
387 PluginManager::add_presets(string domain)
391 vector<string *> *presets;
392 vector<string *>::iterator x;
395 if ((envvar = getenv ("HOME")) == 0) {
399 string path = string_compose("%1/.%2/rdf", envvar, domain);
400 presets = scanner (path, rdf_filter, 0, false, true);
403 for (x = presets->begin(); x != presets->end (); ++x) {
404 string file = "file:" + **x;
405 if (lrdf_read_file(file.c_str())) {
406 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
410 vector_delete (presets);
416 PluginManager::add_lrdf_data (const string &path)
420 vector<string *>* rdf_files;
421 vector<string *>::iterator x;
423 rdf_files = scanner (path, rdf_filter, 0, false, true);
426 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
427 const string uri(string("file://") + **x);
429 if (lrdf_read_file(uri.c_str())) {
430 warning << "Could not parse rdf file: " << uri << endmsg;
434 vector_delete (rdf_files);
440 PluginManager::ladspa_discover (string path)
442 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
444 Glib::Module module(path);
445 const LADSPA_Descriptor *descriptor;
446 LADSPA_Descriptor_Function dfunc;
450 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
451 path, Glib::Module::get_last_error()) << endmsg;
456 if (!module.get_symbol("ladspa_descriptor", func)) {
457 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
458 error << Glib::Module::get_last_error() << endmsg;
462 dfunc = (LADSPA_Descriptor_Function)func;
464 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
466 for (uint32_t i = 0; ; ++i) {
467 if ((descriptor = dfunc (i)) == 0) {
471 if (!ladspa_plugin_whitelist.empty()) {
472 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
477 PluginInfoPtr info(new LadspaPluginInfo);
478 info->name = descriptor->Name;
479 info->category = get_ladspa_category(descriptor->UniqueID);
480 info->creator = descriptor->Maker;
483 info->n_inputs = ChanCount();
484 info->n_outputs = ChanCount();
485 info->type = ARDOUR::LADSPA;
488 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
489 info->unique_id = buf;
491 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
492 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
493 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
494 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
496 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
497 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
502 if(_ladspa_plugin_info->empty()){
503 _ladspa_plugin_info->push_back (info);
506 //Ensure that the plugin is not already in the plugin list.
510 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
511 if(0 == info->unique_id.compare((*i)->unique_id)){
517 _ladspa_plugin_info->push_back (info);
520 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
523 // GDB WILL NOT LIKE YOU IF YOU DO THIS
530 PluginManager::get_ladspa_category (uint32_t plugin_id)
534 lrdf_statement pattern;
536 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
537 pattern.subject = buf;
538 pattern.predicate = const_cast<char*>(RDF_TYPE);
540 pattern.object_type = lrdf_uri;
542 lrdf_statement* matches1 = lrdf_matches (&pattern);
548 pattern.subject = matches1->object;
549 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
551 pattern.object_type = lrdf_literal;
553 lrdf_statement* matches2 = lrdf_matches (&pattern);
554 lrdf_free_statements(matches1);
560 string label = matches2->object;
561 lrdf_free_statements(matches2);
563 /* Kludge LADSPA class names to be singular and match LV2 class names.
564 This avoids duplicate plugin menus for every class, which is necessary
565 to make the plugin category menu at all usable, but is obviously a
568 In the short term, lrdf could be updated so the labels match and a new
569 release made. To support both specs, we should probably be mapping the
570 URIs to the same category in code and perhaps tweaking that hierarchy
571 dynamically to suit the user. Personally, I (drobilla) think that time
572 is better spent replacing the little-used LRDF.
574 In the longer term, we will abandon LRDF entirely in favour of LV2 and
575 use that class hierarchy. Aside from fixing this problem properly, that
576 will also allow for translated labels. SWH plugins have been LV2 for
577 ages; TAP needs porting. I don't know of anything else with LRDF data.
579 if (label == "Utilities") {
581 } else if (label == "Pitch shifters") {
582 return "Pitch Shifter";
583 } else if (label != "Dynamics" && label != "Chorus"
584 &&label[label.length() - 1] == 's'
585 && label[label.length() - 2] != 's') {
586 return label.substr(0, label.length() - 1);
597 PluginManager::lv2_refresh ()
599 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
600 delete _lv2_plugin_info;
601 _lv2_plugin_info = LV2PluginInfo::discover();
605 #ifdef AUDIOUNIT_SUPPORT
607 PluginManager::au_refresh ()
609 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
610 delete _au_plugin_info;
611 _au_plugin_info = AUPluginInfo::discover();
616 #ifdef WINDOWS_VST_SUPPORT
619 PluginManager::windows_vst_refresh (bool cache_only)
621 if (_windows_vst_plugin_info) {
622 _windows_vst_plugin_info->clear ();
624 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
627 if (windows_vst_path.length() == 0) {
628 windows_vst_path = "/usr/local/lib/vst:/usr/lib/vst";
631 windows_vst_discover_from_path (windows_vst_path, cache_only);
635 PluginManager::add_windows_vst_directory (string path)
637 if (windows_vst_discover_from_path (path) == 0) {
638 windows_vst_path += ':';
639 windows_vst_path += path;
645 static bool windows_vst_filter (const string& str, void * /*arg*/)
647 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
649 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
653 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
656 vector<string *> *plugin_objects;
657 vector<string *>::iterator x;
660 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
662 plugin_objects = scanner (windows_vst_path, windows_vst_filter, 0, false, true);
664 if (plugin_objects) {
665 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
666 if (cancelled()) break;
667 ARDOUR::PluginScanMessage(_("VST"), **x);
668 windows_vst_discover (**x, cache_only);
671 vector_delete (plugin_objects);
678 PluginManager::windows_vst_discover (string path, bool cache_only)
680 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
682 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
683 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
685 if (finfos->empty()) {
686 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
690 uint32_t discovered = 0;
691 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
695 if (!finfo->canProcessReplacing) {
696 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
697 finfo->name, PROGRAM_NAME)
702 PluginInfoPtr info (new WindowsVSTPluginInfo);
704 /* what a joke freeware VST is */
706 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
707 info->name = PBD::basename_nosuffix (path);
709 info->name = finfo->name;
713 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
714 info->unique_id = buf;
715 info->category = "VST";
717 info->creator = finfo->creator;
719 info->n_inputs.set_audio (finfo->numInputs);
720 info->n_outputs.set_audio (finfo->numOutputs);
721 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
722 info->type = ARDOUR::Windows_VST;
724 // TODO: check dup-IDs (lxvst AND windows vst)
725 bool duplicate = false;
727 if (!_windows_vst_plugin_info->empty()) {
728 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
729 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
730 warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
738 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
739 _windows_vst_plugin_info->push_back (info);
744 vstfx_free_info_list (finfos);
745 return discovered > 0 ? 0 : -1;
748 #endif // WINDOWS_VST_SUPPORT
753 PluginManager::lxvst_refresh (bool cache_only)
755 if (_lxvst_plugin_info) {
756 _lxvst_plugin_info->clear ();
758 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
761 if (lxvst_path.length() == 0) {
762 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
763 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
764 "/usr/lib/vst:/usr/local/lib/vst";
767 lxvst_discover_from_path (lxvst_path, cache_only);
771 PluginManager::add_lxvst_directory (string path)
773 if (lxvst_discover_from_path (path) == 0) {
781 static bool lxvst_filter (const string& str, void *)
783 /* Not a dotfile, has a prefix before a period, suffix is "so" */
785 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
789 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
792 vector<string *> *plugin_objects;
793 vector<string *>::iterator x;
800 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
802 plugin_objects = scanner (lxvst_path, lxvst_filter, 0, false, true);
804 if (plugin_objects) {
805 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
806 if (cancelled()) break;
807 ARDOUR::PluginScanMessage(_("LXVST"), **x);
808 lxvst_discover (**x, cache_only);
811 vector_delete (plugin_objects);
818 PluginManager::lxvst_discover (string path, bool cache_only)
820 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
822 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
823 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
825 if (finfos->empty()) {
826 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
830 uint32_t discovered = 0;
831 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
835 if (!finfo->canProcessReplacing) {
836 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
837 finfo->name, PROGRAM_NAME)
842 PluginInfoPtr info(new LXVSTPluginInfo);
844 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
845 info->name = PBD::basename_nosuffix (path);
847 info->name = finfo->name;
851 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
852 info->unique_id = buf;
853 info->category = "linuxVSTs";
855 info->creator = finfo->creator;
857 info->n_inputs.set_audio (finfo->numInputs);
858 info->n_outputs.set_audio (finfo->numOutputs);
859 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
860 info->type = ARDOUR::LXVST;
862 /* Make sure we don't find the same plugin in more than one place along
863 the LXVST_PATH We can't use a simple 'find' because the path is included
864 in the PluginInfo, and that is the one thing we can be sure MUST be
865 different if a duplicate instance is found. So we just compare the type
866 and unique ID (which for some VSTs isn't actually unique...)
869 // TODO: check dup-IDs with windowsVST, too
870 bool duplicate = false;
871 if (!_lxvst_plugin_info->empty()) {
872 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
873 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
874 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
882 _lxvst_plugin_info->push_back (info);
887 vstfx_free_info_list (finfos);
888 return discovered > 0 ? 0 : -1;
891 #endif // LXVST_SUPPORT
894 PluginManager::PluginStatusType
895 PluginManager::get_status (const PluginInfoPtr& pi)
897 PluginStatus ps (pi->type, pi->unique_id);
898 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
899 if (i == statuses.end() ) {
907 PluginManager::save_statuses ()
910 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
912 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
918 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
930 ofs << "Windows-VST";
939 switch ((*i).status) {
952 ofs << (*i).unique_id;;
960 PluginManager::load_statuses ()
962 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
963 ifstream ifs (path.c_str());
973 PluginStatusType status;
990 /* rest of the line is the plugin ID */
992 ifs.getline (buf, sizeof (buf), '\n');
997 if (sstatus == "Normal") {
999 } else if (sstatus == "Favorite") {
1001 } else if (sstatus == "Hidden") {
1004 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1010 if (stype == "LADSPA") {
1012 } else if (stype == "AudioUnit") {
1014 } else if (stype == "LV2") {
1016 } else if (stype == "Windows-VST") {
1018 } else if (stype == "LXVST") {
1021 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1027 strip_whitespace_edges (id);
1028 set_status (type, id, status);
1035 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1037 PluginStatus ps (t, id, status);
1038 statuses.erase (ps);
1040 if (status == Normal) {
1044 statuses.insert (ps);
1047 ARDOUR::PluginInfoList&
1048 PluginManager::windows_vst_plugin_info ()
1050 #ifdef WINDOWS_VST_SUPPORT
1051 if (!_windows_vst_plugin_info) {
1052 windows_vst_refresh ();
1054 return *_windows_vst_plugin_info;
1056 return _empty_plugin_info;
1060 ARDOUR::PluginInfoList&
1061 PluginManager::lxvst_plugin_info ()
1063 #ifdef LXVST_SUPPORT
1064 if (!_lxvst_plugin_info)
1066 return *_lxvst_plugin_info;
1068 return _empty_plugin_info;
1072 ARDOUR::PluginInfoList&
1073 PluginManager::ladspa_plugin_info ()
1075 if (!_ladspa_plugin_info)
1077 return *_ladspa_plugin_info;
1080 ARDOUR::PluginInfoList&
1081 PluginManager::lv2_plugin_info ()
1084 if (!_lv2_plugin_info)
1086 return *_lv2_plugin_info;
1088 return _empty_plugin_info;
1092 ARDOUR::PluginInfoList&
1093 PluginManager::au_plugin_info ()
1095 #ifdef AUDIOUNIT_SUPPORT
1096 if (!_au_plugin_info)
1098 return *_au_plugin_info;
1100 return _empty_plugin_info;