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"
64 #endif //MACVST_SUPPORT
66 #include <glibmm/miscutils.h>
67 #include <glibmm/pattern.h>
68 #include <glibmm/fileutils.h>
69 #include <glibmm/miscutils.h>
71 #include "pbd/whitespace.h"
72 #include "pbd/file_utils.h"
74 #include "ardour/debug.h"
75 #include "ardour/filesystem_paths.h"
76 #include "ardour/ladspa.h"
77 #include "ardour/ladspa_plugin.h"
78 #include "ardour/luascripting.h"
79 #include "ardour/luaproc.h"
80 #include "ardour/plugin.h"
81 #include "ardour/plugin_manager.h"
82 #include "ardour/rc_configuration.h"
84 #include "ardour/search_paths.h"
87 #include "ardour/lv2_plugin.h"
90 #ifdef WINDOWS_VST_SUPPORT
91 #include "ardour/windows_vst_plugin.h"
95 #include "ardour/lxvst_plugin.h"
98 #ifdef AUDIOUNIT_SUPPORT
99 #include "ardour/audio_unit.h"
100 #include <Carbon/Carbon.h>
103 #include "pbd/error.h"
104 #include "pbd/stl_delete.h"
106 #include "pbd/i18n.h"
108 #include "ardour/debug.h"
110 using namespace ARDOUR;
114 PluginManager* PluginManager::_instance = 0;
115 std::string PluginManager::scanner_bin_path = "";
118 PluginManager::instance()
121 _instance = new PluginManager;
126 PluginManager::PluginManager ()
127 : _windows_vst_plugin_info(0)
128 , _lxvst_plugin_info(0)
129 , _mac_vst_plugin_info(0)
130 , _ladspa_plugin_info(0)
131 , _lv2_plugin_info(0)
133 , _lua_plugin_info(0)
134 , _cancel_scan(false)
135 , _cancel_timeout(false)
140 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
141 // source-tree (ardev, etc)
142 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
144 #ifdef PLATFORM_WINDOWS
145 // on windows the .exe needs to be in the same folder with libardour.dll
146 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
148 // on Unices additional internal-use binaries are deployed to $libdir
149 vstsp += ARDOUR::ardour_dll_directory();
152 if (!PBD::find_file (vstsp,
153 #ifdef PLATFORM_WINDOWS
154 #ifdef DEBUGGABLE_SCANNER_APP
155 #if defined(DEBUG) || defined(_DEBUG)
156 "ardour-vst-scannerD.exe"
158 "ardour-vst-scannerRDC.exe"
161 "ardour-vst-scanner.exe"
166 , scanner_bin_path)) {
167 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
173 if ((s = getenv ("LADSPA_RDF_PATH"))){
177 if (lrdf_path.length() == 0) {
178 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
181 add_lrdf_data(lrdf_path);
182 add_ladspa_presets();
183 #ifdef WINDOWS_VST_SUPPORT
184 if (Config->get_use_windows_vst ()) {
185 add_windows_vst_presets ();
187 #endif /* WINDOWS_VST_SUPPORT */
190 if (Config->get_use_lxvst()) {
193 #endif /* Native LinuxVST support*/
195 #ifdef MACVST_SUPPORT
196 if (Config->get_use_macvst ()) {
197 add_mac_vst_presets ();
201 if ((s = getenv ("VST_PATH"))) {
202 windows_vst_path = s;
203 } else if ((s = getenv ("VST_PLUGINS"))) {
204 windows_vst_path = s;
207 if (windows_vst_path.length() == 0) {
208 windows_vst_path = vst_search_path ();
211 if ((s = getenv ("LXVST_PATH"))) {
213 } else if ((s = getenv ("LXVST_PLUGINS"))) {
217 if (lxvst_path.length() == 0) {
218 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
219 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
220 "/usr/lib/vst:/usr/local/lib/vst";
223 /* first time setup, use 'default' path */
224 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
225 Config->set_plugin_path_lxvst(get_default_lxvst_path());
227 if (Config->get_plugin_path_vst() == X_("@default@")) {
228 Config->set_plugin_path_vst(get_default_windows_vst_path());
231 if (_instance == 0) {
235 BootMessage (_("Discovering Plugins"));
237 LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
241 PluginManager::~PluginManager()
243 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
244 // don't bother, just exit quickly.
245 delete _windows_vst_plugin_info;
246 delete _lxvst_plugin_info;
247 delete _mac_vst_plugin_info;
248 delete _ladspa_plugin_info;
249 delete _lv2_plugin_info;
250 delete _au_plugin_info;
251 delete _lua_plugin_info;
256 PluginManager::refresh (bool cache_only)
258 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
264 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
265 _cancel_scan = false;
267 BootMessage (_("Scanning LADSPA Plugins"));
269 BootMessage (_("Scanning Lua DSP Processors"));
272 BootMessage (_("Scanning LV2 Plugins"));
275 #ifdef WINDOWS_VST_SUPPORT
276 if (Config->get_use_windows_vst()) {
278 BootMessage (_("Scanning Windows VST Plugins"));
280 BootMessage (_("Discovering Windows VST Plugins"));
282 windows_vst_refresh (cache_only);
284 #endif // WINDOWS_VST_SUPPORT
287 if(Config->get_use_lxvst()) {
289 BootMessage (_("Scanning Linux VST Plugins"));
291 BootMessage (_("Discovering Linux VST Plugins"));
293 lxvst_refresh(cache_only);
295 #endif //Native linuxVST SUPPORT
297 #ifdef MACVST_SUPPORT
298 if(Config->get_use_macvst ()) {
300 BootMessage (_("Scanning Mac VST Plugins"));
302 BootMessage (_("Discovering Mac VST Plugins"));
304 mac_vst_refresh (cache_only);
305 } else if (_mac_vst_plugin_info) {
306 _mac_vst_plugin_info->clear ();
308 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
310 #endif //Native Mac VST SUPPORT
312 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
314 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
315 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
317 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
318 if (Config->get_verbose_plugin_scan()) {
319 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
321 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
329 #ifdef AUDIOUNIT_SUPPORT
331 BootMessage (_("Scanning AU Plugins"));
333 BootMessage (_("Discovering AU Plugins"));
335 au_refresh (cache_only);
338 BootMessage (_("Plugin Scan Complete..."));
339 PluginListChanged (); /* EMIT SIGNAL */
340 PluginScanMessage(X_("closeme"), "", false);
341 _cancel_scan = false;
345 PluginManager::cancel_plugin_scan ()
351 PluginManager::cancel_plugin_timeout ()
353 _cancel_timeout = true;
357 PluginManager::clear_vst_cache ()
359 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
360 #ifdef WINDOWS_VST_SUPPORT
362 vector<string> fsi_files;
363 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
364 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
365 ::g_unlink(i->c_str());
369 vector<string> fsi_files;
370 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
371 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
372 ::g_unlink(i->c_str());
376 vector<string> fsi_files;
377 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
378 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
379 ::g_unlink(i->c_str());
386 vector<string> fsi_files;
387 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
388 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
389 ::g_unlink(i->c_str());
393 vector<string> fsi_files;
394 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
395 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
396 ::g_unlink(i->c_str());
400 vector<string> fsi_files;
401 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
402 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
403 ::g_unlink(i->c_str());
407 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
409 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
410 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
411 PBD::remove_directory (dir);
415 #endif // old cache cleanup
417 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
419 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
420 vector<string> fsi_files;
421 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
422 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
423 ::g_unlink(i->c_str());
430 PluginManager::clear_vst_blacklist ()
432 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
434 #ifdef WINDOWS_VST_SUPPORT
436 vector<string> fsi_files;
437 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
438 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
439 ::g_unlink(i->c_str());
446 vector<string> fsi_files;
447 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
448 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
449 ::g_unlink(i->c_str());
453 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
455 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
456 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
457 PBD::remove_directory (dir);
462 #endif // old blacklist cleanup
464 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
466 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
467 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
468 ::g_unlink (fn.c_str());
476 PluginManager::clear_au_cache ()
478 #ifdef AUDIOUNIT_SUPPORT
479 AUPluginInfo::clear_cache ();
484 PluginManager::clear_au_blacklist ()
486 #ifdef AUDIOUNIT_SUPPORT
487 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
488 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
489 ::g_unlink(fn.c_str());
495 PluginManager::lua_refresh ()
497 if (_lua_plugin_info) {
498 _lua_plugin_info->clear ();
500 _lua_plugin_info = new ARDOUR::PluginInfoList ();
502 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
503 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
504 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
505 _lua_plugin_info->push_back (lpi);
510 PluginManager::lua_refresh_cb ()
512 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
517 PluginListChanged (); /* EMIT SIGNAL */
521 PluginManager::ladspa_refresh ()
523 if (_ladspa_plugin_info) {
524 _ladspa_plugin_info->clear ();
526 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
529 /* allow LADSPA_PATH to augment, not override standard locations */
531 /* Only add standard locations to ladspa_path if it doesn't
532 * already contain them. Check for trailing G_DIR_SEPARATOR too.
535 vector<string> ladspa_modules;
537 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
539 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
540 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
541 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
543 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
544 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
545 ladspa_discover (*i);
550 static bool rdf_filter (const string &str, void* /*arg*/)
552 return str[0] != '.' &&
553 ((str.find(".rdf") == (str.length() - 4)) ||
554 (str.find(".rdfs") == (str.length() - 5)) ||
555 (str.find(".n3") == (str.length() - 3)) ||
556 (str.find(".ttl") == (str.length() - 4)));
561 PluginManager::add_ladspa_presets()
563 add_presets ("ladspa");
567 PluginManager::add_windows_vst_presets()
569 add_presets ("windows-vst");
573 PluginManager::add_mac_vst_presets()
575 add_presets ("mac-vst");
579 PluginManager::add_lxvst_presets()
581 add_presets ("lxvst");
585 PluginManager::add_presets(string domain)
588 vector<string> presets;
589 vector<string>::iterator x;
592 if ((envvar = getenv ("HOME")) == 0) {
596 string path = string_compose("%1/.%2/rdf", envvar, domain);
597 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
599 for (x = presets.begin(); x != presets.end (); ++x) {
600 string file = "file:" + *x;
601 if (lrdf_read_file(file.c_str())) {
602 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
610 PluginManager::add_lrdf_data (const string &path)
613 vector<string> rdf_files;
614 vector<string>::iterator x;
616 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
618 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
619 const string uri(string("file://") + *x);
621 if (lrdf_read_file(uri.c_str())) {
622 warning << "Could not parse rdf file: " << uri << endmsg;
629 PluginManager::ladspa_discover (string path)
631 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
633 Glib::Module module(path);
634 const LADSPA_Descriptor *descriptor;
635 LADSPA_Descriptor_Function dfunc;
639 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
640 path, Glib::Module::get_last_error()) << endmsg;
645 if (!module.get_symbol("ladspa_descriptor", func)) {
646 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
647 error << Glib::Module::get_last_error() << endmsg;
651 dfunc = (LADSPA_Descriptor_Function)func;
653 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
655 for (uint32_t i = 0; ; ++i) {
656 /* if a ladspa plugin allocates memory here
657 * it is never free()ed (or plugin-dependent only when unloading).
658 * For some plugins memory allocated is incremental, we should
659 * avoid re-scanning plugins and file bug reports.
661 if ((descriptor = dfunc (i)) == 0) {
665 if (!ladspa_plugin_whitelist.empty()) {
666 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
671 PluginInfoPtr info(new LadspaPluginInfo);
672 info->name = descriptor->Name;
673 info->category = get_ladspa_category(descriptor->UniqueID);
674 info->creator = descriptor->Maker;
677 info->n_inputs = ChanCount();
678 info->n_outputs = ChanCount();
679 info->type = ARDOUR::LADSPA;
682 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
683 info->unique_id = buf;
685 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
686 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
687 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
688 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
690 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
691 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
696 if(_ladspa_plugin_info->empty()){
697 _ladspa_plugin_info->push_back (info);
700 //Ensure that the plugin is not already in the plugin list.
704 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
705 if(0 == info->unique_id.compare((*i)->unique_id)){
711 _ladspa_plugin_info->push_back (info);
714 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
717 // GDB WILL NOT LIKE YOU IF YOU DO THIS
724 PluginManager::get_ladspa_category (uint32_t plugin_id)
728 lrdf_statement pattern;
730 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
731 pattern.subject = buf;
732 pattern.predicate = const_cast<char*>(RDF_TYPE);
734 pattern.object_type = lrdf_uri;
736 lrdf_statement* matches1 = lrdf_matches (&pattern);
742 pattern.subject = matches1->object;
743 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
745 pattern.object_type = lrdf_literal;
747 lrdf_statement* matches2 = lrdf_matches (&pattern);
748 lrdf_free_statements(matches1);
754 string label = matches2->object;
755 lrdf_free_statements(matches2);
757 /* Kludge LADSPA class names to be singular and match LV2 class names.
758 This avoids duplicate plugin menus for every class, which is necessary
759 to make the plugin category menu at all usable, but is obviously a
762 In the short term, lrdf could be updated so the labels match and a new
763 release made. To support both specs, we should probably be mapping the
764 URIs to the same category in code and perhaps tweaking that hierarchy
765 dynamically to suit the user. Personally, I (drobilla) think that time
766 is better spent replacing the little-used LRDF.
768 In the longer term, we will abandon LRDF entirely in favour of LV2 and
769 use that class hierarchy. Aside from fixing this problem properly, that
770 will also allow for translated labels. SWH plugins have been LV2 for
771 ages; TAP needs porting. I don't know of anything else with LRDF data.
773 if (label == "Utilities") {
775 } else if (label == "Pitch shifters") {
776 return "Pitch Shifter";
777 } else if (label != "Dynamics" && label != "Chorus"
778 &&label[label.length() - 1] == 's'
779 && label[label.length() - 2] != 's') {
780 return label.substr(0, label.length() - 1);
791 PluginManager::lv2_refresh ()
793 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
794 delete _lv2_plugin_info;
795 _lv2_plugin_info = LV2PluginInfo::discover();
799 #ifdef AUDIOUNIT_SUPPORT
801 PluginManager::au_refresh (bool cache_only)
803 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
805 // disable automatic discovery in case we crash
806 bool discover_at_start = Config->get_discover_audio_units ();
807 Config->set_discover_audio_units (false);
808 Config->save_state();
810 delete _au_plugin_info;
811 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
813 // successful scan re-enabled automatic discovery if it was set
814 Config->set_discover_audio_units (discover_at_start);
815 Config->save_state();
820 #ifdef WINDOWS_VST_SUPPORT
823 PluginManager::windows_vst_refresh (bool cache_only)
825 if (_windows_vst_plugin_info) {
826 _windows_vst_plugin_info->clear ();
828 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
831 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
834 static bool windows_vst_filter (const string& str, void * /*arg*/)
836 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
837 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
841 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
843 vector<string> plugin_objects;
844 vector<string>::iterator x;
847 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
849 if (Config->get_verbose_plugin_scan()) {
850 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
853 find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
855 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
856 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
857 windows_vst_discover (*x, cache_only || cancelled());
860 if (Config->get_verbose_plugin_scan()) {
861 info << _("--- Windows VST plugins Scan Done") << endmsg;
867 static std::string dll_info (std::string path) {
871 off_t pe_hdr_off = 0;
873 int fd = g_open(path.c_str(), O_RDONLY, 0444);
876 return _("cannot open dll"); // TODO strerror()
879 if (68 != read (fd, buf, 68)) {
880 rv = _("invalid dll, file too small");
883 if (buf[0] != 'M' && buf[1] != 'Z') {
888 pe_hdr_off = *((int32_t*) &buf[60]);
889 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
890 rv = _("cannot determine dll type");
893 if (6 != read (fd, buf, 6)) {
894 rv = _("cannot read dll PE header");
898 if (buf[0] != 'P' && buf[1] != 'E') {
899 rv = _("invalid dll PE header");
903 type = *((uint16_t*) &buf[4]);
906 rv = _("i386 (32-bit)");
912 rv = _("x64 (64-bit)");
915 rv = _("Native Architecture");
918 rv = _("Unknown Architecture");
922 assert (rv.length() > 0);
928 PluginManager::windows_vst_discover (string path, bool cache_only)
930 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
932 if (Config->get_verbose_plugin_scan()) {
934 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
936 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
940 _cancel_timeout = false;
941 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
942 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
944 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
945 // .err file scanner output etc.
947 if (finfos->empty()) {
948 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
949 if (Config->get_verbose_plugin_scan()) {
950 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
955 uint32_t discovered = 0;
956 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
960 if (!finfo->canProcessReplacing) {
961 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
962 finfo->name, PROGRAM_NAME)
967 PluginInfoPtr info (new WindowsVSTPluginInfo);
969 /* what a joke freeware VST is */
971 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
972 info->name = PBD::basename_nosuffix (path);
974 info->name = finfo->name;
978 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
979 info->unique_id = buf;
980 info->category = "VST";
982 info->creator = finfo->creator;
984 info->n_inputs.set_audio (finfo->numInputs);
985 info->n_outputs.set_audio (finfo->numOutputs);
986 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
987 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
988 info->type = ARDOUR::Windows_VST;
990 // TODO: check dup-IDs (lxvst AND windows vst)
991 bool duplicate = false;
993 if (!_windows_vst_plugin_info->empty()) {
994 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
995 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
996 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1004 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1005 _windows_vst_plugin_info->push_back (info);
1007 if (Config->get_verbose_plugin_scan()) {
1008 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1013 vstfx_free_info_list (finfos);
1014 return discovered > 0 ? 0 : -1;
1017 #endif // WINDOWS_VST_SUPPORT
1019 #ifdef MACVST_SUPPORT
1021 PluginManager::mac_vst_refresh (bool cache_only)
1023 if (_mac_vst_plugin_info) {
1024 _mac_vst_plugin_info->clear ();
1026 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1029 mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1032 static bool mac_vst_filter (const string& str, void *)
1034 if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
1037 string plist = Glib::build_filename (str, "Contents", "Info.plist");
1038 if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1041 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1045 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1047 vector<string> plugin_objects;
1048 vector<string>::iterator x;
1050 find_paths_matching_filter (plugin_objects, path, mac_vst_filter, 0, true, true, true);
1052 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1053 ARDOUR::PluginScanMessage(_("MacVST"), *x, !cache_only && !cancelled());
1054 mac_vst_discover (*x, cache_only || cancelled());
1060 PluginManager::mac_vst_discover (string path, bool cache_only)
1062 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1064 _cancel_timeout = false;
1066 vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1067 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1069 if (finfos->empty()) {
1070 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1074 uint32_t discovered = 0;
1075 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1076 VSTInfo* finfo = *x;
1079 if (!finfo->canProcessReplacing) {
1080 warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1081 finfo->name, PROGRAM_NAME)
1086 PluginInfoPtr info (new MacVSTPluginInfo);
1088 info->name = finfo->name;
1090 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1091 info->unique_id = buf;
1092 info->category = "MacVST";
1094 info->creator = finfo->creator;
1096 info->n_inputs.set_audio (finfo->numInputs);
1097 info->n_outputs.set_audio (finfo->numOutputs);
1098 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1099 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1100 info->type = ARDOUR::MacVST;
1102 bool duplicate = false;
1103 if (!_mac_vst_plugin_info->empty()) {
1104 for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1105 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1106 warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1114 _mac_vst_plugin_info->push_back (info);
1119 vstfx_free_info_list (finfos);
1120 return discovered > 0 ? 0 : -1;
1123 #endif // MAC_VST_SUPPORT
1125 #ifdef LXVST_SUPPORT
1128 PluginManager::lxvst_refresh (bool cache_only)
1130 if (_lxvst_plugin_info) {
1131 _lxvst_plugin_info->clear ();
1133 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1136 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1139 static bool lxvst_filter (const string& str, void *)
1141 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1143 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1147 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1149 vector<string> plugin_objects;
1150 vector<string>::iterator x;
1157 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1159 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1161 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1162 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1163 lxvst_discover (*x, cache_only || cancelled());
1170 PluginManager::lxvst_discover (string path, bool cache_only)
1172 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1174 _cancel_timeout = false;
1175 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1176 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1178 if (finfos->empty()) {
1179 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1183 uint32_t discovered = 0;
1184 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1185 VSTInfo* finfo = *x;
1188 if (!finfo->canProcessReplacing) {
1189 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1190 finfo->name, PROGRAM_NAME)
1195 PluginInfoPtr info(new LXVSTPluginInfo);
1197 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1198 info->name = PBD::basename_nosuffix (path);
1200 info->name = finfo->name;
1204 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1205 info->unique_id = buf;
1206 info->category = "linuxVSTs";
1208 info->creator = finfo->creator;
1210 info->n_inputs.set_audio (finfo->numInputs);
1211 info->n_outputs.set_audio (finfo->numOutputs);
1212 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1213 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1214 info->type = ARDOUR::LXVST;
1216 /* Make sure we don't find the same plugin in more than one place along
1217 the LXVST_PATH We can't use a simple 'find' because the path is included
1218 in the PluginInfo, and that is the one thing we can be sure MUST be
1219 different if a duplicate instance is found. So we just compare the type
1220 and unique ID (which for some VSTs isn't actually unique...)
1223 // TODO: check dup-IDs with windowsVST, too
1224 bool duplicate = false;
1225 if (!_lxvst_plugin_info->empty()) {
1226 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1227 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1228 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1236 _lxvst_plugin_info->push_back (info);
1241 vstfx_free_info_list (finfos);
1242 return discovered > 0 ? 0 : -1;
1245 #endif // LXVST_SUPPORT
1248 PluginManager::PluginStatusType
1249 PluginManager::get_status (const PluginInfoPtr& pi) const
1251 PluginStatus ps (pi->type, pi->unique_id);
1252 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1253 if (i == statuses.end() ) {
1261 PluginManager::save_statuses ()
1263 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1266 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1267 switch ((*i).type) {
1278 ofs << "Windows-VST";
1293 switch ((*i).status) {
1306 ofs << (*i).unique_id;;
1309 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1310 PluginStatusesChanged (); /* EMIT SIGNAL */
1314 PluginManager::load_statuses ()
1316 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1318 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1321 stringstream ifs (fbuf);
1325 std::string sstatus;
1328 PluginStatusType status;
1345 /* rest of the line is the plugin ID */
1347 ifs.getline (buf, sizeof (buf), '\n');
1352 if (sstatus == "Normal") {
1354 } else if (sstatus == "Favorite") {
1356 } else if (sstatus == "Hidden") {
1359 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1365 if (stype == "LADSPA") {
1367 } else if (stype == "AudioUnit") {
1369 } else if (stype == "LV2") {
1371 } else if (stype == "Windows-VST") {
1373 } else if (stype == "LXVST") {
1375 } else if (stype == "Lua") {
1378 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1384 strip_whitespace_edges (id);
1385 set_status (type, id, status);
1390 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1392 PluginStatus ps (t, id, status);
1393 statuses.erase (ps);
1395 if (status == Normal) {
1399 statuses.insert (ps);
1402 const ARDOUR::PluginInfoList&
1403 PluginManager::windows_vst_plugin_info ()
1405 #ifdef WINDOWS_VST_SUPPORT
1406 if (!_windows_vst_plugin_info) {
1407 windows_vst_refresh ();
1409 return *_windows_vst_plugin_info;
1411 return _empty_plugin_info;
1415 const ARDOUR::PluginInfoList&
1416 PluginManager::mac_vst_plugin_info ()
1418 #ifdef MACVST_SUPPORT
1419 assert(_mac_vst_plugin_info);
1420 return *_mac_vst_plugin_info;
1422 return _empty_plugin_info;
1426 const ARDOUR::PluginInfoList&
1427 PluginManager::lxvst_plugin_info ()
1429 #ifdef LXVST_SUPPORT
1430 assert(_lxvst_plugin_info);
1431 return *_lxvst_plugin_info;
1433 return _empty_plugin_info;
1437 const ARDOUR::PluginInfoList&
1438 PluginManager::ladspa_plugin_info ()
1440 assert(_ladspa_plugin_info);
1441 return *_ladspa_plugin_info;
1444 const ARDOUR::PluginInfoList&
1445 PluginManager::lv2_plugin_info ()
1448 assert(_lv2_plugin_info);
1449 return *_lv2_plugin_info;
1451 return _empty_plugin_info;
1455 const ARDOUR::PluginInfoList&
1456 PluginManager::au_plugin_info ()
1458 #ifdef AUDIOUNIT_SUPPORT
1459 if (_au_plugin_info) {
1460 return *_au_plugin_info;
1463 return _empty_plugin_info;
1466 const ARDOUR::PluginInfoList&
1467 PluginManager::lua_plugin_info ()
1469 assert(_lua_plugin_info);
1470 return *_lua_plugin_info;