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
59 #include "ardour/vst_info_file.h"
60 #include "ardour/mac_vst_support.h"
61 #include "ardour/mac_vst_plugin.h"
62 #include "pbd/basename.h"
63 #include "pbd/pathexpand.h"
65 #endif //MACVST_SUPPORT
67 #include <glibmm/miscutils.h>
68 #include <glibmm/pattern.h>
69 #include <glibmm/fileutils.h>
70 #include <glibmm/miscutils.h>
72 #include "pbd/whitespace.h"
73 #include "pbd/file_utils.h"
75 #include "ardour/directory_names.h"
76 #include "ardour/debug.h"
77 #include "ardour/filesystem_paths.h"
78 #include "ardour/ladspa.h"
79 #include "ardour/ladspa_plugin.h"
80 #include "ardour/luascripting.h"
81 #include "ardour/luaproc.h"
82 #include "ardour/plugin.h"
83 #include "ardour/plugin_manager.h"
84 #include "ardour/rc_configuration.h"
86 #include "ardour/search_paths.h"
89 #include "ardour/lv2_plugin.h"
92 #ifdef WINDOWS_VST_SUPPORT
93 #include "ardour/windows_vst_plugin.h"
97 #include "ardour/lxvst_plugin.h"
100 #ifdef AUDIOUNIT_SUPPORT
101 #include "ardour/audio_unit.h"
102 #include <Carbon/Carbon.h>
105 #include "pbd/error.h"
106 #include "pbd/stl_delete.h"
108 #include "pbd/i18n.h"
110 #include "ardour/debug.h"
112 using namespace ARDOUR;
116 PluginManager* PluginManager::_instance = 0;
117 std::string PluginManager::scanner_bin_path = "";
120 PluginManager::instance()
123 _instance = new PluginManager;
128 PluginManager::PluginManager ()
129 : _windows_vst_plugin_info(0)
130 , _lxvst_plugin_info(0)
131 , _mac_vst_plugin_info(0)
132 , _ladspa_plugin_info(0)
133 , _lv2_plugin_info(0)
135 , _lua_plugin_info(0)
136 , _cancel_scan(false)
137 , _cancel_timeout(false)
142 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
143 // source-tree (ardev, etc)
144 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
146 #ifdef PLATFORM_WINDOWS
147 // on windows the .exe needs to be in the same folder with libardour.dll
148 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
150 // on Unices additional internal-use binaries are deployed to $libdir
151 vstsp += ARDOUR::ardour_dll_directory();
154 if (!PBD::find_file (vstsp,
155 #ifdef PLATFORM_WINDOWS
156 #ifdef DEBUGGABLE_SCANNER_APP
157 #if defined(DEBUG) || defined(_DEBUG)
158 "ardour-vst-scannerD.exe"
160 "ardour-vst-scannerRDC.exe"
163 "ardour-vst-scanner.exe"
168 , scanner_bin_path)) {
169 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
175 if ((s = getenv ("LADSPA_RDF_PATH"))){
179 if (lrdf_path.length() == 0) {
180 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
183 add_lrdf_data(lrdf_path);
184 add_ladspa_presets();
185 #ifdef WINDOWS_VST_SUPPORT
186 if (Config->get_use_windows_vst ()) {
187 add_windows_vst_presets ();
189 #endif /* WINDOWS_VST_SUPPORT */
192 if (Config->get_use_lxvst()) {
195 #endif /* Native LinuxVST support*/
197 #ifdef MACVST_SUPPORT
198 if (Config->get_use_macvst ()) {
199 add_mac_vst_presets ();
203 if ((s = getenv ("VST_PATH"))) {
204 windows_vst_path = s;
205 } else if ((s = getenv ("VST_PLUGINS"))) {
206 windows_vst_path = s;
209 if (windows_vst_path.length() == 0) {
210 windows_vst_path = vst_search_path ();
213 if ((s = getenv ("LXVST_PATH"))) {
215 } else if ((s = getenv ("LXVST_PLUGINS"))) {
219 if (lxvst_path.length() == 0) {
220 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
221 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
222 "/usr/lib/vst:/usr/local/lib/vst";
225 /* first time setup, use 'default' path */
226 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
227 Config->set_plugin_path_lxvst(get_default_lxvst_path());
229 if (Config->get_plugin_path_vst() == X_("@default@")) {
230 Config->set_plugin_path_vst(get_default_windows_vst_path());
233 if (_instance == 0) {
237 BootMessage (_("Discovering Plugins"));
239 LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
243 PluginManager::~PluginManager()
245 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
246 // don't bother, just exit quickly.
247 delete _windows_vst_plugin_info;
248 delete _lxvst_plugin_info;
249 delete _mac_vst_plugin_info;
250 delete _ladspa_plugin_info;
251 delete _lv2_plugin_info;
252 delete _au_plugin_info;
253 delete _lua_plugin_info;
258 PluginManager::refresh (bool cache_only)
260 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
266 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
267 _cancel_scan = false;
269 BootMessage (_("Scanning LADSPA Plugins"));
271 BootMessage (_("Scanning Lua DSP Processors"));
274 BootMessage (_("Scanning LV2 Plugins"));
277 #ifdef WINDOWS_VST_SUPPORT
278 if (Config->get_use_windows_vst()) {
280 BootMessage (_("Scanning Windows VST Plugins"));
282 BootMessage (_("Discovering Windows VST Plugins"));
284 windows_vst_refresh (cache_only);
286 #endif // WINDOWS_VST_SUPPORT
289 if(Config->get_use_lxvst()) {
291 BootMessage (_("Scanning Linux VST Plugins"));
293 BootMessage (_("Discovering Linux VST Plugins"));
295 lxvst_refresh(cache_only);
297 #endif //Native linuxVST SUPPORT
299 #ifdef MACVST_SUPPORT
300 if(Config->get_use_macvst ()) {
302 BootMessage (_("Scanning Mac VST Plugins"));
304 BootMessage (_("Discovering Mac VST Plugins"));
306 mac_vst_refresh (cache_only);
307 } else if (_mac_vst_plugin_info) {
308 _mac_vst_plugin_info->clear ();
310 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
312 #endif //Native Mac VST SUPPORT
314 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
316 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
317 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
319 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
320 if (Config->get_verbose_plugin_scan()) {
321 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
323 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
331 #ifdef AUDIOUNIT_SUPPORT
333 BootMessage (_("Scanning AU Plugins"));
335 BootMessage (_("Discovering AU Plugins"));
337 au_refresh (cache_only);
340 BootMessage (_("Plugin Scan Complete..."));
341 PluginListChanged (); /* EMIT SIGNAL */
342 PluginScanMessage(X_("closeme"), "", false);
343 _cancel_scan = false;
347 PluginManager::cancel_plugin_scan ()
353 PluginManager::cancel_plugin_timeout ()
355 _cancel_timeout = true;
359 PluginManager::clear_vst_cache ()
361 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
362 #ifdef WINDOWS_VST_SUPPORT
364 vector<string> fsi_files;
365 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
366 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
367 ::g_unlink(i->c_str());
371 vector<string> fsi_files;
372 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
373 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
374 ::g_unlink(i->c_str());
378 vector<string> fsi_files;
379 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
380 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
381 ::g_unlink(i->c_str());
388 vector<string> fsi_files;
389 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
390 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
391 ::g_unlink(i->c_str());
395 vector<string> fsi_files;
396 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
397 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
398 ::g_unlink(i->c_str());
402 vector<string> fsi_files;
403 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
404 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
405 ::g_unlink(i->c_str());
409 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
411 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
412 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
413 PBD::remove_directory (dir);
417 #endif // old cache cleanup
419 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
421 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
422 vector<string> fsi_files;
423 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
424 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
425 ::g_unlink(i->c_str());
432 PluginManager::clear_vst_blacklist ()
434 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
436 #ifdef WINDOWS_VST_SUPPORT
438 vector<string> fsi_files;
439 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
440 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
441 ::g_unlink(i->c_str());
448 vector<string> fsi_files;
449 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
450 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
451 ::g_unlink(i->c_str());
455 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
457 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
458 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
459 PBD::remove_directory (dir);
464 #endif // old blacklist cleanup
466 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
468 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
469 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
470 ::g_unlink (fn.c_str());
478 PluginManager::clear_au_cache ()
480 #ifdef AUDIOUNIT_SUPPORT
481 AUPluginInfo::clear_cache ();
486 PluginManager::clear_au_blacklist ()
488 #ifdef AUDIOUNIT_SUPPORT
489 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
490 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
491 ::g_unlink(fn.c_str());
497 PluginManager::lua_refresh ()
499 if (_lua_plugin_info) {
500 _lua_plugin_info->clear ();
502 _lua_plugin_info = new ARDOUR::PluginInfoList ();
504 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
505 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
506 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
507 _lua_plugin_info->push_back (lpi);
512 PluginManager::lua_refresh_cb ()
514 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
519 PluginListChanged (); /* EMIT SIGNAL */
523 PluginManager::ladspa_refresh ()
525 if (_ladspa_plugin_info) {
526 _ladspa_plugin_info->clear ();
528 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
531 /* allow LADSPA_PATH to augment, not override standard locations */
533 /* Only add standard locations to ladspa_path if it doesn't
534 * already contain them. Check for trailing G_DIR_SEPARATOR too.
537 vector<string> ladspa_modules;
539 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
541 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
542 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
543 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
545 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
546 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
547 ladspa_discover (*i);
552 static bool rdf_filter (const string &str, void* /*arg*/)
554 return str[0] != '.' &&
555 ((str.find(".rdf") == (str.length() - 4)) ||
556 (str.find(".rdfs") == (str.length() - 5)) ||
557 (str.find(".n3") == (str.length() - 3)) ||
558 (str.find(".ttl") == (str.length() - 4)));
563 PluginManager::add_ladspa_presets()
565 add_presets ("ladspa");
569 PluginManager::add_windows_vst_presets()
571 add_presets ("windows-vst");
575 PluginManager::add_mac_vst_presets()
577 add_presets ("mac-vst");
581 PluginManager::add_lxvst_presets()
583 add_presets ("lxvst");
587 PluginManager::add_presets(string domain)
590 vector<string> presets;
591 vector<string>::iterator x;
594 if ((envvar = getenv ("HOME")) == 0) {
598 string path = string_compose("%1/.%2/rdf", envvar, domain);
599 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
601 for (x = presets.begin(); x != presets.end (); ++x) {
602 string file = "file:" + *x;
603 if (lrdf_read_file(file.c_str())) {
604 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
612 PluginManager::add_lrdf_data (const string &path)
615 vector<string> rdf_files;
616 vector<string>::iterator x;
618 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
620 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
621 const string uri(string("file://") + *x);
623 if (lrdf_read_file(uri.c_str())) {
624 warning << "Could not parse rdf file: " << uri << endmsg;
631 PluginManager::ladspa_discover (string path)
633 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
635 Glib::Module module(path);
636 const LADSPA_Descriptor *descriptor;
637 LADSPA_Descriptor_Function dfunc;
641 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
642 path, Glib::Module::get_last_error()) << endmsg;
647 if (!module.get_symbol("ladspa_descriptor", func)) {
648 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
649 error << Glib::Module::get_last_error() << endmsg;
653 dfunc = (LADSPA_Descriptor_Function)func;
655 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
657 for (uint32_t i = 0; ; ++i) {
658 /* if a ladspa plugin allocates memory here
659 * it is never free()ed (or plugin-dependent only when unloading).
660 * For some plugins memory allocated is incremental, we should
661 * avoid re-scanning plugins and file bug reports.
663 if ((descriptor = dfunc (i)) == 0) {
667 if (!ladspa_plugin_whitelist.empty()) {
668 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
673 PluginInfoPtr info(new LadspaPluginInfo);
674 info->name = descriptor->Name;
675 info->category = get_ladspa_category(descriptor->UniqueID);
676 info->creator = descriptor->Maker;
679 info->n_inputs = ChanCount();
680 info->n_outputs = ChanCount();
681 info->type = ARDOUR::LADSPA;
684 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
685 info->unique_id = buf;
687 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
688 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
689 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
690 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
692 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
693 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
698 if(_ladspa_plugin_info->empty()){
699 _ladspa_plugin_info->push_back (info);
702 //Ensure that the plugin is not already in the plugin list.
706 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
707 if(0 == info->unique_id.compare((*i)->unique_id)){
713 _ladspa_plugin_info->push_back (info);
716 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
719 // GDB WILL NOT LIKE YOU IF YOU DO THIS
726 PluginManager::get_ladspa_category (uint32_t plugin_id)
730 lrdf_statement pattern;
732 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
733 pattern.subject = buf;
734 pattern.predicate = const_cast<char*>(RDF_TYPE);
736 pattern.object_type = lrdf_uri;
738 lrdf_statement* matches1 = lrdf_matches (&pattern);
744 pattern.subject = matches1->object;
745 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
747 pattern.object_type = lrdf_literal;
749 lrdf_statement* matches2 = lrdf_matches (&pattern);
750 lrdf_free_statements(matches1);
756 string label = matches2->object;
757 lrdf_free_statements(matches2);
759 /* Kludge LADSPA class names to be singular and match LV2 class names.
760 This avoids duplicate plugin menus for every class, which is necessary
761 to make the plugin category menu at all usable, but is obviously a
764 In the short term, lrdf could be updated so the labels match and a new
765 release made. To support both specs, we should probably be mapping the
766 URIs to the same category in code and perhaps tweaking that hierarchy
767 dynamically to suit the user. Personally, I (drobilla) think that time
768 is better spent replacing the little-used LRDF.
770 In the longer term, we will abandon LRDF entirely in favour of LV2 and
771 use that class hierarchy. Aside from fixing this problem properly, that
772 will also allow for translated labels. SWH plugins have been LV2 for
773 ages; TAP needs porting. I don't know of anything else with LRDF data.
775 if (label == "Utilities") {
777 } else if (label == "Pitch shifters") {
778 return "Pitch Shifter";
779 } else if (label != "Dynamics" && label != "Chorus"
780 &&label[label.length() - 1] == 's'
781 && label[label.length() - 2] != 's') {
782 return label.substr(0, label.length() - 1);
793 PluginManager::lv2_refresh ()
795 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
796 delete _lv2_plugin_info;
797 _lv2_plugin_info = LV2PluginInfo::discover();
801 #ifdef AUDIOUNIT_SUPPORT
803 PluginManager::au_refresh (bool cache_only)
805 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
807 // disable automatic discovery in case we crash
808 bool discover_at_start = Config->get_discover_audio_units ();
809 Config->set_discover_audio_units (false);
810 Config->save_state();
812 delete _au_plugin_info;
813 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
815 // successful scan re-enabled automatic discovery if it was set
816 Config->set_discover_audio_units (discover_at_start);
817 Config->save_state();
822 #ifdef WINDOWS_VST_SUPPORT
825 PluginManager::windows_vst_refresh (bool cache_only)
827 if (_windows_vst_plugin_info) {
828 _windows_vst_plugin_info->clear ();
830 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
833 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
836 static bool windows_vst_filter (const string& str, void * /*arg*/)
838 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
839 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
843 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
845 vector<string> plugin_objects;
846 vector<string>::iterator x;
849 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
851 if (Session::get_disable_all_loaded_plugins ()) {
852 info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
856 if (Config->get_verbose_plugin_scan()) {
857 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
860 find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
862 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
863 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
864 windows_vst_discover (*x, cache_only || cancelled());
867 if (Config->get_verbose_plugin_scan()) {
868 info << _("--- Windows VST plugins Scan Done") << endmsg;
874 static std::string dll_info (std::string path) {
878 off_t pe_hdr_off = 0;
880 int fd = g_open(path.c_str(), O_RDONLY, 0444);
883 return _("cannot open dll"); // TODO strerror()
886 if (68 != read (fd, buf, 68)) {
887 rv = _("invalid dll, file too small");
890 if (buf[0] != 'M' && buf[1] != 'Z') {
895 pe_hdr_off = *((int32_t*) &buf[60]);
896 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
897 rv = _("cannot determine dll type");
900 if (6 != read (fd, buf, 6)) {
901 rv = _("cannot read dll PE header");
905 if (buf[0] != 'P' && buf[1] != 'E') {
906 rv = _("invalid dll PE header");
910 type = *((uint16_t*) &buf[4]);
913 rv = _("i386 (32-bit)");
919 rv = _("x64 (64-bit)");
922 rv = _("Native Architecture");
925 rv = _("Unknown Architecture");
929 assert (rv.length() > 0);
935 PluginManager::windows_vst_discover (string path, bool cache_only)
937 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
939 if (Config->get_verbose_plugin_scan()) {
941 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
943 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
947 _cancel_timeout = false;
948 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
949 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
951 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
952 // .err file scanner output etc.
954 if (finfos->empty()) {
955 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
956 if (Config->get_verbose_plugin_scan()) {
957 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
962 uint32_t discovered = 0;
963 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
967 if (!finfo->canProcessReplacing) {
968 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
969 finfo->name, PROGRAM_NAME)
974 PluginInfoPtr info (new WindowsVSTPluginInfo);
976 /* what a joke freeware VST is */
978 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
979 info->name = PBD::basename_nosuffix (path);
981 info->name = finfo->name;
985 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
986 info->unique_id = buf;
987 info->category = "VST";
989 info->creator = finfo->creator;
991 info->n_inputs.set_audio (finfo->numInputs);
992 info->n_outputs.set_audio (finfo->numOutputs);
993 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
994 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
995 info->type = ARDOUR::Windows_VST;
997 // TODO: check dup-IDs (lxvst AND windows vst)
998 bool duplicate = false;
1000 if (!_windows_vst_plugin_info->empty()) {
1001 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
1002 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
1003 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1011 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1012 _windows_vst_plugin_info->push_back (info);
1014 if (Config->get_verbose_plugin_scan()) {
1015 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1020 vstfx_free_info_list (finfos);
1021 return discovered > 0 ? 0 : -1;
1024 #endif // WINDOWS_VST_SUPPORT
1026 #ifdef MACVST_SUPPORT
1028 PluginManager::mac_vst_refresh (bool cache_only)
1030 if (_mac_vst_plugin_info) {
1031 _mac_vst_plugin_info->clear ();
1033 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1036 mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1039 static bool mac_vst_filter (const string& str)
1041 string plist = Glib::build_filename (str, "Contents", "Info.plist");
1042 if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1045 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1049 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1051 if (Session::get_disable_all_loaded_plugins ()) {
1052 info << _("Disabled MacVST scan (safe mode)") << endmsg;
1056 Searchpath paths (path);
1057 /* customized version of run_functor_for_paths() */
1058 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1059 string expanded_path = path_expand (*i);
1060 if (!Glib::file_test (expanded_path, Glib::FILE_TEST_IS_DIR)) continue;
1062 Glib::Dir dir(expanded_path);
1063 for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
1064 string fullpath = Glib::build_filename (expanded_path, *di);
1066 /* we're only interested in bundles */
1067 if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
1071 if (mac_vst_filter (fullpath)) {
1072 ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled());
1073 mac_vst_discover (fullpath, cache_only || cancelled());
1077 /* don't descend into AU bundles in the VST dir */
1078 if (fullpath[0] == '.' || (fullpath.length() > 10 && strings_equal_ignore_case (".component", fullpath.substr(fullpath.length() - 10)))) {
1083 mac_vst_discover_from_path (fullpath, cache_only);
1085 } catch (Glib::FileError& err) { }
1092 PluginManager::mac_vst_discover (string path, bool cache_only)
1094 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1096 _cancel_timeout = false;
1098 vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1099 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1101 if (finfos->empty()) {
1102 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1106 uint32_t discovered = 0;
1107 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1108 VSTInfo* finfo = *x;
1111 if (!finfo->canProcessReplacing) {
1112 warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1113 finfo->name, PROGRAM_NAME)
1118 PluginInfoPtr info (new MacVSTPluginInfo);
1120 info->name = finfo->name;
1122 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1123 info->unique_id = buf;
1124 info->category = "MacVST";
1126 info->creator = finfo->creator;
1128 info->n_inputs.set_audio (finfo->numInputs);
1129 info->n_outputs.set_audio (finfo->numOutputs);
1130 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1131 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1132 info->type = ARDOUR::MacVST;
1134 bool duplicate = false;
1135 if (!_mac_vst_plugin_info->empty()) {
1136 for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1137 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1138 warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1146 _mac_vst_plugin_info->push_back (info);
1151 vstfx_free_info_list (finfos);
1152 return discovered > 0 ? 0 : -1;
1155 #endif // MAC_VST_SUPPORT
1157 #ifdef LXVST_SUPPORT
1160 PluginManager::lxvst_refresh (bool cache_only)
1162 if (_lxvst_plugin_info) {
1163 _lxvst_plugin_info->clear ();
1165 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1168 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1171 static bool lxvst_filter (const string& str, void *)
1173 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1175 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1179 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1181 vector<string> plugin_objects;
1182 vector<string>::iterator x;
1185 if (Session::get_disable_all_loaded_plugins ()) {
1186 info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
1194 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1196 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1198 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1199 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1200 lxvst_discover (*x, cache_only || cancelled());
1207 PluginManager::lxvst_discover (string path, bool cache_only)
1209 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1211 _cancel_timeout = false;
1212 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1213 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1215 if (finfos->empty()) {
1216 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1220 uint32_t discovered = 0;
1221 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1222 VSTInfo* finfo = *x;
1225 if (!finfo->canProcessReplacing) {
1226 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1227 finfo->name, PROGRAM_NAME)
1232 PluginInfoPtr info(new LXVSTPluginInfo);
1234 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1235 info->name = PBD::basename_nosuffix (path);
1237 info->name = finfo->name;
1241 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1242 info->unique_id = buf;
1243 info->category = "linuxVSTs";
1245 info->creator = finfo->creator;
1247 info->n_inputs.set_audio (finfo->numInputs);
1248 info->n_outputs.set_audio (finfo->numOutputs);
1249 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1250 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1251 info->type = ARDOUR::LXVST;
1253 /* Make sure we don't find the same plugin in more than one place along
1254 the LXVST_PATH We can't use a simple 'find' because the path is included
1255 in the PluginInfo, and that is the one thing we can be sure MUST be
1256 different if a duplicate instance is found. So we just compare the type
1257 and unique ID (which for some VSTs isn't actually unique...)
1260 // TODO: check dup-IDs with windowsVST, too
1261 bool duplicate = false;
1262 if (!_lxvst_plugin_info->empty()) {
1263 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1264 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1265 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1273 _lxvst_plugin_info->push_back (info);
1278 vstfx_free_info_list (finfos);
1279 return discovered > 0 ? 0 : -1;
1282 #endif // LXVST_SUPPORT
1285 PluginManager::PluginStatusType
1286 PluginManager::get_status (const PluginInfoPtr& pi) const
1288 PluginStatus ps (pi->type, pi->unique_id);
1289 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1290 if (i == statuses.end() ) {
1298 PluginManager::save_statuses ()
1300 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1303 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1304 switch ((*i).type) {
1315 ofs << "Windows-VST";
1330 switch ((*i).status) {
1343 ofs << (*i).unique_id;;
1346 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1347 PluginStatusesChanged (); /* EMIT SIGNAL */
1351 PluginManager::load_statuses ()
1353 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1355 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1358 stringstream ifs (fbuf);
1362 std::string sstatus;
1365 PluginStatusType status;
1382 /* rest of the line is the plugin ID */
1384 ifs.getline (buf, sizeof (buf), '\n');
1389 if (sstatus == "Normal") {
1391 } else if (sstatus == "Favorite") {
1393 } else if (sstatus == "Hidden") {
1396 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1402 if (stype == "LADSPA") {
1404 } else if (stype == "AudioUnit") {
1406 } else if (stype == "LV2") {
1408 } else if (stype == "Windows-VST") {
1410 } else if (stype == "LXVST") {
1412 } else if (stype == "MacVST") {
1414 } else if (stype == "Lua") {
1417 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1423 strip_whitespace_edges (id);
1424 set_status (type, id, status);
1429 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1431 PluginStatus ps (t, id, status);
1432 statuses.erase (ps);
1434 if (status == Normal) {
1438 statuses.insert (ps);
1442 PluginManager::user_plugin_metadata_dir () const
1444 std::string dir = Glib::build_filename (user_config_directory(), plugin_metadata_dir_name);
1445 g_mkdir_with_parents (dir.c_str(), 0744);
1449 const ARDOUR::PluginInfoList&
1450 PluginManager::windows_vst_plugin_info ()
1452 #ifdef WINDOWS_VST_SUPPORT
1453 if (!_windows_vst_plugin_info) {
1454 windows_vst_refresh ();
1456 return *_windows_vst_plugin_info;
1458 return _empty_plugin_info;
1462 const ARDOUR::PluginInfoList&
1463 PluginManager::mac_vst_plugin_info ()
1465 #ifdef MACVST_SUPPORT
1466 assert(_mac_vst_plugin_info);
1467 return *_mac_vst_plugin_info;
1469 return _empty_plugin_info;
1473 const ARDOUR::PluginInfoList&
1474 PluginManager::lxvst_plugin_info ()
1476 #ifdef LXVST_SUPPORT
1477 assert(_lxvst_plugin_info);
1478 return *_lxvst_plugin_info;
1480 return _empty_plugin_info;
1484 const ARDOUR::PluginInfoList&
1485 PluginManager::ladspa_plugin_info ()
1487 assert(_ladspa_plugin_info);
1488 return *_ladspa_plugin_info;
1491 const ARDOUR::PluginInfoList&
1492 PluginManager::lv2_plugin_info ()
1495 assert(_lv2_plugin_info);
1496 return *_lv2_plugin_info;
1498 return _empty_plugin_info;
1502 const ARDOUR::PluginInfoList&
1503 PluginManager::au_plugin_info ()
1505 #ifdef AUDIOUNIT_SUPPORT
1506 if (_au_plugin_info) {
1507 return *_au_plugin_info;
1510 return _empty_plugin_info;
1513 const ARDOUR::PluginInfoList&
1514 PluginManager::lua_plugin_info ()
1516 assert(_lua_plugin_info);
1517 return *_lua_plugin_info;