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>
52 #include <glibmm/fileutils.h>
53 #include <glibmm/miscutils.h>
55 #include "pbd/whitespace.h"
56 #include "pbd/file_utils.h"
58 #include "ardour/debug.h"
59 #include "ardour/filesystem_paths.h"
60 #include "ardour/ladspa.h"
61 #include "ardour/ladspa_plugin.h"
62 #include "ardour/plugin.h"
63 #include "ardour/plugin_manager.h"
64 #include "ardour/rc_configuration.h"
66 #include "ardour/search_paths.h"
69 #include "ardour/lv2_plugin.h"
72 #ifdef WINDOWS_VST_SUPPORT
73 #include "ardour/windows_vst_plugin.h"
77 #include "ardour/lxvst_plugin.h"
80 #ifdef AUDIOUNIT_SUPPORT
81 #include "ardour/audio_unit.h"
82 #include <Carbon/Carbon.h>
85 #include "pbd/error.h"
86 #include "pbd/stl_delete.h"
90 #include "ardour/debug.h"
92 using namespace ARDOUR;
96 PluginManager* PluginManager::_instance = 0;
97 std::string PluginManager::scanner_bin_path = "";
100 PluginManager::instance()
103 _instance = new PluginManager;
108 PluginManager::PluginManager ()
109 : _windows_vst_plugin_info(0)
110 , _lxvst_plugin_info(0)
111 , _ladspa_plugin_info(0)
112 , _lv2_plugin_info(0)
114 , _cancel_scan(false)
115 , _cancel_timeout(false)
120 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
121 // source-tree (ardev, etc)
122 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
124 #ifdef PLATFORM_WINDOWS
125 // on windows the .exe needs to be in the same folder with libardour.dll
126 vstsp += Glib::build_filename(g_win32_get_package_installation_directory_of_module (0), "bin");
128 // on Unices additional internal-use binaries are deployed to $libdir
129 vstsp += ARDOUR::ardour_dll_directory();
132 if (!PBD::find_file (vstsp,
133 #ifdef PLATFORM_WINDOWS
134 #ifdef DEBUGGABLE_SCANNER_APP
135 #if defined(DEBUG) || defined(_DEBUG)
136 "ardour-vst-scannerD.exe"
138 "ardour-vst-scannerRDC.exe"
141 "ardour-vst-scanner.exe"
146 , scanner_bin_path)) {
147 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
153 if ((s = getenv ("LADSPA_RDF_PATH"))){
157 if (lrdf_path.length() == 0) {
158 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
161 add_lrdf_data(lrdf_path);
162 add_ladspa_presets();
163 #ifdef WINDOWS_VST_SUPPORT
164 if (Config->get_use_windows_vst ()) {
165 add_windows_vst_presets ();
167 #endif /* WINDOWS_VST_SUPPORT */
170 if (Config->get_use_lxvst()) {
173 #endif /* Native LinuxVST support*/
175 if ((s = getenv ("VST_PATH"))) {
176 windows_vst_path = s;
177 } else if ((s = getenv ("VST_PLUGINS"))) {
178 windows_vst_path = s;
181 if (windows_vst_path.length() == 0) {
182 windows_vst_path = vst_search_path ();
185 if ((s = getenv ("LXVST_PATH"))) {
187 } else if ((s = getenv ("LXVST_PLUGINS"))) {
191 if (lxvst_path.length() == 0) {
192 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
193 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
194 "/usr/lib/vst:/usr/local/lib/vst";
197 /* first time setup, use 'default' path */
198 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
199 Config->set_plugin_path_lxvst(get_default_lxvst_path());
201 if (Config->get_plugin_path_vst() == X_("@default@")) {
202 Config->set_plugin_path_vst(get_default_windows_vst_path());
205 if (_instance == 0) {
209 BootMessage (_("Discovering Plugins"));
213 PluginManager::~PluginManager()
215 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
216 // don't bother, just exit quickly.
217 delete _windows_vst_plugin_info;
218 delete _lxvst_plugin_info;
219 delete _ladspa_plugin_info;
220 delete _lv2_plugin_info;
221 delete _au_plugin_info;
226 PluginManager::refresh (bool cache_only)
228 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
234 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
235 _cancel_scan = false;
237 BootMessage (_("Scanning LADSPA Plugins"));
240 BootMessage (_("Scanning LV2 Plugins"));
243 #ifdef WINDOWS_VST_SUPPORT
244 if (Config->get_use_windows_vst()) {
245 BootMessage (_("Scanning Windows VST Plugins"));
246 windows_vst_refresh (cache_only);
248 #endif // WINDOWS_VST_SUPPORT
251 if(Config->get_use_lxvst()) {
252 BootMessage (_("Scanning Linux VST Plugins"));
253 lxvst_refresh(cache_only);
255 #endif //Native linuxVST SUPPORT
257 #ifdef AUDIOUNIT_SUPPORT
258 BootMessage (_("Scanning AU Plugins"));
259 au_refresh (cache_only);
262 BootMessage (_("Plugin Scan Complete..."));
263 PluginListChanged (); /* EMIT SIGNAL */
264 PluginScanMessage(X_("closeme"), "", false);
265 _cancel_scan = false;
269 PluginManager::cancel_plugin_scan ()
275 PluginManager::cancel_plugin_timeout ()
277 _cancel_timeout = true;
281 PluginManager::clear_vst_cache ()
283 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
284 #ifdef WINDOWS_VST_SUPPORT
286 vector<string> fsi_files;
287 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
288 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
289 ::g_unlink(i->c_str());
296 vector<string> fsi_files;
297 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
298 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
299 ::g_unlink(i->c_str());
304 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
306 string personal = get_personal_vst_info_cache_dir();
307 vector<string> fsi_files;
308 find_files_matching_regex (fsi_files, personal, "\\.fsi$", /* user cache is flat, no recursion */ false);
309 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
310 ::g_unlink(i->c_str());
317 PluginManager::clear_vst_blacklist ()
319 #ifdef WINDOWS_VST_SUPPORT
321 vector<string> fsi_files;
322 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
323 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
324 ::g_unlink(i->c_str());
331 vector<string> fsi_files;
332 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
333 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
334 ::g_unlink(i->c_str());
339 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
341 string personal = get_personal_vst_blacklist_dir();
343 vector<string> fsi_files;
344 find_files_matching_regex (fsi_files, personal, "\\" VST_EXT_BLACKLIST "$", /* flat user cache */ false);
345 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
346 ::g_unlink(i->c_str());
353 PluginManager::clear_au_cache ()
355 #ifdef AUDIOUNIT_SUPPORT
356 // AUPluginInfo::au_cache_path ()
357 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
358 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
359 ::g_unlink(fn.c_str());
365 PluginManager::clear_au_blacklist ()
367 #ifdef AUDIOUNIT_SUPPORT
368 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
369 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
370 ::g_unlink(fn.c_str());
376 PluginManager::ladspa_refresh ()
378 if (_ladspa_plugin_info) {
379 _ladspa_plugin_info->clear ();
381 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
384 /* allow LADSPA_PATH to augment, not override standard locations */
386 /* Only add standard locations to ladspa_path if it doesn't
387 * already contain them. Check for trailing G_DIR_SEPARATOR too.
390 vector<string> ladspa_modules;
392 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
394 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
395 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
396 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
398 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
399 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
400 ladspa_discover (*i);
405 static bool rdf_filter (const string &str, void* /*arg*/)
407 return str[0] != '.' &&
408 ((str.find(".rdf") == (str.length() - 4)) ||
409 (str.find(".rdfs") == (str.length() - 5)) ||
410 (str.find(".n3") == (str.length() - 3)) ||
411 (str.find(".ttl") == (str.length() - 4)));
416 PluginManager::add_ladspa_presets()
418 add_presets ("ladspa");
422 PluginManager::add_windows_vst_presets()
424 add_presets ("windows-vst");
428 PluginManager::add_lxvst_presets()
430 add_presets ("lxvst");
434 PluginManager::add_presets(string domain)
437 vector<string> presets;
438 vector<string>::iterator x;
441 if ((envvar = getenv ("HOME")) == 0) {
445 string path = string_compose("%1/.%2/rdf", envvar, domain);
446 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
448 for (x = presets.begin(); x != presets.end (); ++x) {
449 string file = "file:" + *x;
450 if (lrdf_read_file(file.c_str())) {
451 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
459 PluginManager::add_lrdf_data (const string &path)
462 vector<string> rdf_files;
463 vector<string>::iterator x;
465 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
467 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
468 const string uri(string("file://") + *x);
470 if (lrdf_read_file(uri.c_str())) {
471 warning << "Could not parse rdf file: " << uri << endmsg;
478 PluginManager::ladspa_discover (string path)
480 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
482 Glib::Module module(path);
483 const LADSPA_Descriptor *descriptor;
484 LADSPA_Descriptor_Function dfunc;
488 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
489 path, Glib::Module::get_last_error()) << endmsg;
494 if (!module.get_symbol("ladspa_descriptor", func)) {
495 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
496 error << Glib::Module::get_last_error() << endmsg;
500 dfunc = (LADSPA_Descriptor_Function)func;
502 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
504 for (uint32_t i = 0; ; ++i) {
505 if ((descriptor = dfunc (i)) == 0) {
509 if (!ladspa_plugin_whitelist.empty()) {
510 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
515 PluginInfoPtr info(new LadspaPluginInfo);
516 info->name = descriptor->Name;
517 info->category = get_ladspa_category(descriptor->UniqueID);
518 info->creator = descriptor->Maker;
521 info->n_inputs = ChanCount();
522 info->n_outputs = ChanCount();
523 info->type = ARDOUR::LADSPA;
526 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
527 info->unique_id = buf;
529 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
530 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
531 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
532 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
534 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
535 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
540 if(_ladspa_plugin_info->empty()){
541 _ladspa_plugin_info->push_back (info);
544 //Ensure that the plugin is not already in the plugin list.
548 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
549 if(0 == info->unique_id.compare((*i)->unique_id)){
555 _ladspa_plugin_info->push_back (info);
558 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
561 // GDB WILL NOT LIKE YOU IF YOU DO THIS
568 PluginManager::get_ladspa_category (uint32_t plugin_id)
572 lrdf_statement pattern;
574 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
575 pattern.subject = buf;
576 pattern.predicate = const_cast<char*>(RDF_TYPE);
578 pattern.object_type = lrdf_uri;
580 lrdf_statement* matches1 = lrdf_matches (&pattern);
586 pattern.subject = matches1->object;
587 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
589 pattern.object_type = lrdf_literal;
591 lrdf_statement* matches2 = lrdf_matches (&pattern);
592 lrdf_free_statements(matches1);
598 string label = matches2->object;
599 lrdf_free_statements(matches2);
601 /* Kludge LADSPA class names to be singular and match LV2 class names.
602 This avoids duplicate plugin menus for every class, which is necessary
603 to make the plugin category menu at all usable, but is obviously a
606 In the short term, lrdf could be updated so the labels match and a new
607 release made. To support both specs, we should probably be mapping the
608 URIs to the same category in code and perhaps tweaking that hierarchy
609 dynamically to suit the user. Personally, I (drobilla) think that time
610 is better spent replacing the little-used LRDF.
612 In the longer term, we will abandon LRDF entirely in favour of LV2 and
613 use that class hierarchy. Aside from fixing this problem properly, that
614 will also allow for translated labels. SWH plugins have been LV2 for
615 ages; TAP needs porting. I don't know of anything else with LRDF data.
617 if (label == "Utilities") {
619 } else if (label == "Pitch shifters") {
620 return "Pitch Shifter";
621 } else if (label != "Dynamics" && label != "Chorus"
622 &&label[label.length() - 1] == 's'
623 && label[label.length() - 2] != 's') {
624 return label.substr(0, label.length() - 1);
635 PluginManager::lv2_refresh ()
637 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
638 delete _lv2_plugin_info;
639 _lv2_plugin_info = LV2PluginInfo::discover();
643 #ifdef AUDIOUNIT_SUPPORT
645 PluginManager::au_refresh (bool cache_only)
647 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
649 // disable automatic discovery in case we crash
650 bool discover_at_start = Config->get_discover_audio_units ();
651 Config->set_discover_audio_units (false);
652 Config->save_state();
654 delete _au_plugin_info;
655 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
657 // successful scan re-enabled automatic discovery if it was set
658 Config->set_discover_audio_units (discover_at_start);
659 Config->save_state();
664 #ifdef WINDOWS_VST_SUPPORT
667 PluginManager::windows_vst_refresh (bool cache_only)
669 if (_windows_vst_plugin_info) {
670 _windows_vst_plugin_info->clear ();
672 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
675 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
678 static bool windows_vst_filter (const string& str, void * /*arg*/)
680 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
681 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
685 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
687 vector<string> plugin_objects;
688 vector<string>::iterator x;
691 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
693 if (Config->get_verbose_plugin_scan()) {
694 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
697 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
699 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
700 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
701 windows_vst_discover (*x, cache_only || cancelled());
704 if (Config->get_verbose_plugin_scan()) {
705 info << _("--- Windows VST plugins Scan Done") << endmsg;
712 PluginManager::windows_vst_discover (string path, bool cache_only)
714 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
716 if (Config->get_verbose_plugin_scan()) {
717 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
720 _cancel_timeout = false;
721 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
722 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
724 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
725 // .err file scanner output etc.
727 if (finfos->empty()) {
728 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
729 if (Config->get_verbose_plugin_scan()) {
730 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
735 uint32_t discovered = 0;
736 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
740 if (!finfo->canProcessReplacing) {
741 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
742 finfo->name, PROGRAM_NAME)
747 PluginInfoPtr info (new WindowsVSTPluginInfo);
749 /* what a joke freeware VST is */
751 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
752 info->name = PBD::basename_nosuffix (path);
754 info->name = finfo->name;
758 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
759 info->unique_id = buf;
760 info->category = "VST";
762 info->creator = finfo->creator;
764 info->n_inputs.set_audio (finfo->numInputs);
765 info->n_outputs.set_audio (finfo->numOutputs);
766 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
767 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
768 info->type = ARDOUR::Windows_VST;
770 // TODO: check dup-IDs (lxvst AND windows vst)
771 bool duplicate = false;
773 if (!_windows_vst_plugin_info->empty()) {
774 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
775 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
776 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
784 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
785 _windows_vst_plugin_info->push_back (info);
787 if (Config->get_verbose_plugin_scan()) {
788 PBD::info << string_compose (_(" -> OK. (VST Plugin \"%1\" added)."), info->name) << endmsg;
793 vstfx_free_info_list (finfos);
794 return discovered > 0 ? 0 : -1;
797 #endif // WINDOWS_VST_SUPPORT
802 PluginManager::lxvst_refresh (bool cache_only)
804 if (_lxvst_plugin_info) {
805 _lxvst_plugin_info->clear ();
807 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
810 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
813 static bool lxvst_filter (const string& str, void *)
815 /* Not a dotfile, has a prefix before a period, suffix is "so" */
817 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
821 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
823 vector<string> plugin_objects;
824 vector<string>::iterator x;
831 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
833 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
835 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
836 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
837 lxvst_discover (*x, cache_only || cancelled());
844 PluginManager::lxvst_discover (string path, bool cache_only)
846 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
848 _cancel_timeout = false;
849 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
850 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
852 if (finfos->empty()) {
853 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
857 uint32_t discovered = 0;
858 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
862 if (!finfo->canProcessReplacing) {
863 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
864 finfo->name, PROGRAM_NAME)
869 PluginInfoPtr info(new LXVSTPluginInfo);
871 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
872 info->name = PBD::basename_nosuffix (path);
874 info->name = finfo->name;
878 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
879 info->unique_id = buf;
880 info->category = "linuxVSTs";
882 info->creator = finfo->creator;
884 info->n_inputs.set_audio (finfo->numInputs);
885 info->n_outputs.set_audio (finfo->numOutputs);
886 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
887 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
888 info->type = ARDOUR::LXVST;
890 /* Make sure we don't find the same plugin in more than one place along
891 the LXVST_PATH We can't use a simple 'find' because the path is included
892 in the PluginInfo, and that is the one thing we can be sure MUST be
893 different if a duplicate instance is found. So we just compare the type
894 and unique ID (which for some VSTs isn't actually unique...)
897 // TODO: check dup-IDs with windowsVST, too
898 bool duplicate = false;
899 if (!_lxvst_plugin_info->empty()) {
900 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
901 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
902 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
910 _lxvst_plugin_info->push_back (info);
915 vstfx_free_info_list (finfos);
916 return discovered > 0 ? 0 : -1;
919 #endif // LXVST_SUPPORT
922 PluginManager::PluginStatusType
923 PluginManager::get_status (const PluginInfoPtr& pi)
925 PluginStatus ps (pi->type, pi->unique_id);
926 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
927 if (i == statuses.end() ) {
935 PluginManager::save_statuses ()
938 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
940 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
946 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
958 ofs << "Windows-VST";
967 switch ((*i).status) {
980 ofs << (*i).unique_id;;
988 PluginManager::load_statuses ()
990 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
991 ifstream ifs (path.c_str());
1001 PluginStatusType status;
1018 /* rest of the line is the plugin ID */
1020 ifs.getline (buf, sizeof (buf), '\n');
1025 if (sstatus == "Normal") {
1027 } else if (sstatus == "Favorite") {
1029 } else if (sstatus == "Hidden") {
1032 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1038 if (stype == "LADSPA") {
1040 } else if (stype == "AudioUnit") {
1042 } else if (stype == "LV2") {
1044 } else if (stype == "Windows-VST") {
1046 } else if (stype == "LXVST") {
1049 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1055 strip_whitespace_edges (id);
1056 set_status (type, id, status);
1063 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1065 PluginStatus ps (t, id, status);
1066 statuses.erase (ps);
1068 if (status == Normal) {
1072 statuses.insert (ps);
1075 ARDOUR::PluginInfoList&
1076 PluginManager::windows_vst_plugin_info ()
1078 #ifdef WINDOWS_VST_SUPPORT
1079 if (!_windows_vst_plugin_info) {
1080 windows_vst_refresh ();
1082 return *_windows_vst_plugin_info;
1084 return _empty_plugin_info;
1088 ARDOUR::PluginInfoList&
1089 PluginManager::lxvst_plugin_info ()
1091 #ifdef LXVST_SUPPORT
1092 assert(_lxvst_plugin_info);
1093 return *_lxvst_plugin_info;
1095 return _empty_plugin_info;
1099 ARDOUR::PluginInfoList&
1100 PluginManager::ladspa_plugin_info ()
1102 assert(_ladspa_plugin_info);
1103 return *_ladspa_plugin_info;
1106 ARDOUR::PluginInfoList&
1107 PluginManager::lv2_plugin_info ()
1110 assert(_lv2_plugin_info);
1111 return *_lv2_plugin_info;
1113 return _empty_plugin_info;
1117 ARDOUR::PluginInfoList&
1118 PluginManager::au_plugin_info ()
1120 #ifdef AUDIOUNIT_SUPPORT
1121 if (_au_plugin_info) {
1122 return *_au_plugin_info;
1125 return _empty_plugin_info;