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 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
229 _cancel_scan = false;
231 BootMessage (_("Scanning LADSPA Plugins"));
234 BootMessage (_("Scanning LV2 Plugins"));
237 #ifdef WINDOWS_VST_SUPPORT
238 if (Config->get_use_windows_vst()) {
239 BootMessage (_("Scanning Windows VST Plugins"));
240 windows_vst_refresh (cache_only);
242 #endif // WINDOWS_VST_SUPPORT
245 if(Config->get_use_lxvst()) {
246 BootMessage (_("Scanning Linux VST Plugins"));
247 lxvst_refresh(cache_only);
249 #endif //Native linuxVST SUPPORT
251 #ifdef AUDIOUNIT_SUPPORT
252 BootMessage (_("Scanning AU Plugins"));
253 au_refresh (cache_only);
256 BootMessage (_("Plugin Scan Complete..."));
257 PluginListChanged (); /* EMIT SIGNAL */
258 PluginScanMessage(X_("closeme"), "", false);
259 _cancel_scan = false;
263 PluginManager::cancel_plugin_scan ()
269 PluginManager::cancel_plugin_timeout ()
271 _cancel_timeout = true;
275 PluginManager::clear_vst_cache ()
277 // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
278 #ifdef WINDOWS_VST_SUPPORT
280 vector<string> fsi_files;
281 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
282 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
283 ::g_unlink(i->c_str());
290 vector<string> fsi_files;
291 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
292 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
293 ::g_unlink(i->c_str());
298 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
300 string personal = get_personal_vst_info_cache_dir();
301 vector<string> fsi_files;
302 find_files_matching_regex (fsi_files, personal, "\\.fsi$", /* user cache is flat, no recursion */ false);
303 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
304 ::g_unlink(i->c_str());
311 PluginManager::clear_vst_blacklist ()
313 #ifdef WINDOWS_VST_SUPPORT
315 vector<string> fsi_files;
316 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
317 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
318 ::g_unlink(i->c_str());
325 vector<string> fsi_files;
326 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
327 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
328 ::g_unlink(i->c_str());
333 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
335 string personal = get_personal_vst_blacklist_dir();
337 vector<string> fsi_files;
338 find_files_matching_regex (fsi_files, personal, "\\" VST_EXT_BLACKLIST "$", /* flat user cache */ false);
339 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
340 ::g_unlink(i->c_str());
347 PluginManager::clear_au_cache ()
349 #ifdef AUDIOUNIT_SUPPORT
350 // AUPluginInfo::au_cache_path ()
351 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
352 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
353 ::g_unlink(fn.c_str());
359 PluginManager::clear_au_blacklist ()
361 #ifdef AUDIOUNIT_SUPPORT
362 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
363 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
364 ::g_unlink(fn.c_str());
370 PluginManager::ladspa_refresh ()
372 if (_ladspa_plugin_info) {
373 _ladspa_plugin_info->clear ();
375 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
378 /* allow LADSPA_PATH to augment, not override standard locations */
380 /* Only add standard locations to ladspa_path if it doesn't
381 * already contain them. Check for trailing G_DIR_SEPARATOR too.
384 vector<string> ladspa_modules;
386 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
388 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
389 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
390 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
392 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
393 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
394 ladspa_discover (*i);
399 static bool rdf_filter (const string &str, void* /*arg*/)
401 return str[0] != '.' &&
402 ((str.find(".rdf") == (str.length() - 4)) ||
403 (str.find(".rdfs") == (str.length() - 5)) ||
404 (str.find(".n3") == (str.length() - 3)) ||
405 (str.find(".ttl") == (str.length() - 4)));
410 PluginManager::add_ladspa_presets()
412 add_presets ("ladspa");
416 PluginManager::add_windows_vst_presets()
418 add_presets ("windows-vst");
422 PluginManager::add_lxvst_presets()
424 add_presets ("lxvst");
428 PluginManager::add_presets(string domain)
431 vector<string> presets;
432 vector<string>::iterator x;
435 if ((envvar = getenv ("HOME")) == 0) {
439 string path = string_compose("%1/.%2/rdf", envvar, domain);
440 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
442 for (x = presets.begin(); x != presets.end (); ++x) {
443 string file = "file:" + *x;
444 if (lrdf_read_file(file.c_str())) {
445 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
453 PluginManager::add_lrdf_data (const string &path)
456 vector<string> rdf_files;
457 vector<string>::iterator x;
459 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
461 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
462 const string uri(string("file://") + *x);
464 if (lrdf_read_file(uri.c_str())) {
465 warning << "Could not parse rdf file: " << uri << endmsg;
472 PluginManager::ladspa_discover (string path)
474 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
476 Glib::Module module(path);
477 const LADSPA_Descriptor *descriptor;
478 LADSPA_Descriptor_Function dfunc;
482 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
483 path, Glib::Module::get_last_error()) << endmsg;
488 if (!module.get_symbol("ladspa_descriptor", func)) {
489 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
490 error << Glib::Module::get_last_error() << endmsg;
494 dfunc = (LADSPA_Descriptor_Function)func;
496 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
498 for (uint32_t i = 0; ; ++i) {
499 if ((descriptor = dfunc (i)) == 0) {
503 if (!ladspa_plugin_whitelist.empty()) {
504 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
509 PluginInfoPtr info(new LadspaPluginInfo);
510 info->name = descriptor->Name;
511 info->category = get_ladspa_category(descriptor->UniqueID);
512 info->creator = descriptor->Maker;
515 info->n_inputs = ChanCount();
516 info->n_outputs = ChanCount();
517 info->type = ARDOUR::LADSPA;
520 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
521 info->unique_id = buf;
523 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
524 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
525 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
526 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
528 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
529 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
534 if(_ladspa_plugin_info->empty()){
535 _ladspa_plugin_info->push_back (info);
538 //Ensure that the plugin is not already in the plugin list.
542 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
543 if(0 == info->unique_id.compare((*i)->unique_id)){
549 _ladspa_plugin_info->push_back (info);
552 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
555 // GDB WILL NOT LIKE YOU IF YOU DO THIS
562 PluginManager::get_ladspa_category (uint32_t plugin_id)
566 lrdf_statement pattern;
568 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
569 pattern.subject = buf;
570 pattern.predicate = const_cast<char*>(RDF_TYPE);
572 pattern.object_type = lrdf_uri;
574 lrdf_statement* matches1 = lrdf_matches (&pattern);
580 pattern.subject = matches1->object;
581 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
583 pattern.object_type = lrdf_literal;
585 lrdf_statement* matches2 = lrdf_matches (&pattern);
586 lrdf_free_statements(matches1);
592 string label = matches2->object;
593 lrdf_free_statements(matches2);
595 /* Kludge LADSPA class names to be singular and match LV2 class names.
596 This avoids duplicate plugin menus for every class, which is necessary
597 to make the plugin category menu at all usable, but is obviously a
600 In the short term, lrdf could be updated so the labels match and a new
601 release made. To support both specs, we should probably be mapping the
602 URIs to the same category in code and perhaps tweaking that hierarchy
603 dynamically to suit the user. Personally, I (drobilla) think that time
604 is better spent replacing the little-used LRDF.
606 In the longer term, we will abandon LRDF entirely in favour of LV2 and
607 use that class hierarchy. Aside from fixing this problem properly, that
608 will also allow for translated labels. SWH plugins have been LV2 for
609 ages; TAP needs porting. I don't know of anything else with LRDF data.
611 if (label == "Utilities") {
613 } else if (label == "Pitch shifters") {
614 return "Pitch Shifter";
615 } else if (label != "Dynamics" && label != "Chorus"
616 &&label[label.length() - 1] == 's'
617 && label[label.length() - 2] != 's') {
618 return label.substr(0, label.length() - 1);
629 PluginManager::lv2_refresh ()
631 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
632 delete _lv2_plugin_info;
633 _lv2_plugin_info = LV2PluginInfo::discover();
637 #ifdef AUDIOUNIT_SUPPORT
639 PluginManager::au_refresh (bool cache_only)
641 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
642 if (cache_only && !Config->get_discover_audio_units ()) {
645 delete _au_plugin_info;
646 _au_plugin_info = AUPluginInfo::discover();
648 // disable automatic scan in case we crash
649 Config->set_discover_audio_units (false);
650 Config->save_state();
652 /* note: AU require a CAComponentDescription pointer provided by the OS.
653 * Ardour only caches port and i/o config. It can't just 'scan' without
654 * 'discovering' (like we do for VST).
656 * So in case discovery fails, we assume the worst: the Description
657 * is broken (malicious plugins) and even a simple 'scan' would always
658 * crash ardour on startup. Hence we disable Auto-Scan on start.
660 * If the crash happens at any later time (description is available),
661 * Ardour will blacklist the plugin in question -- unless
662 * the crash happens during realtime-run.
665 // successful scan re-enabled automatic discovery
666 Config->set_discover_audio_units (true);
667 Config->save_state();
672 #ifdef WINDOWS_VST_SUPPORT
675 PluginManager::windows_vst_refresh (bool cache_only)
677 if (_windows_vst_plugin_info) {
678 _windows_vst_plugin_info->clear ();
680 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
683 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
686 static bool windows_vst_filter (const string& str, void * /*arg*/)
688 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
689 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
693 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
695 vector<string> plugin_objects;
696 vector<string>::iterator x;
699 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
701 if (Config->get_verbose_plugin_scan()) {
702 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
705 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
707 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
708 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
709 windows_vst_discover (*x, cache_only || cancelled());
712 if (Config->get_verbose_plugin_scan()) {
713 info << _("--- Windows VST plugins Scan Done") << endmsg;
720 PluginManager::windows_vst_discover (string path, bool cache_only)
722 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
724 if (Config->get_verbose_plugin_scan()) {
725 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
728 _cancel_timeout = false;
729 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
730 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
732 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
733 // .err file scanner output etc.
735 if (finfos->empty()) {
736 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
737 if (Config->get_verbose_plugin_scan()) {
738 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
743 uint32_t discovered = 0;
744 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
748 if (!finfo->canProcessReplacing) {
749 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
750 finfo->name, PROGRAM_NAME)
755 PluginInfoPtr info (new WindowsVSTPluginInfo);
757 /* what a joke freeware VST is */
759 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
760 info->name = PBD::basename_nosuffix (path);
762 info->name = finfo->name;
766 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
767 info->unique_id = buf;
768 info->category = "VST";
770 info->creator = finfo->creator;
772 info->n_inputs.set_audio (finfo->numInputs);
773 info->n_outputs.set_audio (finfo->numOutputs);
774 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
775 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
776 info->type = ARDOUR::Windows_VST;
778 // TODO: check dup-IDs (lxvst AND windows vst)
779 bool duplicate = false;
781 if (!_windows_vst_plugin_info->empty()) {
782 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
783 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
784 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
792 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
793 _windows_vst_plugin_info->push_back (info);
795 if (Config->get_verbose_plugin_scan()) {
796 PBD::info << string_compose (_(" -> OK. (VST Plugin \"%1\" added)."), info->name) << endmsg;
801 vstfx_free_info_list (finfos);
802 return discovered > 0 ? 0 : -1;
805 #endif // WINDOWS_VST_SUPPORT
810 PluginManager::lxvst_refresh (bool cache_only)
812 if (_lxvst_plugin_info) {
813 _lxvst_plugin_info->clear ();
815 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
818 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
821 static bool lxvst_filter (const string& str, void *)
823 /* Not a dotfile, has a prefix before a period, suffix is "so" */
825 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
829 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
831 vector<string> plugin_objects;
832 vector<string>::iterator x;
839 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
841 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
843 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
844 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
845 lxvst_discover (*x, cache_only || cancelled());
852 PluginManager::lxvst_discover (string path, bool cache_only)
854 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
856 _cancel_timeout = false;
857 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
858 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
860 if (finfos->empty()) {
861 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
865 uint32_t discovered = 0;
866 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
870 if (!finfo->canProcessReplacing) {
871 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
872 finfo->name, PROGRAM_NAME)
877 PluginInfoPtr info(new LXVSTPluginInfo);
879 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
880 info->name = PBD::basename_nosuffix (path);
882 info->name = finfo->name;
886 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
887 info->unique_id = buf;
888 info->category = "linuxVSTs";
890 info->creator = finfo->creator;
892 info->n_inputs.set_audio (finfo->numInputs);
893 info->n_outputs.set_audio (finfo->numOutputs);
894 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
895 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
896 info->type = ARDOUR::LXVST;
898 /* Make sure we don't find the same plugin in more than one place along
899 the LXVST_PATH We can't use a simple 'find' because the path is included
900 in the PluginInfo, and that is the one thing we can be sure MUST be
901 different if a duplicate instance is found. So we just compare the type
902 and unique ID (which for some VSTs isn't actually unique...)
905 // TODO: check dup-IDs with windowsVST, too
906 bool duplicate = false;
907 if (!_lxvst_plugin_info->empty()) {
908 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
909 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
910 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
918 _lxvst_plugin_info->push_back (info);
923 vstfx_free_info_list (finfos);
924 return discovered > 0 ? 0 : -1;
927 #endif // LXVST_SUPPORT
930 PluginManager::PluginStatusType
931 PluginManager::get_status (const PluginInfoPtr& pi)
933 PluginStatus ps (pi->type, pi->unique_id);
934 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
935 if (i == statuses.end() ) {
943 PluginManager::save_statuses ()
946 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
948 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
954 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
966 ofs << "Windows-VST";
975 switch ((*i).status) {
988 ofs << (*i).unique_id;;
996 PluginManager::load_statuses ()
998 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
999 ifstream ifs (path.c_str());
1006 std::string sstatus;
1009 PluginStatusType status;
1026 /* rest of the line is the plugin ID */
1028 ifs.getline (buf, sizeof (buf), '\n');
1033 if (sstatus == "Normal") {
1035 } else if (sstatus == "Favorite") {
1037 } else if (sstatus == "Hidden") {
1040 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1046 if (stype == "LADSPA") {
1048 } else if (stype == "AudioUnit") {
1050 } else if (stype == "LV2") {
1052 } else if (stype == "Windows-VST") {
1054 } else if (stype == "LXVST") {
1057 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1063 strip_whitespace_edges (id);
1064 set_status (type, id, status);
1071 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1073 PluginStatus ps (t, id, status);
1074 statuses.erase (ps);
1076 if (status == Normal) {
1080 statuses.insert (ps);
1083 ARDOUR::PluginInfoList&
1084 PluginManager::windows_vst_plugin_info ()
1086 #ifdef WINDOWS_VST_SUPPORT
1087 if (!_windows_vst_plugin_info) {
1088 windows_vst_refresh ();
1090 return *_windows_vst_plugin_info;
1092 return _empty_plugin_info;
1096 ARDOUR::PluginInfoList&
1097 PluginManager::lxvst_plugin_info ()
1099 #ifdef LXVST_SUPPORT
1100 assert(_lxvst_plugin_info);
1101 return *_lxvst_plugin_info;
1103 return _empty_plugin_info;
1107 ARDOUR::PluginInfoList&
1108 PluginManager::ladspa_plugin_info ()
1110 assert(_ladspa_plugin_info);
1111 return *_ladspa_plugin_info;
1114 ARDOUR::PluginInfoList&
1115 PluginManager::lv2_plugin_info ()
1118 assert(_lv2_plugin_info);
1119 return *_lv2_plugin_info;
1121 return _empty_plugin_info;
1125 ARDOUR::PluginInfoList&
1126 PluginManager::au_plugin_info ()
1128 #ifdef AUDIOUNIT_SUPPORT
1129 if (_au_plugin_info) {
1130 return *_au_plugin_info;
1133 return _empty_plugin_info;