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 // source-tree (ardev, etc)
120 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
122 #ifdef PLATFORM_WINDOWS
123 // on windows the .exe needs to be in the same folder with libardour.dll
124 vstsp += Glib::build_filename(g_win32_get_package_installation_directory_of_module (0), "bin");
126 // on Unices additional internal-use binaries are deployed to $libdir
127 vstsp += ARDOUR::ardour_dll_directory();
130 if (!PBD::find_file (vstsp,
131 #ifdef PLATFORM_WINDOWS
132 #ifdef DEBUGGABLE_SCANNER_APP
133 #if defined(DEBUG) || defined(_DEBUG)
134 "ardour-vst-scannerD.exe"
136 "ardour-vst-scannerRDC.exe"
139 "ardour-vst-scanner.exe"
144 , scanner_bin_path)) {
145 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
151 if ((s = getenv ("LADSPA_RDF_PATH"))){
155 if (lrdf_path.length() == 0) {
156 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
159 add_lrdf_data(lrdf_path);
160 add_ladspa_presets();
161 #ifdef WINDOWS_VST_SUPPORT
162 if (Config->get_use_windows_vst ()) {
163 add_windows_vst_presets ();
165 #endif /* WINDOWS_VST_SUPPORT */
168 if (Config->get_use_lxvst()) {
171 #endif /* Native LinuxVST support*/
173 if ((s = getenv ("VST_PATH"))) {
174 windows_vst_path = s;
175 } else if ((s = getenv ("VST_PLUGINS"))) {
176 windows_vst_path = s;
179 if (windows_vst_path.length() == 0) {
180 windows_vst_path = vst_search_path ();
183 if ((s = getenv ("LXVST_PATH"))) {
185 } else if ((s = getenv ("LXVST_PLUGINS"))) {
189 if (lxvst_path.length() == 0) {
190 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
191 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
192 "/usr/lib/vst:/usr/local/lib/vst";
195 /* first time setup, use 'default' path */
196 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
197 Config->set_plugin_path_lxvst(get_default_lxvst_path());
199 if (Config->get_plugin_path_vst() == X_("@default@")) {
200 Config->set_plugin_path_vst(get_default_windows_vst_path());
203 if (_instance == 0) {
207 BootMessage (_("Discovering Plugins"));
211 PluginManager::~PluginManager()
213 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
214 // don't bother, just exit quickly.
215 delete _windows_vst_plugin_info;
216 delete _lxvst_plugin_info;
217 delete _ladspa_plugin_info;
218 delete _lv2_plugin_info;
219 delete _au_plugin_info;
224 PluginManager::refresh (bool cache_only)
226 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
227 _cancel_scan = false;
229 BootMessage (_("Scanning LADSPA Plugins"));
232 BootMessage (_("Scanning LV2 Plugins"));
235 #ifdef WINDOWS_VST_SUPPORT
236 if (Config->get_use_windows_vst()) {
237 BootMessage (_("Scanning Windows VST Plugins"));
238 windows_vst_refresh (cache_only);
240 #endif // WINDOWS_VST_SUPPORT
243 if(Config->get_use_lxvst()) {
244 BootMessage (_("Scanning Linux VST Plugins"));
245 lxvst_refresh(cache_only);
247 #endif //Native linuxVST SUPPORT
249 #ifdef AUDIOUNIT_SUPPORT
250 BootMessage (_("Scanning AU Plugins"));
251 au_refresh (cache_only);
254 BootMessage (_("Plugin Scan Complete..."));
255 PluginListChanged (); /* EMIT SIGNAL */
256 PluginScanMessage(X_("closeme"), "", false);
257 _cancel_scan = false;
261 PluginManager::cancel_plugin_scan ()
267 PluginManager::cancel_plugin_timeout ()
269 _cancel_timeout = true;
273 PluginManager::clear_vst_cache ()
275 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
276 #ifdef WINDOWS_VST_SUPPORT
278 vector<string> fsi_files;
279 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$");
280 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
281 ::g_unlink(i->c_str());
288 vector<string> fsi_files;
289 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$");
290 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
291 ::g_unlink(i->c_str());
296 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
298 string personal = get_personal_vst_info_cache_dir();
299 vector<string> fsi_files;
300 find_files_matching_regex (fsi_files, personal, "\\.fsi$");
301 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
302 ::g_unlink(i->c_str());
309 PluginManager::clear_vst_blacklist ()
311 #ifdef WINDOWS_VST_SUPPORT
313 vector<string> fsi_files;
314 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsb$");
315 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
316 ::g_unlink(i->c_str());
323 vector<string> fsi_files;
324 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsb$");
325 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
326 ::g_unlink(i->c_str());
331 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
333 string personal = get_personal_vst_blacklist_dir();
335 vector<string> fsi_files;
336 find_files_matching_regex (fsi_files, personal, "\\.fsb$");
337 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
338 ::g_unlink(i->c_str());
345 PluginManager::ladspa_refresh ()
347 if (_ladspa_plugin_info) {
348 _ladspa_plugin_info->clear ();
350 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
353 /* allow LADSPA_PATH to augment, not override standard locations */
355 /* Only add standard locations to ladspa_path if it doesn't
356 * already contain them. Check for trailing G_DIR_SEPARATOR too.
359 vector<string> ladspa_modules;
361 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
363 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
364 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
365 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
367 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
368 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
369 ladspa_discover (*i);
373 static bool rdf_filter (const string &str, void* /*arg*/)
375 return str[0] != '.' &&
376 ((str.find(".rdf") == (str.length() - 4)) ||
377 (str.find(".rdfs") == (str.length() - 5)) ||
378 (str.find(".n3") == (str.length() - 3)) ||
379 (str.find(".ttl") == (str.length() - 4)));
383 PluginManager::add_ladspa_presets()
385 add_presets ("ladspa");
389 PluginManager::add_windows_vst_presets()
391 add_presets ("windows-vst");
395 PluginManager::add_lxvst_presets()
397 add_presets ("lxvst");
401 PluginManager::add_presets(string domain)
404 vector<string> presets;
405 vector<string>::iterator x;
408 if ((envvar = getenv ("HOME")) == 0) {
412 string path = string_compose("%1/.%2/rdf", envvar, domain);
413 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
415 for (x = presets.begin(); x != presets.end (); ++x) {
416 string file = "file:" + *x;
417 if (lrdf_read_file(file.c_str())) {
418 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
426 PluginManager::add_lrdf_data (const string &path)
429 vector<string> rdf_files;
430 vector<string>::iterator x;
432 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
434 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
435 const string uri(string("file://") + *x);
437 if (lrdf_read_file(uri.c_str())) {
438 warning << "Could not parse rdf file: " << uri << endmsg;
445 PluginManager::ladspa_discover (string path)
447 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
449 Glib::Module module(path);
450 const LADSPA_Descriptor *descriptor;
451 LADSPA_Descriptor_Function dfunc;
455 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
456 path, Glib::Module::get_last_error()) << endmsg;
461 if (!module.get_symbol("ladspa_descriptor", func)) {
462 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
463 error << Glib::Module::get_last_error() << endmsg;
467 dfunc = (LADSPA_Descriptor_Function)func;
469 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
471 for (uint32_t i = 0; ; ++i) {
472 if ((descriptor = dfunc (i)) == 0) {
476 if (!ladspa_plugin_whitelist.empty()) {
477 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
482 PluginInfoPtr info(new LadspaPluginInfo);
483 info->name = descriptor->Name;
484 info->category = get_ladspa_category(descriptor->UniqueID);
485 info->creator = descriptor->Maker;
488 info->n_inputs = ChanCount();
489 info->n_outputs = ChanCount();
490 info->type = ARDOUR::LADSPA;
493 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
494 info->unique_id = buf;
496 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
497 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
498 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
499 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
501 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
502 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
507 if(_ladspa_plugin_info->empty()){
508 _ladspa_plugin_info->push_back (info);
511 //Ensure that the plugin is not already in the plugin list.
515 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
516 if(0 == info->unique_id.compare((*i)->unique_id)){
522 _ladspa_plugin_info->push_back (info);
525 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
528 // GDB WILL NOT LIKE YOU IF YOU DO THIS
535 PluginManager::get_ladspa_category (uint32_t plugin_id)
539 lrdf_statement pattern;
541 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
542 pattern.subject = buf;
543 pattern.predicate = const_cast<char*>(RDF_TYPE);
545 pattern.object_type = lrdf_uri;
547 lrdf_statement* matches1 = lrdf_matches (&pattern);
553 pattern.subject = matches1->object;
554 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
556 pattern.object_type = lrdf_literal;
558 lrdf_statement* matches2 = lrdf_matches (&pattern);
559 lrdf_free_statements(matches1);
565 string label = matches2->object;
566 lrdf_free_statements(matches2);
568 /* Kludge LADSPA class names to be singular and match LV2 class names.
569 This avoids duplicate plugin menus for every class, which is necessary
570 to make the plugin category menu at all usable, but is obviously a
573 In the short term, lrdf could be updated so the labels match and a new
574 release made. To support both specs, we should probably be mapping the
575 URIs to the same category in code and perhaps tweaking that hierarchy
576 dynamically to suit the user. Personally, I (drobilla) think that time
577 is better spent replacing the little-used LRDF.
579 In the longer term, we will abandon LRDF entirely in favour of LV2 and
580 use that class hierarchy. Aside from fixing this problem properly, that
581 will also allow for translated labels. SWH plugins have been LV2 for
582 ages; TAP needs porting. I don't know of anything else with LRDF data.
584 if (label == "Utilities") {
586 } else if (label == "Pitch shifters") {
587 return "Pitch Shifter";
588 } else if (label != "Dynamics" && label != "Chorus"
589 &&label[label.length() - 1] == 's'
590 && label[label.length() - 2] != 's') {
591 return label.substr(0, label.length() - 1);
602 PluginManager::lv2_refresh ()
604 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
605 delete _lv2_plugin_info;
606 _lv2_plugin_info = LV2PluginInfo::discover();
610 #ifdef AUDIOUNIT_SUPPORT
612 PluginManager::au_refresh (bool cache_only)
614 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
615 if (cache_only && !Config->get_discover_audio_units ()) {
618 delete _au_plugin_info;
620 // disable automatic scan in case we crash
621 Config->set_discover_audio_units (false);
622 Config->save_state();
624 _au_plugin_info = AUPluginInfo::discover();
626 // successful scan re-enabled automatic discovery
627 Config->set_discover_audio_units (true);
628 Config->save_state();
633 #ifdef WINDOWS_VST_SUPPORT
636 PluginManager::windows_vst_refresh (bool cache_only)
638 if (_windows_vst_plugin_info) {
639 _windows_vst_plugin_info->clear ();
641 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
644 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
647 static bool windows_vst_filter (const string& str, void * /*arg*/)
649 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
651 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
655 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
657 vector<string> plugin_objects;
658 vector<string>::iterator x;
661 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
663 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
665 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
666 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
667 windows_vst_discover (*x, cache_only || cancelled());
674 PluginManager::windows_vst_discover (string path, bool cache_only)
676 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
678 _cancel_timeout = false;
679 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
680 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
682 if (finfos->empty()) {
683 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
687 uint32_t discovered = 0;
688 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
692 if (!finfo->canProcessReplacing) {
693 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
694 finfo->name, PROGRAM_NAME)
699 PluginInfoPtr info (new WindowsVSTPluginInfo);
701 /* what a joke freeware VST is */
703 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
704 info->name = PBD::basename_nosuffix (path);
706 info->name = finfo->name;
710 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
711 info->unique_id = buf;
712 info->category = "VST";
714 info->creator = finfo->creator;
716 info->n_inputs.set_audio (finfo->numInputs);
717 info->n_outputs.set_audio (finfo->numOutputs);
718 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
719 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
720 info->type = ARDOUR::Windows_VST;
722 // TODO: check dup-IDs (lxvst AND windows vst)
723 bool duplicate = false;
725 if (!_windows_vst_plugin_info->empty()) {
726 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
727 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
728 warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
736 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
737 _windows_vst_plugin_info->push_back (info);
742 vstfx_free_info_list (finfos);
743 return discovered > 0 ? 0 : -1;
746 #endif // WINDOWS_VST_SUPPORT
751 PluginManager::lxvst_refresh (bool cache_only)
753 if (_lxvst_plugin_info) {
754 _lxvst_plugin_info->clear ();
756 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
759 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
762 static bool lxvst_filter (const string& str, void *)
764 /* Not a dotfile, has a prefix before a period, suffix is "so" */
766 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
770 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
772 vector<string> plugin_objects;
773 vector<string>::iterator x;
780 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
782 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
784 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
785 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
786 lxvst_discover (*x, cache_only || cancelled());
793 PluginManager::lxvst_discover (string path, bool cache_only)
795 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
797 _cancel_timeout = false;
798 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
799 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
801 if (finfos->empty()) {
802 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
806 uint32_t discovered = 0;
807 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
811 if (!finfo->canProcessReplacing) {
812 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
813 finfo->name, PROGRAM_NAME)
818 PluginInfoPtr info(new LXVSTPluginInfo);
820 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
821 info->name = PBD::basename_nosuffix (path);
823 info->name = finfo->name;
827 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
828 info->unique_id = buf;
829 info->category = "linuxVSTs";
831 info->creator = finfo->creator;
833 info->n_inputs.set_audio (finfo->numInputs);
834 info->n_outputs.set_audio (finfo->numOutputs);
835 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
836 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
837 info->type = ARDOUR::LXVST;
839 /* Make sure we don't find the same plugin in more than one place along
840 the LXVST_PATH We can't use a simple 'find' because the path is included
841 in the PluginInfo, and that is the one thing we can be sure MUST be
842 different if a duplicate instance is found. So we just compare the type
843 and unique ID (which for some VSTs isn't actually unique...)
846 // TODO: check dup-IDs with windowsVST, too
847 bool duplicate = false;
848 if (!_lxvst_plugin_info->empty()) {
849 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
850 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
851 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
859 _lxvst_plugin_info->push_back (info);
864 vstfx_free_info_list (finfos);
865 return discovered > 0 ? 0 : -1;
868 #endif // LXVST_SUPPORT
871 PluginManager::PluginStatusType
872 PluginManager::get_status (const PluginInfoPtr& pi)
874 PluginStatus ps (pi->type, pi->unique_id);
875 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
876 if (i == statuses.end() ) {
884 PluginManager::save_statuses ()
887 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
889 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
895 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
907 ofs << "Windows-VST";
916 switch ((*i).status) {
929 ofs << (*i).unique_id;;
937 PluginManager::load_statuses ()
939 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
940 ifstream ifs (path.c_str());
950 PluginStatusType status;
967 /* rest of the line is the plugin ID */
969 ifs.getline (buf, sizeof (buf), '\n');
974 if (sstatus == "Normal") {
976 } else if (sstatus == "Favorite") {
978 } else if (sstatus == "Hidden") {
981 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
987 if (stype == "LADSPA") {
989 } else if (stype == "AudioUnit") {
991 } else if (stype == "LV2") {
993 } else if (stype == "Windows-VST") {
995 } else if (stype == "LXVST") {
998 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1004 strip_whitespace_edges (id);
1005 set_status (type, id, status);
1012 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1014 PluginStatus ps (t, id, status);
1015 statuses.erase (ps);
1017 if (status == Normal) {
1021 statuses.insert (ps);
1024 ARDOUR::PluginInfoList&
1025 PluginManager::windows_vst_plugin_info ()
1027 #ifdef WINDOWS_VST_SUPPORT
1028 if (!_windows_vst_plugin_info) {
1029 windows_vst_refresh ();
1031 return *_windows_vst_plugin_info;
1033 return _empty_plugin_info;
1037 ARDOUR::PluginInfoList&
1038 PluginManager::lxvst_plugin_info ()
1040 #ifdef LXVST_SUPPORT
1041 assert(_lxvst_plugin_info);
1042 return *_lxvst_plugin_info;
1044 return _empty_plugin_info;
1048 ARDOUR::PluginInfoList&
1049 PluginManager::ladspa_plugin_info ()
1051 assert(_ladspa_plugin_info);
1052 return *_ladspa_plugin_info;
1055 ARDOUR::PluginInfoList&
1056 PluginManager::lv2_plugin_info ()
1059 assert(_lv2_plugin_info);
1060 return *_lv2_plugin_info;
1062 return _empty_plugin_info;
1066 ARDOUR::PluginInfoList&
1067 PluginManager::au_plugin_info ()
1069 #ifdef AUDIOUNIT_SUPPORT
1070 if (_au_plugin_info) {
1071 return *_au_plugin_info;
1074 return _empty_plugin_info;