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()) {
860 info << string_compose (_(" * %1 %2 %3"), path, (cache_only ? _(" (cache only)") : "", dll_info (path))) << endmsg;
863 _cancel_timeout = false;
864 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
865 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
867 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
868 // .err file scanner output etc.
870 if (finfos->empty()) {
871 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
872 if (Config->get_verbose_plugin_scan()) {
873 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
878 uint32_t discovered = 0;
879 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
883 if (!finfo->canProcessReplacing) {
884 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
885 finfo->name, PROGRAM_NAME)
890 PluginInfoPtr info (new WindowsVSTPluginInfo);
892 /* what a joke freeware VST is */
894 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
895 info->name = PBD::basename_nosuffix (path);
897 info->name = finfo->name;
901 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
902 info->unique_id = buf;
903 info->category = "VST";
905 info->creator = finfo->creator;
907 info->n_inputs.set_audio (finfo->numInputs);
908 info->n_outputs.set_audio (finfo->numOutputs);
909 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
910 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
911 info->type = ARDOUR::Windows_VST;
913 // TODO: check dup-IDs (lxvst AND windows vst)
914 bool duplicate = false;
916 if (!_windows_vst_plugin_info->empty()) {
917 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
918 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
919 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
927 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
928 _windows_vst_plugin_info->push_back (info);
930 if (Config->get_verbose_plugin_scan()) {
931 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
936 vstfx_free_info_list (finfos);
937 return discovered > 0 ? 0 : -1;
940 #endif // WINDOWS_VST_SUPPORT
945 PluginManager::lxvst_refresh (bool cache_only)
947 if (_lxvst_plugin_info) {
948 _lxvst_plugin_info->clear ();
950 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
953 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
956 static bool lxvst_filter (const string& str, void *)
958 /* Not a dotfile, has a prefix before a period, suffix is "so" */
960 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
964 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
966 vector<string> plugin_objects;
967 vector<string>::iterator x;
974 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
976 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
978 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
979 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
980 lxvst_discover (*x, cache_only || cancelled());
987 PluginManager::lxvst_discover (string path, bool cache_only)
989 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
991 _cancel_timeout = false;
992 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
993 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
995 if (finfos->empty()) {
996 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1000 uint32_t discovered = 0;
1001 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1002 VSTInfo* finfo = *x;
1005 if (!finfo->canProcessReplacing) {
1006 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1007 finfo->name, PROGRAM_NAME)
1012 PluginInfoPtr info(new LXVSTPluginInfo);
1014 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1015 info->name = PBD::basename_nosuffix (path);
1017 info->name = finfo->name;
1021 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1022 info->unique_id = buf;
1023 info->category = "linuxVSTs";
1025 info->creator = finfo->creator;
1027 info->n_inputs.set_audio (finfo->numInputs);
1028 info->n_outputs.set_audio (finfo->numOutputs);
1029 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1030 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1031 info->type = ARDOUR::LXVST;
1033 /* Make sure we don't find the same plugin in more than one place along
1034 the LXVST_PATH We can't use a simple 'find' because the path is included
1035 in the PluginInfo, and that is the one thing we can be sure MUST be
1036 different if a duplicate instance is found. So we just compare the type
1037 and unique ID (which for some VSTs isn't actually unique...)
1040 // TODO: check dup-IDs with windowsVST, too
1041 bool duplicate = false;
1042 if (!_lxvst_plugin_info->empty()) {
1043 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1044 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1045 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1053 _lxvst_plugin_info->push_back (info);
1058 vstfx_free_info_list (finfos);
1059 return discovered > 0 ? 0 : -1;
1062 #endif // LXVST_SUPPORT
1065 PluginManager::PluginStatusType
1066 PluginManager::get_status (const PluginInfoPtr& pi)
1068 PluginStatus ps (pi->type, pi->unique_id);
1069 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1070 if (i == statuses.end() ) {
1078 PluginManager::save_statuses ()
1080 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1083 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1084 switch ((*i).type) {
1095 ofs << "Windows-VST";
1104 switch ((*i).status) {
1117 ofs << (*i).unique_id;;
1120 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1124 PluginManager::load_statuses ()
1126 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1128 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1131 stringstream ifs (fbuf);
1135 std::string sstatus;
1138 PluginStatusType status;
1155 /* rest of the line is the plugin ID */
1157 ifs.getline (buf, sizeof (buf), '\n');
1162 if (sstatus == "Normal") {
1164 } else if (sstatus == "Favorite") {
1166 } else if (sstatus == "Hidden") {
1169 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1175 if (stype == "LADSPA") {
1177 } else if (stype == "AudioUnit") {
1179 } else if (stype == "LV2") {
1181 } else if (stype == "Windows-VST") {
1183 } else if (stype == "LXVST") {
1186 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1192 strip_whitespace_edges (id);
1193 set_status (type, id, status);
1198 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1200 PluginStatus ps (t, id, status);
1201 statuses.erase (ps);
1203 if (status == Normal) {
1207 statuses.insert (ps);
1210 ARDOUR::PluginInfoList&
1211 PluginManager::windows_vst_plugin_info ()
1213 #ifdef WINDOWS_VST_SUPPORT
1214 if (!_windows_vst_plugin_info) {
1215 windows_vst_refresh ();
1217 return *_windows_vst_plugin_info;
1219 return _empty_plugin_info;
1223 ARDOUR::PluginInfoList&
1224 PluginManager::lxvst_plugin_info ()
1226 #ifdef LXVST_SUPPORT
1227 assert(_lxvst_plugin_info);
1228 return *_lxvst_plugin_info;
1230 return _empty_plugin_info;
1234 ARDOUR::PluginInfoList&
1235 PluginManager::ladspa_plugin_info ()
1237 assert(_ladspa_plugin_info);
1238 return *_ladspa_plugin_info;
1241 ARDOUR::PluginInfoList&
1242 PluginManager::lv2_plugin_info ()
1245 assert(_lv2_plugin_info);
1246 return *_lv2_plugin_info;
1248 return _empty_plugin_info;
1252 ARDOUR::PluginInfoList&
1253 PluginManager::au_plugin_info ()
1255 #ifdef AUDIOUNIT_SUPPORT
1256 if (_au_plugin_info) {
1257 return *_au_plugin_info;
1260 return _empty_plugin_info;