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/whitespace.h"
54 #include "pbd/file_utils.h"
56 #include "ardour/debug.h"
57 #include "ardour/filesystem_paths.h"
58 #include "ardour/ladspa.h"
59 #include "ardour/ladspa_plugin.h"
60 #include "ardour/plugin.h"
61 #include "ardour/plugin_manager.h"
62 #include "ardour/rc_configuration.h"
64 #include "ardour/search_paths.h"
67 #include "ardour/lv2_plugin.h"
70 #ifdef WINDOWS_VST_SUPPORT
71 #include "ardour/windows_vst_plugin.h"
75 #include "ardour/lxvst_plugin.h"
78 #ifdef AUDIOUNIT_SUPPORT
79 #include "ardour/audio_unit.h"
80 #include <Carbon/Carbon.h>
83 #include "pbd/error.h"
84 #include "pbd/stl_delete.h"
88 #include "ardour/debug.h"
90 using namespace ARDOUR;
94 PluginManager* PluginManager::_instance = 0;
95 std::string PluginManager::scanner_bin_path = "";
98 PluginManager::instance()
101 _instance = new PluginManager;
106 PluginManager::PluginManager ()
107 : _windows_vst_plugin_info(0)
108 , _lxvst_plugin_info(0)
109 , _ladspa_plugin_info(0)
110 , _lv2_plugin_info(0)
112 , _cancel_scan(false)
113 , _cancel_timeout(false)
118 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
119 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
120 #ifdef PLATFORM_WINDOWS
121 vstsp += Glib::build_filename(g_win32_get_package_installation_directory_of_module (0), "bin");
123 vstsp += Glib::getenv("PATH");
125 if (!PBD::find_file (vstsp,
126 #ifdef PLATFORM_WINDOWS
127 #ifdef DEBUGGABLE_SCANNER_APP
128 #if defined(DEBUG) || defined(_DEBUG)
129 "ardour-vst-scannerD.exe"
131 "ardour-vst-scannerRDC.exe"
134 "ardour-vst-scanner.exe"
139 , scanner_bin_path)) {
140 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
146 if ((s = getenv ("LADSPA_RDF_PATH"))){
150 if (lrdf_path.length() == 0) {
151 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
154 add_lrdf_data(lrdf_path);
155 add_ladspa_presets();
156 #ifdef WINDOWS_VST_SUPPORT
157 if (Config->get_use_windows_vst ()) {
158 add_windows_vst_presets ();
160 #endif /* WINDOWS_VST_SUPPORT */
163 if (Config->get_use_lxvst()) {
166 #endif /* Native LinuxVST support*/
168 if ((s = getenv ("VST_PATH"))) {
169 windows_vst_path = s;
170 } else if ((s = getenv ("VST_PLUGINS"))) {
171 windows_vst_path = s;
174 if (windows_vst_path.length() == 0) {
175 windows_vst_path = vst_search_path ();
178 if ((s = getenv ("LXVST_PATH"))) {
180 } else if ((s = getenv ("LXVST_PLUGINS"))) {
184 if (lxvst_path.length() == 0) {
185 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
186 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
187 "/usr/lib/vst:/usr/local/lib/vst";
190 /* first time setup, use 'default' path */
191 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
192 Config->set_plugin_path_lxvst(get_default_lxvst_path());
194 if (Config->get_plugin_path_vst() == X_("@default@")) {
195 Config->set_plugin_path_vst(get_default_windows_vst_path());
198 if (_instance == 0) {
202 BootMessage (_("Discovering Plugins"));
206 PluginManager::~PluginManager()
208 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
209 // don't bother, just exit quickly.
210 delete _windows_vst_plugin_info;
211 delete _lxvst_plugin_info;
212 delete _ladspa_plugin_info;
213 delete _lv2_plugin_info;
214 delete _au_plugin_info;
219 PluginManager::refresh (bool cache_only)
221 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
222 _cancel_scan = false;
224 BootMessage (_("Scanning LADSPA Plugins"));
227 BootMessage (_("Scanning LV2 Plugins"));
230 #ifdef WINDOWS_VST_SUPPORT
231 if (Config->get_use_windows_vst()) {
232 BootMessage (_("Scanning Windows VST Plugins"));
233 windows_vst_refresh (cache_only);
235 #endif // WINDOWS_VST_SUPPORT
238 if(Config->get_use_lxvst()) {
239 BootMessage (_("Scanning Linux VST Plugins"));
240 lxvst_refresh(cache_only);
242 #endif //Native linuxVST SUPPORT
244 #ifdef AUDIOUNIT_SUPPORT
245 BootMessage (_("Scanning AU Plugins"));
246 au_refresh (cache_only);
249 BootMessage (_("Plugin Scan Complete..."));
250 PluginListChanged (); /* EMIT SIGNAL */
251 PluginScanMessage(X_("closeme"), "", false);
252 _cancel_scan = false;
256 PluginManager::cancel_plugin_scan ()
262 PluginManager::cancel_plugin_timeout ()
264 _cancel_timeout = true;
268 PluginManager::clear_vst_cache ()
270 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
271 #ifdef WINDOWS_VST_SUPPORT
273 vector<string> fsi_files;
274 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$");
275 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
276 ::g_unlink(i->c_str());
283 vector<string> fsi_files;
284 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$");
285 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
286 ::g_unlink(i->c_str());
291 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
293 string personal = get_personal_vst_info_cache_dir();
294 vector<string> fsi_files;
295 find_files_matching_regex (fsi_files, personal, "\\.fsi$");
296 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
297 ::g_unlink(i->c_str());
304 PluginManager::clear_vst_blacklist ()
306 #ifdef WINDOWS_VST_SUPPORT
308 vector<string> fsi_files;
309 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsb$");
310 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
311 ::g_unlink(i->c_str());
318 vector<string> fsi_files;
319 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsb$");
320 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
321 ::g_unlink(i->c_str());
326 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
328 string personal = get_personal_vst_blacklist_dir();
330 vector<string> fsi_files;
331 find_files_matching_regex (fsi_files, personal, "\\.fsb$");
332 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
333 ::g_unlink(i->c_str());
340 PluginManager::ladspa_refresh ()
342 if (_ladspa_plugin_info) {
343 _ladspa_plugin_info->clear ();
345 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
348 /* allow LADSPA_PATH to augment, not override standard locations */
350 /* Only add standard locations to ladspa_path if it doesn't
351 * already contain them. Check for trailing G_DIR_SEPARATOR too.
354 vector<string> ladspa_modules;
356 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
358 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
359 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
360 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
362 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
363 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
364 ladspa_discover (*i);
368 static bool rdf_filter (const string &str, void* /*arg*/)
370 return str[0] != '.' &&
371 ((str.find(".rdf") == (str.length() - 4)) ||
372 (str.find(".rdfs") == (str.length() - 5)) ||
373 (str.find(".n3") == (str.length() - 3)) ||
374 (str.find(".ttl") == (str.length() - 4)));
378 PluginManager::add_ladspa_presets()
380 add_presets ("ladspa");
384 PluginManager::add_windows_vst_presets()
386 add_presets ("windows-vst");
390 PluginManager::add_lxvst_presets()
392 add_presets ("lxvst");
396 PluginManager::add_presets(string domain)
399 vector<string> presets;
400 vector<string>::iterator x;
403 if ((envvar = getenv ("HOME")) == 0) {
407 string path = string_compose("%1/.%2/rdf", envvar, domain);
408 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
410 for (x = presets.begin(); x != presets.end (); ++x) {
411 string file = "file:" + *x;
412 if (lrdf_read_file(file.c_str())) {
413 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
421 PluginManager::add_lrdf_data (const string &path)
424 vector<string> rdf_files;
425 vector<string>::iterator x;
427 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
429 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
430 const string uri(string("file://") + *x);
432 if (lrdf_read_file(uri.c_str())) {
433 warning << "Could not parse rdf file: " << uri << endmsg;
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 (bool cache_only)
609 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
610 if (cache_only && !Config->get_discover_audio_units ()) {
613 delete _au_plugin_info;
615 // disable automatic scan in case we crash
616 Config->set_discover_audio_units (false);
617 Config->save_state();
619 _au_plugin_info = AUPluginInfo::discover();
621 // successful scan re-enabled automatic discovery
622 Config->set_discover_audio_units (true);
623 Config->save_state();
628 #ifdef WINDOWS_VST_SUPPORT
631 PluginManager::windows_vst_refresh (bool cache_only)
633 if (_windows_vst_plugin_info) {
634 _windows_vst_plugin_info->clear ();
636 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
639 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
642 static bool windows_vst_filter (const string& str, void * /*arg*/)
644 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
646 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
650 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
652 vector<string> plugin_objects;
653 vector<string>::iterator x;
656 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
658 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
660 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
661 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
662 windows_vst_discover (*x, cache_only || cancelled());
669 PluginManager::windows_vst_discover (string path, bool cache_only)
671 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
673 _cancel_timeout = false;
674 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
675 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
677 if (finfos->empty()) {
678 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
682 uint32_t discovered = 0;
683 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
687 if (!finfo->canProcessReplacing) {
688 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
689 finfo->name, PROGRAM_NAME)
694 PluginInfoPtr info (new WindowsVSTPluginInfo);
696 /* what a joke freeware VST is */
698 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
699 info->name = PBD::basename_nosuffix (path);
701 info->name = finfo->name;
705 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
706 info->unique_id = buf;
707 info->category = "VST";
709 info->creator = finfo->creator;
711 info->n_inputs.set_audio (finfo->numInputs);
712 info->n_outputs.set_audio (finfo->numOutputs);
713 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
714 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
715 info->type = ARDOUR::Windows_VST;
717 // TODO: check dup-IDs (lxvst AND windows vst)
718 bool duplicate = false;
720 if (!_windows_vst_plugin_info->empty()) {
721 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
722 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
723 warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
731 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
732 _windows_vst_plugin_info->push_back (info);
737 vstfx_free_info_list (finfos);
738 return discovered > 0 ? 0 : -1;
741 #endif // WINDOWS_VST_SUPPORT
746 PluginManager::lxvst_refresh (bool cache_only)
748 if (_lxvst_plugin_info) {
749 _lxvst_plugin_info->clear ();
751 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
754 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
757 static bool lxvst_filter (const string& str, void *)
759 /* Not a dotfile, has a prefix before a period, suffix is "so" */
761 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
765 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
767 vector<string> plugin_objects;
768 vector<string>::iterator x;
775 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
777 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
779 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
780 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
781 lxvst_discover (*x, cache_only || cancelled());
788 PluginManager::lxvst_discover (string path, bool cache_only)
790 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
792 _cancel_timeout = false;
793 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
794 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
796 if (finfos->empty()) {
797 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
801 uint32_t discovered = 0;
802 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
806 if (!finfo->canProcessReplacing) {
807 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
808 finfo->name, PROGRAM_NAME)
813 PluginInfoPtr info(new LXVSTPluginInfo);
815 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
816 info->name = PBD::basename_nosuffix (path);
818 info->name = finfo->name;
822 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
823 info->unique_id = buf;
824 info->category = "linuxVSTs";
826 info->creator = finfo->creator;
828 info->n_inputs.set_audio (finfo->numInputs);
829 info->n_outputs.set_audio (finfo->numOutputs);
830 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
831 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
832 info->type = ARDOUR::LXVST;
834 /* Make sure we don't find the same plugin in more than one place along
835 the LXVST_PATH We can't use a simple 'find' because the path is included
836 in the PluginInfo, and that is the one thing we can be sure MUST be
837 different if a duplicate instance is found. So we just compare the type
838 and unique ID (which for some VSTs isn't actually unique...)
841 // TODO: check dup-IDs with windowsVST, too
842 bool duplicate = false;
843 if (!_lxvst_plugin_info->empty()) {
844 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
845 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
846 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
854 _lxvst_plugin_info->push_back (info);
859 vstfx_free_info_list (finfos);
860 return discovered > 0 ? 0 : -1;
863 #endif // LXVST_SUPPORT
866 PluginManager::PluginStatusType
867 PluginManager::get_status (const PluginInfoPtr& pi)
869 PluginStatus ps (pi->type, pi->unique_id);
870 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
871 if (i == statuses.end() ) {
879 PluginManager::save_statuses ()
882 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
884 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
890 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
902 ofs << "Windows-VST";
911 switch ((*i).status) {
924 ofs << (*i).unique_id;;
932 PluginManager::load_statuses ()
934 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
935 ifstream ifs (path.c_str());
945 PluginStatusType status;
962 /* rest of the line is the plugin ID */
964 ifs.getline (buf, sizeof (buf), '\n');
969 if (sstatus == "Normal") {
971 } else if (sstatus == "Favorite") {
973 } else if (sstatus == "Hidden") {
976 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
982 if (stype == "LADSPA") {
984 } else if (stype == "AudioUnit") {
986 } else if (stype == "LV2") {
988 } else if (stype == "Windows-VST") {
990 } else if (stype == "LXVST") {
993 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
999 strip_whitespace_edges (id);
1000 set_status (type, id, status);
1007 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1009 PluginStatus ps (t, id, status);
1010 statuses.erase (ps);
1012 if (status == Normal) {
1016 statuses.insert (ps);
1019 ARDOUR::PluginInfoList&
1020 PluginManager::windows_vst_plugin_info ()
1022 #ifdef WINDOWS_VST_SUPPORT
1023 if (!_windows_vst_plugin_info) {
1024 windows_vst_refresh ();
1026 return *_windows_vst_plugin_info;
1028 return _empty_plugin_info;
1032 ARDOUR::PluginInfoList&
1033 PluginManager::lxvst_plugin_info ()
1035 #ifdef LXVST_SUPPORT
1036 assert(_lxvst_plugin_info);
1037 return *_lxvst_plugin_info;
1039 return _empty_plugin_info;
1043 ARDOUR::PluginInfoList&
1044 PluginManager::ladspa_plugin_info ()
1046 assert(_ladspa_plugin_info);
1047 return *_ladspa_plugin_info;
1050 ARDOUR::PluginInfoList&
1051 PluginManager::lv2_plugin_info ()
1054 assert(_lv2_plugin_info);
1055 return *_lv2_plugin_info;
1057 return _empty_plugin_info;
1061 ARDOUR::PluginInfoList&
1062 PluginManager::au_plugin_info ()
1064 #ifdef AUDIOUNIT_SUPPORT
1065 if (_au_plugin_info) {
1066 return *_au_plugin_info;
1069 return _empty_plugin_info;