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);
374 static bool rdf_filter (const string &str, void* /*arg*/)
376 return str[0] != '.' &&
377 ((str.find(".rdf") == (str.length() - 4)) ||
378 (str.find(".rdfs") == (str.length() - 5)) ||
379 (str.find(".n3") == (str.length() - 3)) ||
380 (str.find(".ttl") == (str.length() - 4)));
385 PluginManager::add_ladspa_presets()
387 add_presets ("ladspa");
391 PluginManager::add_windows_vst_presets()
393 add_presets ("windows-vst");
397 PluginManager::add_lxvst_presets()
399 add_presets ("lxvst");
403 PluginManager::add_presets(string domain)
406 vector<string> presets;
407 vector<string>::iterator x;
410 if ((envvar = getenv ("HOME")) == 0) {
414 string path = string_compose("%1/.%2/rdf", envvar, domain);
415 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
417 for (x = presets.begin(); x != presets.end (); ++x) {
418 string file = "file:" + *x;
419 if (lrdf_read_file(file.c_str())) {
420 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
428 PluginManager::add_lrdf_data (const string &path)
431 vector<string> rdf_files;
432 vector<string>::iterator x;
434 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
436 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
437 const string uri(string("file://") + *x);
439 if (lrdf_read_file(uri.c_str())) {
440 warning << "Could not parse rdf file: " << uri << endmsg;
447 PluginManager::ladspa_discover (string path)
449 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
451 Glib::Module module(path);
452 const LADSPA_Descriptor *descriptor;
453 LADSPA_Descriptor_Function dfunc;
457 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
458 path, Glib::Module::get_last_error()) << endmsg;
463 if (!module.get_symbol("ladspa_descriptor", func)) {
464 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
465 error << Glib::Module::get_last_error() << endmsg;
469 dfunc = (LADSPA_Descriptor_Function)func;
471 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
473 for (uint32_t i = 0; ; ++i) {
474 if ((descriptor = dfunc (i)) == 0) {
478 if (!ladspa_plugin_whitelist.empty()) {
479 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
484 PluginInfoPtr info(new LadspaPluginInfo);
485 info->name = descriptor->Name;
486 info->category = get_ladspa_category(descriptor->UniqueID);
487 info->creator = descriptor->Maker;
490 info->n_inputs = ChanCount();
491 info->n_outputs = ChanCount();
492 info->type = ARDOUR::LADSPA;
495 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
496 info->unique_id = buf;
498 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
499 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
500 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
501 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
503 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
504 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
509 if(_ladspa_plugin_info->empty()){
510 _ladspa_plugin_info->push_back (info);
513 //Ensure that the plugin is not already in the plugin list.
517 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
518 if(0 == info->unique_id.compare((*i)->unique_id)){
524 _ladspa_plugin_info->push_back (info);
527 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
530 // GDB WILL NOT LIKE YOU IF YOU DO THIS
537 PluginManager::get_ladspa_category (uint32_t plugin_id)
541 lrdf_statement pattern;
543 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
544 pattern.subject = buf;
545 pattern.predicate = const_cast<char*>(RDF_TYPE);
547 pattern.object_type = lrdf_uri;
549 lrdf_statement* matches1 = lrdf_matches (&pattern);
555 pattern.subject = matches1->object;
556 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
558 pattern.object_type = lrdf_literal;
560 lrdf_statement* matches2 = lrdf_matches (&pattern);
561 lrdf_free_statements(matches1);
567 string label = matches2->object;
568 lrdf_free_statements(matches2);
570 /* Kludge LADSPA class names to be singular and match LV2 class names.
571 This avoids duplicate plugin menus for every class, which is necessary
572 to make the plugin category menu at all usable, but is obviously a
575 In the short term, lrdf could be updated so the labels match and a new
576 release made. To support both specs, we should probably be mapping the
577 URIs to the same category in code and perhaps tweaking that hierarchy
578 dynamically to suit the user. Personally, I (drobilla) think that time
579 is better spent replacing the little-used LRDF.
581 In the longer term, we will abandon LRDF entirely in favour of LV2 and
582 use that class hierarchy. Aside from fixing this problem properly, that
583 will also allow for translated labels. SWH plugins have been LV2 for
584 ages; TAP needs porting. I don't know of anything else with LRDF data.
586 if (label == "Utilities") {
588 } else if (label == "Pitch shifters") {
589 return "Pitch Shifter";
590 } else if (label != "Dynamics" && label != "Chorus"
591 &&label[label.length() - 1] == 's'
592 && label[label.length() - 2] != 's') {
593 return label.substr(0, label.length() - 1);
604 PluginManager::lv2_refresh ()
606 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
607 delete _lv2_plugin_info;
608 _lv2_plugin_info = LV2PluginInfo::discover();
612 #ifdef AUDIOUNIT_SUPPORT
614 PluginManager::au_refresh (bool cache_only)
616 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
617 if (cache_only && !Config->get_discover_audio_units ()) {
620 delete _au_plugin_info;
622 // disable automatic scan in case we crash
623 Config->set_discover_audio_units (false);
624 Config->save_state();
626 _au_plugin_info = AUPluginInfo::discover();
628 // successful scan re-enabled automatic discovery
629 Config->set_discover_audio_units (true);
630 Config->save_state();
635 #ifdef WINDOWS_VST_SUPPORT
638 PluginManager::windows_vst_refresh (bool cache_only)
640 if (_windows_vst_plugin_info) {
641 _windows_vst_plugin_info->clear ();
643 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
646 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
649 static bool windows_vst_filter (const string& str, void * /*arg*/)
651 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
653 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
657 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
659 vector<string> plugin_objects;
660 vector<string>::iterator x;
663 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
665 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
667 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
668 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
669 windows_vst_discover (*x, cache_only || cancelled());
676 PluginManager::windows_vst_discover (string path, bool cache_only)
678 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
680 _cancel_timeout = false;
681 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
682 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
684 if (finfos->empty()) {
685 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
689 uint32_t discovered = 0;
690 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
694 if (!finfo->canProcessReplacing) {
695 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
696 finfo->name, PROGRAM_NAME)
701 PluginInfoPtr info (new WindowsVSTPluginInfo);
703 /* what a joke freeware VST is */
705 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
706 info->name = PBD::basename_nosuffix (path);
708 info->name = finfo->name;
712 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
713 info->unique_id = buf;
714 info->category = "VST";
716 info->creator = finfo->creator;
718 info->n_inputs.set_audio (finfo->numInputs);
719 info->n_outputs.set_audio (finfo->numOutputs);
720 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
721 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 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 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
764 static bool lxvst_filter (const string& str, void *)
766 /* Not a dotfile, has a prefix before a period, suffix is "so" */
768 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
772 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
774 vector<string> plugin_objects;
775 vector<string>::iterator x;
782 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
784 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
786 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
787 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
788 lxvst_discover (*x, cache_only || cancelled());
795 PluginManager::lxvst_discover (string path, bool cache_only)
797 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
799 _cancel_timeout = false;
800 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
801 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
803 if (finfos->empty()) {
804 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
808 uint32_t discovered = 0;
809 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
813 if (!finfo->canProcessReplacing) {
814 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
815 finfo->name, PROGRAM_NAME)
820 PluginInfoPtr info(new LXVSTPluginInfo);
822 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
823 info->name = PBD::basename_nosuffix (path);
825 info->name = finfo->name;
829 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
830 info->unique_id = buf;
831 info->category = "linuxVSTs";
833 info->creator = finfo->creator;
835 info->n_inputs.set_audio (finfo->numInputs);
836 info->n_outputs.set_audio (finfo->numOutputs);
837 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
838 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
839 info->type = ARDOUR::LXVST;
841 /* Make sure we don't find the same plugin in more than one place along
842 the LXVST_PATH We can't use a simple 'find' because the path is included
843 in the PluginInfo, and that is the one thing we can be sure MUST be
844 different if a duplicate instance is found. So we just compare the type
845 and unique ID (which for some VSTs isn't actually unique...)
848 // TODO: check dup-IDs with windowsVST, too
849 bool duplicate = false;
850 if (!_lxvst_plugin_info->empty()) {
851 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
852 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
853 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
861 _lxvst_plugin_info->push_back (info);
866 vstfx_free_info_list (finfos);
867 return discovered > 0 ? 0 : -1;
870 #endif // LXVST_SUPPORT
873 PluginManager::PluginStatusType
874 PluginManager::get_status (const PluginInfoPtr& pi)
876 PluginStatus ps (pi->type, pi->unique_id);
877 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
878 if (i == statuses.end() ) {
886 PluginManager::save_statuses ()
889 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
891 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
897 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
909 ofs << "Windows-VST";
918 switch ((*i).status) {
931 ofs << (*i).unique_id;;
939 PluginManager::load_statuses ()
941 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
942 ifstream ifs (path.c_str());
952 PluginStatusType status;
969 /* rest of the line is the plugin ID */
971 ifs.getline (buf, sizeof (buf), '\n');
976 if (sstatus == "Normal") {
978 } else if (sstatus == "Favorite") {
980 } else if (sstatus == "Hidden") {
983 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
989 if (stype == "LADSPA") {
991 } else if (stype == "AudioUnit") {
993 } else if (stype == "LV2") {
995 } else if (stype == "Windows-VST") {
997 } else if (stype == "LXVST") {
1000 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1006 strip_whitespace_edges (id);
1007 set_status (type, id, status);
1014 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1016 PluginStatus ps (t, id, status);
1017 statuses.erase (ps);
1019 if (status == Normal) {
1023 statuses.insert (ps);
1026 ARDOUR::PluginInfoList&
1027 PluginManager::windows_vst_plugin_info ()
1029 #ifdef WINDOWS_VST_SUPPORT
1030 if (!_windows_vst_plugin_info) {
1031 windows_vst_refresh ();
1033 return *_windows_vst_plugin_info;
1035 return _empty_plugin_info;
1039 ARDOUR::PluginInfoList&
1040 PluginManager::lxvst_plugin_info ()
1042 #ifdef LXVST_SUPPORT
1043 assert(_lxvst_plugin_info);
1044 return *_lxvst_plugin_info;
1046 return _empty_plugin_info;
1050 ARDOUR::PluginInfoList&
1051 PluginManager::ladspa_plugin_info ()
1053 assert(_ladspa_plugin_info);
1054 return *_ladspa_plugin_info;
1057 ARDOUR::PluginInfoList&
1058 PluginManager::lv2_plugin_info ()
1061 assert(_lv2_plugin_info);
1062 return *_lv2_plugin_info;
1064 return _empty_plugin_info;
1068 ARDOUR::PluginInfoList&
1069 PluginManager::au_plugin_info ()
1071 #ifdef AUDIOUNIT_SUPPORT
1072 if (_au_plugin_info) {
1073 return *_au_plugin_info;
1076 return _empty_plugin_info;