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>
31 #include "pbd/gstdio_compat.h"
37 #ifdef WINDOWS_VST_SUPPORT
38 #include "ardour/vst_info_file.h"
40 #include "pbd/basename.h"
49 #endif // WINDOWS_VST_SUPPORT
52 #include "ardour/vst_info_file.h"
53 #include "ardour/linux_vst_support.h"
54 #include "pbd/basename.h"
56 #endif //LXVST_SUPPORT
58 #include <glibmm/miscutils.h>
59 #include <glibmm/pattern.h>
60 #include <glibmm/fileutils.h>
61 #include <glibmm/miscutils.h>
63 #include "pbd/whitespace.h"
64 #include "pbd/file_utils.h"
66 #include "ardour/debug.h"
67 #include "ardour/filesystem_paths.h"
68 #include "ardour/ladspa.h"
69 #include "ardour/ladspa_plugin.h"
70 #include "ardour/plugin.h"
71 #include "ardour/plugin_manager.h"
72 #include "ardour/rc_configuration.h"
74 #include "ardour/search_paths.h"
77 #include "ardour/lv2_plugin.h"
80 #ifdef WINDOWS_VST_SUPPORT
81 #include "ardour/windows_vst_plugin.h"
85 #include "ardour/lxvst_plugin.h"
88 #ifdef AUDIOUNIT_SUPPORT
89 #include "ardour/audio_unit.h"
90 #include <Carbon/Carbon.h>
93 #include "pbd/error.h"
94 #include "pbd/stl_delete.h"
98 #include "ardour/debug.h"
100 using namespace ARDOUR;
104 PluginManager* PluginManager::_instance = 0;
105 std::string PluginManager::scanner_bin_path = "";
108 PluginManager::instance()
111 _instance = new PluginManager;
116 PluginManager::PluginManager ()
117 : _windows_vst_plugin_info(0)
118 , _lxvst_plugin_info(0)
119 , _ladspa_plugin_info(0)
120 , _lv2_plugin_info(0)
122 , _cancel_scan(false)
123 , _cancel_timeout(false)
128 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
129 // source-tree (ardev, etc)
130 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
132 #ifdef PLATFORM_WINDOWS
133 // on windows the .exe needs to be in the same folder with libardour.dll
134 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
136 // on Unices additional internal-use binaries are deployed to $libdir
137 vstsp += ARDOUR::ardour_dll_directory();
140 if (!PBD::find_file (vstsp,
141 #ifdef PLATFORM_WINDOWS
142 #ifdef DEBUGGABLE_SCANNER_APP
143 #if defined(DEBUG) || defined(_DEBUG)
144 "ardour-vst-scannerD.exe"
146 "ardour-vst-scannerRDC.exe"
149 "ardour-vst-scanner.exe"
154 , scanner_bin_path)) {
155 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
161 if ((s = getenv ("LADSPA_RDF_PATH"))){
165 if (lrdf_path.length() == 0) {
166 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
169 add_lrdf_data(lrdf_path);
170 add_ladspa_presets();
171 #ifdef WINDOWS_VST_SUPPORT
172 if (Config->get_use_windows_vst ()) {
173 add_windows_vst_presets ();
175 #endif /* WINDOWS_VST_SUPPORT */
178 if (Config->get_use_lxvst()) {
181 #endif /* Native LinuxVST support*/
183 if ((s = getenv ("VST_PATH"))) {
184 windows_vst_path = s;
185 } else if ((s = getenv ("VST_PLUGINS"))) {
186 windows_vst_path = s;
189 if (windows_vst_path.length() == 0) {
190 windows_vst_path = vst_search_path ();
193 if ((s = getenv ("LXVST_PATH"))) {
195 } else if ((s = getenv ("LXVST_PLUGINS"))) {
199 if (lxvst_path.length() == 0) {
200 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
201 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
202 "/usr/lib/vst:/usr/local/lib/vst";
205 /* first time setup, use 'default' path */
206 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
207 Config->set_plugin_path_lxvst(get_default_lxvst_path());
209 if (Config->get_plugin_path_vst() == X_("@default@")) {
210 Config->set_plugin_path_vst(get_default_windows_vst_path());
213 if (_instance == 0) {
217 BootMessage (_("Discovering Plugins"));
221 PluginManager::~PluginManager()
223 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
224 // don't bother, just exit quickly.
225 delete _windows_vst_plugin_info;
226 delete _lxvst_plugin_info;
227 delete _ladspa_plugin_info;
228 delete _lv2_plugin_info;
229 delete _au_plugin_info;
234 PluginManager::refresh (bool cache_only)
236 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
242 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
243 _cancel_scan = false;
245 BootMessage (_("Scanning LADSPA Plugins"));
248 BootMessage (_("Scanning LV2 Plugins"));
251 #ifdef WINDOWS_VST_SUPPORT
252 if (Config->get_use_windows_vst()) {
254 BootMessage (_("Scanning Windows VST Plugins"));
256 BootMessage (_("Discovering Windows VST Plugins"));
258 windows_vst_refresh (cache_only);
260 #endif // WINDOWS_VST_SUPPORT
263 if(Config->get_use_lxvst()) {
265 BootMessage (_("Scanning Linux VST Plugins"));
267 BootMessage (_("Discovering Linux VST Plugins"));
269 lxvst_refresh(cache_only);
271 #endif //Native linuxVST SUPPORT
273 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
275 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
276 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
278 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
279 if (Config->get_verbose_plugin_scan()) {
280 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
282 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
290 #ifdef AUDIOUNIT_SUPPORT
292 BootMessage (_("Scanning AU Plugins"));
294 BootMessage (_("Discovering AU Plugins"));
296 au_refresh (cache_only);
299 BootMessage (_("Plugin Scan Complete..."));
300 PluginListChanged (); /* EMIT SIGNAL */
301 PluginScanMessage(X_("closeme"), "", false);
302 _cancel_scan = false;
306 PluginManager::cancel_plugin_scan ()
312 PluginManager::cancel_plugin_timeout ()
314 _cancel_timeout = true;
318 PluginManager::clear_vst_cache ()
320 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
321 #ifdef WINDOWS_VST_SUPPORT
323 vector<string> fsi_files;
324 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
325 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
326 ::g_unlink(i->c_str());
330 vector<string> fsi_files;
331 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
332 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
333 ::g_unlink(i->c_str());
337 vector<string> fsi_files;
338 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
339 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
340 ::g_unlink(i->c_str());
347 vector<string> fsi_files;
348 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
349 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
350 ::g_unlink(i->c_str());
354 vector<string> fsi_files;
355 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
356 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
357 ::g_unlink(i->c_str());
361 vector<string> fsi_files;
362 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
363 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
364 ::g_unlink(i->c_str());
368 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
370 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
371 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
372 PBD::remove_directory (dir);
376 #endif // old cache cleanup
378 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
380 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
381 vector<string> fsi_files;
382 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
383 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
384 ::g_unlink(i->c_str());
391 PluginManager::clear_vst_blacklist ()
393 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
395 #ifdef WINDOWS_VST_SUPPORT
397 vector<string> fsi_files;
398 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
399 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
400 ::g_unlink(i->c_str());
407 vector<string> fsi_files;
408 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
409 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
410 ::g_unlink(i->c_str());
414 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
416 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
417 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
418 PBD::remove_directory (dir);
423 #endif // old blacklist cleanup
425 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
427 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
428 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
429 ::g_unlink (fn.c_str());
437 PluginManager::clear_au_cache ()
439 #ifdef AUDIOUNIT_SUPPORT
440 // AUPluginInfo::au_cache_path ()
441 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
442 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
443 ::g_unlink(fn.c_str());
449 PluginManager::clear_au_blacklist ()
451 #ifdef AUDIOUNIT_SUPPORT
452 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
453 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
454 ::g_unlink(fn.c_str());
460 PluginManager::ladspa_refresh ()
462 if (_ladspa_plugin_info) {
463 _ladspa_plugin_info->clear ();
465 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
468 /* allow LADSPA_PATH to augment, not override standard locations */
470 /* Only add standard locations to ladspa_path if it doesn't
471 * already contain them. Check for trailing G_DIR_SEPARATOR too.
474 vector<string> ladspa_modules;
476 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
478 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
479 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
480 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
482 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
483 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
484 ladspa_discover (*i);
489 static bool rdf_filter (const string &str, void* /*arg*/)
491 return str[0] != '.' &&
492 ((str.find(".rdf") == (str.length() - 4)) ||
493 (str.find(".rdfs") == (str.length() - 5)) ||
494 (str.find(".n3") == (str.length() - 3)) ||
495 (str.find(".ttl") == (str.length() - 4)));
500 PluginManager::add_ladspa_presets()
502 add_presets ("ladspa");
506 PluginManager::add_windows_vst_presets()
508 add_presets ("windows-vst");
512 PluginManager::add_lxvst_presets()
514 add_presets ("lxvst");
518 PluginManager::add_presets(string domain)
521 vector<string> presets;
522 vector<string>::iterator x;
525 if ((envvar = getenv ("HOME")) == 0) {
529 string path = string_compose("%1/.%2/rdf", envvar, domain);
530 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
532 for (x = presets.begin(); x != presets.end (); ++x) {
533 string file = "file:" + *x;
534 if (lrdf_read_file(file.c_str())) {
535 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
543 PluginManager::add_lrdf_data (const string &path)
546 vector<string> rdf_files;
547 vector<string>::iterator x;
549 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
551 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
552 const string uri(string("file://") + *x);
554 if (lrdf_read_file(uri.c_str())) {
555 warning << "Could not parse rdf file: " << uri << endmsg;
562 PluginManager::ladspa_discover (string path)
564 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
566 Glib::Module module(path);
567 const LADSPA_Descriptor *descriptor;
568 LADSPA_Descriptor_Function dfunc;
572 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
573 path, Glib::Module::get_last_error()) << endmsg;
578 if (!module.get_symbol("ladspa_descriptor", func)) {
579 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
580 error << Glib::Module::get_last_error() << endmsg;
584 dfunc = (LADSPA_Descriptor_Function)func;
586 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
588 for (uint32_t i = 0; ; ++i) {
589 if ((descriptor = dfunc (i)) == 0) {
593 if (!ladspa_plugin_whitelist.empty()) {
594 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
599 PluginInfoPtr info(new LadspaPluginInfo);
600 info->name = descriptor->Name;
601 info->category = get_ladspa_category(descriptor->UniqueID);
602 info->creator = descriptor->Maker;
605 info->n_inputs = ChanCount();
606 info->n_outputs = ChanCount();
607 info->type = ARDOUR::LADSPA;
610 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
611 info->unique_id = buf;
613 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
614 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
615 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
616 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
618 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
619 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
624 if(_ladspa_plugin_info->empty()){
625 _ladspa_plugin_info->push_back (info);
628 //Ensure that the plugin is not already in the plugin list.
632 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
633 if(0 == info->unique_id.compare((*i)->unique_id)){
639 _ladspa_plugin_info->push_back (info);
642 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
645 // GDB WILL NOT LIKE YOU IF YOU DO THIS
652 PluginManager::get_ladspa_category (uint32_t plugin_id)
656 lrdf_statement pattern;
658 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
659 pattern.subject = buf;
660 pattern.predicate = const_cast<char*>(RDF_TYPE);
662 pattern.object_type = lrdf_uri;
664 lrdf_statement* matches1 = lrdf_matches (&pattern);
670 pattern.subject = matches1->object;
671 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
673 pattern.object_type = lrdf_literal;
675 lrdf_statement* matches2 = lrdf_matches (&pattern);
676 lrdf_free_statements(matches1);
682 string label = matches2->object;
683 lrdf_free_statements(matches2);
685 /* Kludge LADSPA class names to be singular and match LV2 class names.
686 This avoids duplicate plugin menus for every class, which is necessary
687 to make the plugin category menu at all usable, but is obviously a
690 In the short term, lrdf could be updated so the labels match and a new
691 release made. To support both specs, we should probably be mapping the
692 URIs to the same category in code and perhaps tweaking that hierarchy
693 dynamically to suit the user. Personally, I (drobilla) think that time
694 is better spent replacing the little-used LRDF.
696 In the longer term, we will abandon LRDF entirely in favour of LV2 and
697 use that class hierarchy. Aside from fixing this problem properly, that
698 will also allow for translated labels. SWH plugins have been LV2 for
699 ages; TAP needs porting. I don't know of anything else with LRDF data.
701 if (label == "Utilities") {
703 } else if (label == "Pitch shifters") {
704 return "Pitch Shifter";
705 } else if (label != "Dynamics" && label != "Chorus"
706 &&label[label.length() - 1] == 's'
707 && label[label.length() - 2] != 's') {
708 return label.substr(0, label.length() - 1);
719 PluginManager::lv2_refresh ()
721 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
722 delete _lv2_plugin_info;
723 _lv2_plugin_info = LV2PluginInfo::discover();
727 #ifdef AUDIOUNIT_SUPPORT
729 PluginManager::au_refresh (bool cache_only)
731 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
733 // disable automatic discovery in case we crash
734 bool discover_at_start = Config->get_discover_audio_units ();
735 Config->set_discover_audio_units (false);
736 Config->save_state();
738 delete _au_plugin_info;
739 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
741 // successful scan re-enabled automatic discovery if it was set
742 Config->set_discover_audio_units (discover_at_start);
743 Config->save_state();
748 #ifdef WINDOWS_VST_SUPPORT
751 PluginManager::windows_vst_refresh (bool cache_only)
753 if (_windows_vst_plugin_info) {
754 _windows_vst_plugin_info->clear ();
756 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
759 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
762 static bool windows_vst_filter (const string& str, void * /*arg*/)
764 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
765 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
769 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
771 vector<string> plugin_objects;
772 vector<string>::iterator x;
775 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
777 if (Config->get_verbose_plugin_scan()) {
778 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
781 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
783 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
784 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
785 windows_vst_discover (*x, cache_only || cancelled());
788 if (Config->get_verbose_plugin_scan()) {
789 info << _("--- Windows VST plugins Scan Done") << endmsg;
795 static std::string dll_info (std::string path) {
799 off_t pe_hdr_off = 0;
801 int fd = open(path.c_str(), O_RDONLY, 0444);
804 return _("- cannot open dll"); // TODO strerror()
807 if (68 != read (fd, buf, 68)) {
808 rv = _("- invalid dll, file too small");
811 if (buf[0] != 'M' && buf[1] != 'Z') {
812 rv = _("- not a dll");
816 pe_hdr_off = *((int32_t*) &buf[60]);
817 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
818 rv = _("- cannot determine dll type");
821 if (6 != read (fd, buf, 6)) {
822 rv = _("- cannot read dll PE header");
826 if (buf[0] != 'P' && buf[1] != 'E') {
827 rv = _("- invalid dll PE header");
831 type = *((uint16_t*) &buf[4]);
834 rv = _("- i386 (32bit)");
840 rv = _("- x64 (64bit)");
843 rv = _("- Native Architecture");
846 rv = _("- Unknown Architecture");
855 PluginManager::windows_vst_discover (string path, bool cache_only)
857 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
859 if (Config->get_verbose_plugin_scan()) {
861 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
863 info << string_compose (_(" * %1 %2"), path, dll_info (path)) << endmsg;
867 _cancel_timeout = false;
868 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
869 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
871 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
872 // .err file scanner output etc.
874 if (finfos->empty()) {
875 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
876 if (Config->get_verbose_plugin_scan()) {
877 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
882 uint32_t discovered = 0;
883 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
887 if (!finfo->canProcessReplacing) {
888 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
889 finfo->name, PROGRAM_NAME)
894 PluginInfoPtr info (new WindowsVSTPluginInfo);
896 /* what a joke freeware VST is */
898 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
899 info->name = PBD::basename_nosuffix (path);
901 info->name = finfo->name;
905 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
906 info->unique_id = buf;
907 info->category = "VST";
909 info->creator = finfo->creator;
911 info->n_inputs.set_audio (finfo->numInputs);
912 info->n_outputs.set_audio (finfo->numOutputs);
913 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
914 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
915 info->type = ARDOUR::Windows_VST;
917 // TODO: check dup-IDs (lxvst AND windows vst)
918 bool duplicate = false;
920 if (!_windows_vst_plugin_info->empty()) {
921 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
922 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
923 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
931 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
932 _windows_vst_plugin_info->push_back (info);
934 if (Config->get_verbose_plugin_scan()) {
935 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
940 vstfx_free_info_list (finfos);
941 return discovered > 0 ? 0 : -1;
944 #endif // WINDOWS_VST_SUPPORT
949 PluginManager::lxvst_refresh (bool cache_only)
951 if (_lxvst_plugin_info) {
952 _lxvst_plugin_info->clear ();
954 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
957 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
960 static bool lxvst_filter (const string& str, void *)
962 /* Not a dotfile, has a prefix before a period, suffix is "so" */
964 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
968 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
970 vector<string> plugin_objects;
971 vector<string>::iterator x;
978 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
980 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
982 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
983 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
984 lxvst_discover (*x, cache_only || cancelled());
991 PluginManager::lxvst_discover (string path, bool cache_only)
993 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
995 _cancel_timeout = false;
996 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
997 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
999 if (finfos->empty()) {
1000 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1004 uint32_t discovered = 0;
1005 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1006 VSTInfo* finfo = *x;
1009 if (!finfo->canProcessReplacing) {
1010 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1011 finfo->name, PROGRAM_NAME)
1016 PluginInfoPtr info(new LXVSTPluginInfo);
1018 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1019 info->name = PBD::basename_nosuffix (path);
1021 info->name = finfo->name;
1025 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1026 info->unique_id = buf;
1027 info->category = "linuxVSTs";
1029 info->creator = finfo->creator;
1031 info->n_inputs.set_audio (finfo->numInputs);
1032 info->n_outputs.set_audio (finfo->numOutputs);
1033 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1034 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1035 info->type = ARDOUR::LXVST;
1037 /* Make sure we don't find the same plugin in more than one place along
1038 the LXVST_PATH We can't use a simple 'find' because the path is included
1039 in the PluginInfo, and that is the one thing we can be sure MUST be
1040 different if a duplicate instance is found. So we just compare the type
1041 and unique ID (which for some VSTs isn't actually unique...)
1044 // TODO: check dup-IDs with windowsVST, too
1045 bool duplicate = false;
1046 if (!_lxvst_plugin_info->empty()) {
1047 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1048 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1049 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1057 _lxvst_plugin_info->push_back (info);
1062 vstfx_free_info_list (finfos);
1063 return discovered > 0 ? 0 : -1;
1066 #endif // LXVST_SUPPORT
1069 PluginManager::PluginStatusType
1070 PluginManager::get_status (const PluginInfoPtr& pi)
1072 PluginStatus ps (pi->type, pi->unique_id);
1073 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1074 if (i == statuses.end() ) {
1082 PluginManager::save_statuses ()
1084 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1087 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1088 switch ((*i).type) {
1099 ofs << "Windows-VST";
1108 switch ((*i).status) {
1121 ofs << (*i).unique_id;;
1124 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1128 PluginManager::load_statuses ()
1130 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1132 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1135 stringstream ifs (fbuf);
1139 std::string sstatus;
1142 PluginStatusType status;
1159 /* rest of the line is the plugin ID */
1161 ifs.getline (buf, sizeof (buf), '\n');
1166 if (sstatus == "Normal") {
1168 } else if (sstatus == "Favorite") {
1170 } else if (sstatus == "Hidden") {
1173 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1179 if (stype == "LADSPA") {
1181 } else if (stype == "AudioUnit") {
1183 } else if (stype == "LV2") {
1185 } else if (stype == "Windows-VST") {
1187 } else if (stype == "LXVST") {
1190 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1196 strip_whitespace_edges (id);
1197 set_status (type, id, status);
1202 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1204 PluginStatus ps (t, id, status);
1205 statuses.erase (ps);
1207 if (status == Normal) {
1211 statuses.insert (ps);
1214 ARDOUR::PluginInfoList&
1215 PluginManager::windows_vst_plugin_info ()
1217 #ifdef WINDOWS_VST_SUPPORT
1218 if (!_windows_vst_plugin_info) {
1219 windows_vst_refresh ();
1221 return *_windows_vst_plugin_info;
1223 return _empty_plugin_info;
1227 ARDOUR::PluginInfoList&
1228 PluginManager::lxvst_plugin_info ()
1230 #ifdef LXVST_SUPPORT
1231 assert(_lxvst_plugin_info);
1232 return *_lxvst_plugin_info;
1234 return _empty_plugin_info;
1238 ARDOUR::PluginInfoList&
1239 PluginManager::ladspa_plugin_info ()
1241 assert(_ladspa_plugin_info);
1242 return *_ladspa_plugin_info;
1245 ARDOUR::PluginInfoList&
1246 PluginManager::lv2_plugin_info ()
1249 assert(_lv2_plugin_info);
1250 return *_lv2_plugin_info;
1252 return _empty_plugin_info;
1256 ARDOUR::PluginInfoList&
1257 PluginManager::au_plugin_info ()
1259 #ifdef AUDIOUNIT_SUPPORT
1260 if (_au_plugin_info) {
1261 return *_au_plugin_info;
1264 return _empty_plugin_info;