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 bool discover_at_start = Config->get_discover_audio_units ();
649 // disable automatic scan in case we crash
650 Config->set_discover_audio_units (false);
651 Config->save_state();
653 /* note: AU require a CAComponentDescription pointer provided by the OS.
654 * Ardour only caches port and i/o config. It can't just 'scan' without
655 * 'discovering' (like we do for VST).
657 * So in case discovery fails, we assume the worst: the Description
658 * is broken (malicious plugins) and even a simple 'scan' would always
659 * crash ardour on startup. Hence we disable Auto-Scan on start.
661 * If the crash happens at any later time (description is available),
662 * Ardour will blacklist the plugin in question -- unless
663 * the crash happens during realtime-run.
666 // successful scan re-enabled automatic discovery
667 Config->set_discover_audio_units (discover_at_start);
668 Config->save_state();
673 #ifdef WINDOWS_VST_SUPPORT
676 PluginManager::windows_vst_refresh (bool cache_only)
678 if (_windows_vst_plugin_info) {
679 _windows_vst_plugin_info->clear ();
681 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
684 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
687 static bool windows_vst_filter (const string& str, void * /*arg*/)
689 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
690 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
694 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
696 vector<string> plugin_objects;
697 vector<string>::iterator x;
700 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
702 if (Config->get_verbose_plugin_scan()) {
703 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
706 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
708 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
709 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
710 windows_vst_discover (*x, cache_only || cancelled());
713 if (Config->get_verbose_plugin_scan()) {
714 info << _("--- Windows VST plugins Scan Done") << endmsg;
721 PluginManager::windows_vst_discover (string path, bool cache_only)
723 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
725 if (Config->get_verbose_plugin_scan()) {
726 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
729 _cancel_timeout = false;
730 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
731 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
733 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
734 // .err file scanner output etc.
736 if (finfos->empty()) {
737 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
738 if (Config->get_verbose_plugin_scan()) {
739 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
744 uint32_t discovered = 0;
745 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
749 if (!finfo->canProcessReplacing) {
750 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
751 finfo->name, PROGRAM_NAME)
756 PluginInfoPtr info (new WindowsVSTPluginInfo);
758 /* what a joke freeware VST is */
760 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
761 info->name = PBD::basename_nosuffix (path);
763 info->name = finfo->name;
767 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
768 info->unique_id = buf;
769 info->category = "VST";
771 info->creator = finfo->creator;
773 info->n_inputs.set_audio (finfo->numInputs);
774 info->n_outputs.set_audio (finfo->numOutputs);
775 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
776 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
777 info->type = ARDOUR::Windows_VST;
779 // TODO: check dup-IDs (lxvst AND windows vst)
780 bool duplicate = false;
782 if (!_windows_vst_plugin_info->empty()) {
783 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
784 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
785 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
793 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
794 _windows_vst_plugin_info->push_back (info);
796 if (Config->get_verbose_plugin_scan()) {
797 PBD::info << string_compose (_(" -> OK. (VST Plugin \"%1\" added)."), info->name) << endmsg;
802 vstfx_free_info_list (finfos);
803 return discovered > 0 ? 0 : -1;
806 #endif // WINDOWS_VST_SUPPORT
811 PluginManager::lxvst_refresh (bool cache_only)
813 if (_lxvst_plugin_info) {
814 _lxvst_plugin_info->clear ();
816 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
819 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
822 static bool lxvst_filter (const string& str, void *)
824 /* Not a dotfile, has a prefix before a period, suffix is "so" */
826 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
830 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
832 vector<string> plugin_objects;
833 vector<string>::iterator x;
840 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
842 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
844 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
845 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
846 lxvst_discover (*x, cache_only || cancelled());
853 PluginManager::lxvst_discover (string path, bool cache_only)
855 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
857 _cancel_timeout = false;
858 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
859 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
861 if (finfos->empty()) {
862 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
866 uint32_t discovered = 0;
867 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
871 if (!finfo->canProcessReplacing) {
872 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
873 finfo->name, PROGRAM_NAME)
878 PluginInfoPtr info(new LXVSTPluginInfo);
880 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
881 info->name = PBD::basename_nosuffix (path);
883 info->name = finfo->name;
887 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
888 info->unique_id = buf;
889 info->category = "linuxVSTs";
891 info->creator = finfo->creator;
893 info->n_inputs.set_audio (finfo->numInputs);
894 info->n_outputs.set_audio (finfo->numOutputs);
895 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
896 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
897 info->type = ARDOUR::LXVST;
899 /* Make sure we don't find the same plugin in more than one place along
900 the LXVST_PATH We can't use a simple 'find' because the path is included
901 in the PluginInfo, and that is the one thing we can be sure MUST be
902 different if a duplicate instance is found. So we just compare the type
903 and unique ID (which for some VSTs isn't actually unique...)
906 // TODO: check dup-IDs with windowsVST, too
907 bool duplicate = false;
908 if (!_lxvst_plugin_info->empty()) {
909 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
910 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
911 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
919 _lxvst_plugin_info->push_back (info);
924 vstfx_free_info_list (finfos);
925 return discovered > 0 ? 0 : -1;
928 #endif // LXVST_SUPPORT
931 PluginManager::PluginStatusType
932 PluginManager::get_status (const PluginInfoPtr& pi)
934 PluginStatus ps (pi->type, pi->unique_id);
935 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
936 if (i == statuses.end() ) {
944 PluginManager::save_statuses ()
947 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
949 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
955 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
967 ofs << "Windows-VST";
976 switch ((*i).status) {
989 ofs << (*i).unique_id;;
997 PluginManager::load_statuses ()
999 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1000 ifstream ifs (path.c_str());
1007 std::string sstatus;
1010 PluginStatusType status;
1027 /* rest of the line is the plugin ID */
1029 ifs.getline (buf, sizeof (buf), '\n');
1034 if (sstatus == "Normal") {
1036 } else if (sstatus == "Favorite") {
1038 } else if (sstatus == "Hidden") {
1041 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1047 if (stype == "LADSPA") {
1049 } else if (stype == "AudioUnit") {
1051 } else if (stype == "LV2") {
1053 } else if (stype == "Windows-VST") {
1055 } else if (stype == "LXVST") {
1058 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1064 strip_whitespace_edges (id);
1065 set_status (type, id, status);
1072 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1074 PluginStatus ps (t, id, status);
1075 statuses.erase (ps);
1077 if (status == Normal) {
1081 statuses.insert (ps);
1084 ARDOUR::PluginInfoList&
1085 PluginManager::windows_vst_plugin_info ()
1087 #ifdef WINDOWS_VST_SUPPORT
1088 if (!_windows_vst_plugin_info) {
1089 windows_vst_refresh ();
1091 return *_windows_vst_plugin_info;
1093 return _empty_plugin_info;
1097 ARDOUR::PluginInfoList&
1098 PluginManager::lxvst_plugin_info ()
1100 #ifdef LXVST_SUPPORT
1101 assert(_lxvst_plugin_info);
1102 return *_lxvst_plugin_info;
1104 return _empty_plugin_info;
1108 ARDOUR::PluginInfoList&
1109 PluginManager::ladspa_plugin_info ()
1111 assert(_ladspa_plugin_info);
1112 return *_ladspa_plugin_info;
1115 ARDOUR::PluginInfoList&
1116 PluginManager::lv2_plugin_info ()
1119 assert(_lv2_plugin_info);
1120 return *_lv2_plugin_info;
1122 return _empty_plugin_info;
1126 ARDOUR::PluginInfoList&
1127 PluginManager::au_plugin_info ()
1129 #ifdef AUDIOUNIT_SUPPORT
1130 if (_au_plugin_info) {
1131 return *_au_plugin_info;
1134 return _empty_plugin_info;