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()) {
246 BootMessage (_("Scanning Windows VST Plugins"));
248 BootMessage (_("Discovering Windows VST Plugins"));
250 windows_vst_refresh (cache_only);
252 #endif // WINDOWS_VST_SUPPORT
255 if(Config->get_use_lxvst()) {
257 BootMessage (_("Scanning Linux VST Plugins"));
259 BootMessage (_("Discovering Linux VST Plugins"));
261 lxvst_refresh(cache_only);
263 #endif //Native linuxVST SUPPORT
265 #ifdef AUDIOUNIT_SUPPORT
267 BootMessage (_("Scanning AU Plugins"));
269 BootMessage (_("Discovering AU Plugins"));
271 au_refresh (cache_only);
274 BootMessage (_("Plugin Scan Complete..."));
275 PluginListChanged (); /* EMIT SIGNAL */
276 PluginScanMessage(X_("closeme"), "", false);
277 _cancel_scan = false;
281 PluginManager::cancel_plugin_scan ()
287 PluginManager::cancel_plugin_timeout ()
289 _cancel_timeout = true;
293 PluginManager::clear_vst_cache ()
295 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
296 #ifdef WINDOWS_VST_SUPPORT
298 vector<string> fsi_files;
299 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
300 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
301 ::g_unlink(i->c_str());
308 vector<string> fsi_files;
309 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
310 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
311 ::g_unlink(i->c_str());
316 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
318 string personal = get_personal_vst_info_cache_dir();
319 vector<string> fsi_files;
320 find_files_matching_regex (fsi_files, personal, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
321 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
322 ::g_unlink(i->c_str());
329 PluginManager::clear_vst_blacklist ()
331 #ifdef WINDOWS_VST_SUPPORT
333 vector<string> fsi_files;
334 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
335 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
336 ::g_unlink(i->c_str());
343 vector<string> fsi_files;
344 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
345 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
346 ::g_unlink(i->c_str());
351 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
353 string personal = get_personal_vst_blacklist_dir();
355 vector<string> fsi_files;
356 find_files_matching_regex (fsi_files, personal, "\\" VST_EXT_BLACKLIST "$", /* flat user cache */ false);
357 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
358 ::g_unlink(i->c_str());
365 PluginManager::clear_au_cache ()
367 #ifdef AUDIOUNIT_SUPPORT
368 // AUPluginInfo::au_cache_path ()
369 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
370 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
371 ::g_unlink(fn.c_str());
377 PluginManager::clear_au_blacklist ()
379 #ifdef AUDIOUNIT_SUPPORT
380 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
381 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
382 ::g_unlink(fn.c_str());
388 PluginManager::ladspa_refresh ()
390 if (_ladspa_plugin_info) {
391 _ladspa_plugin_info->clear ();
393 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
396 /* allow LADSPA_PATH to augment, not override standard locations */
398 /* Only add standard locations to ladspa_path if it doesn't
399 * already contain them. Check for trailing G_DIR_SEPARATOR too.
402 vector<string> ladspa_modules;
404 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
406 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
407 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
408 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
410 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
411 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
412 ladspa_discover (*i);
417 static bool rdf_filter (const string &str, void* /*arg*/)
419 return str[0] != '.' &&
420 ((str.find(".rdf") == (str.length() - 4)) ||
421 (str.find(".rdfs") == (str.length() - 5)) ||
422 (str.find(".n3") == (str.length() - 3)) ||
423 (str.find(".ttl") == (str.length() - 4)));
428 PluginManager::add_ladspa_presets()
430 add_presets ("ladspa");
434 PluginManager::add_windows_vst_presets()
436 add_presets ("windows-vst");
440 PluginManager::add_lxvst_presets()
442 add_presets ("lxvst");
446 PluginManager::add_presets(string domain)
449 vector<string> presets;
450 vector<string>::iterator x;
453 if ((envvar = getenv ("HOME")) == 0) {
457 string path = string_compose("%1/.%2/rdf", envvar, domain);
458 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
460 for (x = presets.begin(); x != presets.end (); ++x) {
461 string file = "file:" + *x;
462 if (lrdf_read_file(file.c_str())) {
463 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
471 PluginManager::add_lrdf_data (const string &path)
474 vector<string> rdf_files;
475 vector<string>::iterator x;
477 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
479 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
480 const string uri(string("file://") + *x);
482 if (lrdf_read_file(uri.c_str())) {
483 warning << "Could not parse rdf file: " << uri << endmsg;
490 PluginManager::ladspa_discover (string path)
492 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
494 Glib::Module module(path);
495 const LADSPA_Descriptor *descriptor;
496 LADSPA_Descriptor_Function dfunc;
500 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
501 path, Glib::Module::get_last_error()) << endmsg;
506 if (!module.get_symbol("ladspa_descriptor", func)) {
507 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
508 error << Glib::Module::get_last_error() << endmsg;
512 dfunc = (LADSPA_Descriptor_Function)func;
514 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
516 for (uint32_t i = 0; ; ++i) {
517 if ((descriptor = dfunc (i)) == 0) {
521 if (!ladspa_plugin_whitelist.empty()) {
522 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
527 PluginInfoPtr info(new LadspaPluginInfo);
528 info->name = descriptor->Name;
529 info->category = get_ladspa_category(descriptor->UniqueID);
530 info->creator = descriptor->Maker;
533 info->n_inputs = ChanCount();
534 info->n_outputs = ChanCount();
535 info->type = ARDOUR::LADSPA;
538 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
539 info->unique_id = buf;
541 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
542 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
543 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
544 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
546 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
547 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
552 if(_ladspa_plugin_info->empty()){
553 _ladspa_plugin_info->push_back (info);
556 //Ensure that the plugin is not already in the plugin list.
560 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
561 if(0 == info->unique_id.compare((*i)->unique_id)){
567 _ladspa_plugin_info->push_back (info);
570 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
573 // GDB WILL NOT LIKE YOU IF YOU DO THIS
580 PluginManager::get_ladspa_category (uint32_t plugin_id)
584 lrdf_statement pattern;
586 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
587 pattern.subject = buf;
588 pattern.predicate = const_cast<char*>(RDF_TYPE);
590 pattern.object_type = lrdf_uri;
592 lrdf_statement* matches1 = lrdf_matches (&pattern);
598 pattern.subject = matches1->object;
599 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
601 pattern.object_type = lrdf_literal;
603 lrdf_statement* matches2 = lrdf_matches (&pattern);
604 lrdf_free_statements(matches1);
610 string label = matches2->object;
611 lrdf_free_statements(matches2);
613 /* Kludge LADSPA class names to be singular and match LV2 class names.
614 This avoids duplicate plugin menus for every class, which is necessary
615 to make the plugin category menu at all usable, but is obviously a
618 In the short term, lrdf could be updated so the labels match and a new
619 release made. To support both specs, we should probably be mapping the
620 URIs to the same category in code and perhaps tweaking that hierarchy
621 dynamically to suit the user. Personally, I (drobilla) think that time
622 is better spent replacing the little-used LRDF.
624 In the longer term, we will abandon LRDF entirely in favour of LV2 and
625 use that class hierarchy. Aside from fixing this problem properly, that
626 will also allow for translated labels. SWH plugins have been LV2 for
627 ages; TAP needs porting. I don't know of anything else with LRDF data.
629 if (label == "Utilities") {
631 } else if (label == "Pitch shifters") {
632 return "Pitch Shifter";
633 } else if (label != "Dynamics" && label != "Chorus"
634 &&label[label.length() - 1] == 's'
635 && label[label.length() - 2] != 's') {
636 return label.substr(0, label.length() - 1);
647 PluginManager::lv2_refresh ()
649 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
650 delete _lv2_plugin_info;
651 _lv2_plugin_info = LV2PluginInfo::discover();
655 #ifdef AUDIOUNIT_SUPPORT
657 PluginManager::au_refresh (bool cache_only)
659 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
661 // disable automatic discovery in case we crash
662 bool discover_at_start = Config->get_discover_audio_units ();
663 Config->set_discover_audio_units (false);
664 Config->save_state();
666 delete _au_plugin_info;
667 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
669 // successful scan re-enabled automatic discovery if it was set
670 Config->set_discover_audio_units (discover_at_start);
671 Config->save_state();
676 #ifdef WINDOWS_VST_SUPPORT
679 PluginManager::windows_vst_refresh (bool cache_only)
681 if (_windows_vst_plugin_info) {
682 _windows_vst_plugin_info->clear ();
684 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
687 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
690 static bool windows_vst_filter (const string& str, void * /*arg*/)
692 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
693 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
697 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
699 vector<string> plugin_objects;
700 vector<string>::iterator x;
703 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
705 if (Config->get_verbose_plugin_scan()) {
706 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
709 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
711 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
712 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
713 windows_vst_discover (*x, cache_only || cancelled());
716 if (Config->get_verbose_plugin_scan()) {
717 info << _("--- Windows VST plugins Scan Done") << endmsg;
724 PluginManager::windows_vst_discover (string path, bool cache_only)
726 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
728 if (Config->get_verbose_plugin_scan()) {
729 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
732 _cancel_timeout = false;
733 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
734 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
736 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
737 // .err file scanner output etc.
739 if (finfos->empty()) {
740 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
741 if (Config->get_verbose_plugin_scan()) {
742 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
747 uint32_t discovered = 0;
748 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
752 if (!finfo->canProcessReplacing) {
753 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
754 finfo->name, PROGRAM_NAME)
759 PluginInfoPtr info (new WindowsVSTPluginInfo);
761 /* what a joke freeware VST is */
763 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
764 info->name = PBD::basename_nosuffix (path);
766 info->name = finfo->name;
770 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
771 info->unique_id = buf;
772 info->category = "VST";
774 info->creator = finfo->creator;
776 info->n_inputs.set_audio (finfo->numInputs);
777 info->n_outputs.set_audio (finfo->numOutputs);
778 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
779 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
780 info->type = ARDOUR::Windows_VST;
782 // TODO: check dup-IDs (lxvst AND windows vst)
783 bool duplicate = false;
785 if (!_windows_vst_plugin_info->empty()) {
786 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
787 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
788 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
796 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
797 _windows_vst_plugin_info->push_back (info);
799 if (Config->get_verbose_plugin_scan()) {
800 PBD::info << string_compose (_(" -> OK. (VST Plugin \"%1\" added)."), info->name) << endmsg;
805 vstfx_free_info_list (finfos);
806 return discovered > 0 ? 0 : -1;
809 #endif // WINDOWS_VST_SUPPORT
814 PluginManager::lxvst_refresh (bool cache_only)
816 if (_lxvst_plugin_info) {
817 _lxvst_plugin_info->clear ();
819 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
822 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
825 static bool lxvst_filter (const string& str, void *)
827 /* Not a dotfile, has a prefix before a period, suffix is "so" */
829 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
833 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
835 vector<string> plugin_objects;
836 vector<string>::iterator x;
843 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
845 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
847 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
848 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
849 lxvst_discover (*x, cache_only || cancelled());
856 PluginManager::lxvst_discover (string path, bool cache_only)
858 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
860 _cancel_timeout = false;
861 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
862 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
864 if (finfos->empty()) {
865 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
869 uint32_t discovered = 0;
870 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
874 if (!finfo->canProcessReplacing) {
875 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
876 finfo->name, PROGRAM_NAME)
881 PluginInfoPtr info(new LXVSTPluginInfo);
883 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
884 info->name = PBD::basename_nosuffix (path);
886 info->name = finfo->name;
890 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
891 info->unique_id = buf;
892 info->category = "linuxVSTs";
894 info->creator = finfo->creator;
896 info->n_inputs.set_audio (finfo->numInputs);
897 info->n_outputs.set_audio (finfo->numOutputs);
898 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
899 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
900 info->type = ARDOUR::LXVST;
902 /* Make sure we don't find the same plugin in more than one place along
903 the LXVST_PATH We can't use a simple 'find' because the path is included
904 in the PluginInfo, and that is the one thing we can be sure MUST be
905 different if a duplicate instance is found. So we just compare the type
906 and unique ID (which for some VSTs isn't actually unique...)
909 // TODO: check dup-IDs with windowsVST, too
910 bool duplicate = false;
911 if (!_lxvst_plugin_info->empty()) {
912 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
913 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
914 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
922 _lxvst_plugin_info->push_back (info);
927 vstfx_free_info_list (finfos);
928 return discovered > 0 ? 0 : -1;
931 #endif // LXVST_SUPPORT
934 PluginManager::PluginStatusType
935 PluginManager::get_status (const PluginInfoPtr& pi)
937 PluginStatus ps (pi->type, pi->unique_id);
938 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
939 if (i == statuses.end() ) {
947 PluginManager::save_statuses ()
950 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
952 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
958 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
970 ofs << "Windows-VST";
979 switch ((*i).status) {
992 ofs << (*i).unique_id;;
1000 PluginManager::load_statuses ()
1002 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1003 ifstream ifs (path.c_str());
1010 std::string sstatus;
1013 PluginStatusType status;
1030 /* rest of the line is the plugin ID */
1032 ifs.getline (buf, sizeof (buf), '\n');
1037 if (sstatus == "Normal") {
1039 } else if (sstatus == "Favorite") {
1041 } else if (sstatus == "Hidden") {
1044 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1050 if (stype == "LADSPA") {
1052 } else if (stype == "AudioUnit") {
1054 } else if (stype == "LV2") {
1056 } else if (stype == "Windows-VST") {
1058 } else if (stype == "LXVST") {
1061 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1067 strip_whitespace_edges (id);
1068 set_status (type, id, status);
1075 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1077 PluginStatus ps (t, id, status);
1078 statuses.erase (ps);
1080 if (status == Normal) {
1084 statuses.insert (ps);
1087 ARDOUR::PluginInfoList&
1088 PluginManager::windows_vst_plugin_info ()
1090 #ifdef WINDOWS_VST_SUPPORT
1091 if (!_windows_vst_plugin_info) {
1092 windows_vst_refresh ();
1094 return *_windows_vst_plugin_info;
1096 return _empty_plugin_info;
1100 ARDOUR::PluginInfoList&
1101 PluginManager::lxvst_plugin_info ()
1103 #ifdef LXVST_SUPPORT
1104 assert(_lxvst_plugin_info);
1105 return *_lxvst_plugin_info;
1107 return _empty_plugin_info;
1111 ARDOUR::PluginInfoList&
1112 PluginManager::ladspa_plugin_info ()
1114 assert(_ladspa_plugin_info);
1115 return *_ladspa_plugin_info;
1118 ARDOUR::PluginInfoList&
1119 PluginManager::lv2_plugin_info ()
1122 assert(_lv2_plugin_info);
1123 return *_lv2_plugin_info;
1125 return _empty_plugin_info;
1129 ARDOUR::PluginInfoList&
1130 PluginManager::au_plugin_info ()
1132 #ifdef AUDIOUNIT_SUPPORT
1133 if (_au_plugin_info) {
1134 return *_au_plugin_info;
1137 return _empty_plugin_info;