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/debug.h"
76 #include "ardour/filesystem_paths.h"
77 #include "ardour/ladspa.h"
78 #include "ardour/ladspa_plugin.h"
79 #include "ardour/luascripting.h"
80 #include "ardour/luaproc.h"
81 #include "ardour/plugin.h"
82 #include "ardour/plugin_manager.h"
83 #include "ardour/rc_configuration.h"
85 #include "ardour/search_paths.h"
88 #include "ardour/lv2_plugin.h"
91 #ifdef WINDOWS_VST_SUPPORT
92 #include "ardour/windows_vst_plugin.h"
96 #include "ardour/lxvst_plugin.h"
99 #ifdef AUDIOUNIT_SUPPORT
100 #include "ardour/audio_unit.h"
101 #include <Carbon/Carbon.h>
104 #include "pbd/error.h"
105 #include "pbd/stl_delete.h"
107 #include "pbd/i18n.h"
109 #include "ardour/debug.h"
111 using namespace ARDOUR;
115 PluginManager* PluginManager::_instance = 0;
116 std::string PluginManager::scanner_bin_path = "";
119 PluginManager::instance()
122 _instance = new PluginManager;
127 PluginManager::PluginManager ()
128 : _windows_vst_plugin_info(0)
129 , _lxvst_plugin_info(0)
130 , _mac_vst_plugin_info(0)
131 , _ladspa_plugin_info(0)
132 , _lv2_plugin_info(0)
134 , _lua_plugin_info(0)
135 , _cancel_scan(false)
136 , _cancel_timeout(false)
141 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
142 // source-tree (ardev, etc)
143 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
145 #ifdef PLATFORM_WINDOWS
146 // on windows the .exe needs to be in the same folder with libardour.dll
147 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
149 // on Unices additional internal-use binaries are deployed to $libdir
150 vstsp += ARDOUR::ardour_dll_directory();
153 if (!PBD::find_file (vstsp,
154 #ifdef PLATFORM_WINDOWS
155 #ifdef DEBUGGABLE_SCANNER_APP
156 #if defined(DEBUG) || defined(_DEBUG)
157 "ardour-vst-scannerD.exe"
159 "ardour-vst-scannerRDC.exe"
162 "ardour-vst-scanner.exe"
167 , scanner_bin_path)) {
168 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
174 if ((s = getenv ("LADSPA_RDF_PATH"))){
178 if (lrdf_path.length() == 0) {
179 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
182 add_lrdf_data(lrdf_path);
183 add_ladspa_presets();
184 #ifdef WINDOWS_VST_SUPPORT
185 if (Config->get_use_windows_vst ()) {
186 add_windows_vst_presets ();
188 #endif /* WINDOWS_VST_SUPPORT */
191 if (Config->get_use_lxvst()) {
194 #endif /* Native LinuxVST support*/
196 #ifdef MACVST_SUPPORT
197 if (Config->get_use_macvst ()) {
198 add_mac_vst_presets ();
202 if ((s = getenv ("VST_PATH"))) {
203 windows_vst_path = s;
204 } else if ((s = getenv ("VST_PLUGINS"))) {
205 windows_vst_path = s;
208 if (windows_vst_path.length() == 0) {
209 windows_vst_path = vst_search_path ();
212 if ((s = getenv ("LXVST_PATH"))) {
214 } else if ((s = getenv ("LXVST_PLUGINS"))) {
218 if (lxvst_path.length() == 0) {
219 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
220 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
221 "/usr/lib/vst:/usr/local/lib/vst";
224 /* first time setup, use 'default' path */
225 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
226 Config->set_plugin_path_lxvst(get_default_lxvst_path());
228 if (Config->get_plugin_path_vst() == X_("@default@")) {
229 Config->set_plugin_path_vst(get_default_windows_vst_path());
232 if (_instance == 0) {
236 BootMessage (_("Discovering Plugins"));
238 LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
242 PluginManager::~PluginManager()
244 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
245 // don't bother, just exit quickly.
246 delete _windows_vst_plugin_info;
247 delete _lxvst_plugin_info;
248 delete _mac_vst_plugin_info;
249 delete _ladspa_plugin_info;
250 delete _lv2_plugin_info;
251 delete _au_plugin_info;
252 delete _lua_plugin_info;
257 PluginManager::refresh (bool cache_only)
259 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
265 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
266 _cancel_scan = false;
268 BootMessage (_("Scanning LADSPA Plugins"));
270 BootMessage (_("Scanning Lua DSP Processors"));
273 BootMessage (_("Scanning LV2 Plugins"));
276 #ifdef WINDOWS_VST_SUPPORT
277 if (Config->get_use_windows_vst()) {
279 BootMessage (_("Scanning Windows VST Plugins"));
281 BootMessage (_("Discovering Windows VST Plugins"));
283 windows_vst_refresh (cache_only);
285 #endif // WINDOWS_VST_SUPPORT
288 if(Config->get_use_lxvst()) {
290 BootMessage (_("Scanning Linux VST Plugins"));
292 BootMessage (_("Discovering Linux VST Plugins"));
294 lxvst_refresh(cache_only);
296 #endif //Native linuxVST SUPPORT
298 #ifdef MACVST_SUPPORT
299 if(Config->get_use_macvst ()) {
301 BootMessage (_("Scanning Mac VST Plugins"));
303 BootMessage (_("Discovering Mac VST Plugins"));
305 mac_vst_refresh (cache_only);
306 } else if (_mac_vst_plugin_info) {
307 _mac_vst_plugin_info->clear ();
309 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
311 #endif //Native Mac VST SUPPORT
313 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
315 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
316 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
318 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
319 if (Config->get_verbose_plugin_scan()) {
320 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
322 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
330 #ifdef AUDIOUNIT_SUPPORT
332 BootMessage (_("Scanning AU Plugins"));
334 BootMessage (_("Discovering AU Plugins"));
336 au_refresh (cache_only);
339 BootMessage (_("Plugin Scan Complete..."));
340 PluginListChanged (); /* EMIT SIGNAL */
341 PluginScanMessage(X_("closeme"), "", false);
342 _cancel_scan = false;
346 PluginManager::cancel_plugin_scan ()
352 PluginManager::cancel_plugin_timeout ()
354 _cancel_timeout = true;
358 PluginManager::clear_vst_cache ()
360 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
361 #ifdef WINDOWS_VST_SUPPORT
363 vector<string> fsi_files;
364 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
365 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
366 ::g_unlink(i->c_str());
370 vector<string> fsi_files;
371 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
372 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
373 ::g_unlink(i->c_str());
377 vector<string> fsi_files;
378 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
379 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
380 ::g_unlink(i->c_str());
387 vector<string> fsi_files;
388 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
389 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
390 ::g_unlink(i->c_str());
394 vector<string> fsi_files;
395 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
396 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
397 ::g_unlink(i->c_str());
401 vector<string> fsi_files;
402 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
403 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
404 ::g_unlink(i->c_str());
408 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
410 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
411 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
412 PBD::remove_directory (dir);
416 #endif // old cache cleanup
418 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
420 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
421 vector<string> fsi_files;
422 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
423 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
424 ::g_unlink(i->c_str());
431 PluginManager::clear_vst_blacklist ()
433 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
435 #ifdef WINDOWS_VST_SUPPORT
437 vector<string> fsi_files;
438 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
439 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
440 ::g_unlink(i->c_str());
447 vector<string> fsi_files;
448 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
449 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
450 ::g_unlink(i->c_str());
454 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
456 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
457 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
458 PBD::remove_directory (dir);
463 #endif // old blacklist cleanup
465 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
467 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
468 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
469 ::g_unlink (fn.c_str());
477 PluginManager::clear_au_cache ()
479 #ifdef AUDIOUNIT_SUPPORT
480 AUPluginInfo::clear_cache ();
485 PluginManager::clear_au_blacklist ()
487 #ifdef AUDIOUNIT_SUPPORT
488 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
489 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
490 ::g_unlink(fn.c_str());
496 PluginManager::lua_refresh ()
498 if (_lua_plugin_info) {
499 _lua_plugin_info->clear ();
501 _lua_plugin_info = new ARDOUR::PluginInfoList ();
503 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
504 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
505 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
506 _lua_plugin_info->push_back (lpi);
511 PluginManager::lua_refresh_cb ()
513 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
518 PluginListChanged (); /* EMIT SIGNAL */
522 PluginManager::ladspa_refresh ()
524 if (_ladspa_plugin_info) {
525 _ladspa_plugin_info->clear ();
527 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
530 /* allow LADSPA_PATH to augment, not override standard locations */
532 /* Only add standard locations to ladspa_path if it doesn't
533 * already contain them. Check for trailing G_DIR_SEPARATOR too.
536 vector<string> ladspa_modules;
538 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
540 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
541 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
542 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
544 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
545 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
546 ladspa_discover (*i);
551 static bool rdf_filter (const string &str, void* /*arg*/)
553 return str[0] != '.' &&
554 ((str.find(".rdf") == (str.length() - 4)) ||
555 (str.find(".rdfs") == (str.length() - 5)) ||
556 (str.find(".n3") == (str.length() - 3)) ||
557 (str.find(".ttl") == (str.length() - 4)));
562 PluginManager::add_ladspa_presets()
564 add_presets ("ladspa");
568 PluginManager::add_windows_vst_presets()
570 add_presets ("windows-vst");
574 PluginManager::add_mac_vst_presets()
576 add_presets ("mac-vst");
580 PluginManager::add_lxvst_presets()
582 add_presets ("lxvst");
586 PluginManager::add_presets(string domain)
589 vector<string> presets;
590 vector<string>::iterator x;
593 if ((envvar = getenv ("HOME")) == 0) {
597 string path = string_compose("%1/.%2/rdf", envvar, domain);
598 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
600 for (x = presets.begin(); x != presets.end (); ++x) {
601 string file = "file:" + *x;
602 if (lrdf_read_file(file.c_str())) {
603 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
611 PluginManager::add_lrdf_data (const string &path)
614 vector<string> rdf_files;
615 vector<string>::iterator x;
617 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
619 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
620 const string uri(string("file://") + *x);
622 if (lrdf_read_file(uri.c_str())) {
623 warning << "Could not parse rdf file: " << uri << endmsg;
630 PluginManager::ladspa_discover (string path)
632 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
634 Glib::Module module(path);
635 const LADSPA_Descriptor *descriptor;
636 LADSPA_Descriptor_Function dfunc;
640 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
641 path, Glib::Module::get_last_error()) << endmsg;
646 if (!module.get_symbol("ladspa_descriptor", func)) {
647 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
648 error << Glib::Module::get_last_error() << endmsg;
652 dfunc = (LADSPA_Descriptor_Function)func;
654 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
656 for (uint32_t i = 0; ; ++i) {
657 /* if a ladspa plugin allocates memory here
658 * it is never free()ed (or plugin-dependent only when unloading).
659 * For some plugins memory allocated is incremental, we should
660 * avoid re-scanning plugins and file bug reports.
662 if ((descriptor = dfunc (i)) == 0) {
666 if (!ladspa_plugin_whitelist.empty()) {
667 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
672 PluginInfoPtr info(new LadspaPluginInfo);
673 info->name = descriptor->Name;
674 info->category = get_ladspa_category(descriptor->UniqueID);
675 info->creator = descriptor->Maker;
678 info->n_inputs = ChanCount();
679 info->n_outputs = ChanCount();
680 info->type = ARDOUR::LADSPA;
683 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
684 info->unique_id = buf;
686 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
687 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
688 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
689 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
691 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
692 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
697 if(_ladspa_plugin_info->empty()){
698 _ladspa_plugin_info->push_back (info);
701 //Ensure that the plugin is not already in the plugin list.
705 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
706 if(0 == info->unique_id.compare((*i)->unique_id)){
712 _ladspa_plugin_info->push_back (info);
715 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
718 // GDB WILL NOT LIKE YOU IF YOU DO THIS
725 PluginManager::get_ladspa_category (uint32_t plugin_id)
729 lrdf_statement pattern;
731 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
732 pattern.subject = buf;
733 pattern.predicate = const_cast<char*>(RDF_TYPE);
735 pattern.object_type = lrdf_uri;
737 lrdf_statement* matches1 = lrdf_matches (&pattern);
743 pattern.subject = matches1->object;
744 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
746 pattern.object_type = lrdf_literal;
748 lrdf_statement* matches2 = lrdf_matches (&pattern);
749 lrdf_free_statements(matches1);
755 string label = matches2->object;
756 lrdf_free_statements(matches2);
758 /* Kludge LADSPA class names to be singular and match LV2 class names.
759 This avoids duplicate plugin menus for every class, which is necessary
760 to make the plugin category menu at all usable, but is obviously a
763 In the short term, lrdf could be updated so the labels match and a new
764 release made. To support both specs, we should probably be mapping the
765 URIs to the same category in code and perhaps tweaking that hierarchy
766 dynamically to suit the user. Personally, I (drobilla) think that time
767 is better spent replacing the little-used LRDF.
769 In the longer term, we will abandon LRDF entirely in favour of LV2 and
770 use that class hierarchy. Aside from fixing this problem properly, that
771 will also allow for translated labels. SWH plugins have been LV2 for
772 ages; TAP needs porting. I don't know of anything else with LRDF data.
774 if (label == "Utilities") {
776 } else if (label == "Pitch shifters") {
777 return "Pitch Shifter";
778 } else if (label != "Dynamics" && label != "Chorus"
779 &&label[label.length() - 1] == 's'
780 && label[label.length() - 2] != 's') {
781 return label.substr(0, label.length() - 1);
792 PluginManager::lv2_refresh ()
794 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
795 delete _lv2_plugin_info;
796 _lv2_plugin_info = LV2PluginInfo::discover();
800 #ifdef AUDIOUNIT_SUPPORT
802 PluginManager::au_refresh (bool cache_only)
804 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
806 // disable automatic discovery in case we crash
807 bool discover_at_start = Config->get_discover_audio_units ();
808 Config->set_discover_audio_units (false);
809 Config->save_state();
811 delete _au_plugin_info;
812 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
814 // successful scan re-enabled automatic discovery if it was set
815 Config->set_discover_audio_units (discover_at_start);
816 Config->save_state();
821 #ifdef WINDOWS_VST_SUPPORT
824 PluginManager::windows_vst_refresh (bool cache_only)
826 if (_windows_vst_plugin_info) {
827 _windows_vst_plugin_info->clear ();
829 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
832 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
835 static bool windows_vst_filter (const string& str, void * /*arg*/)
837 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
838 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
842 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
844 vector<string> plugin_objects;
845 vector<string>::iterator x;
848 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
850 if (Session::get_disable_all_loaded_plugins ()) {
851 info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
855 if (Config->get_verbose_plugin_scan()) {
856 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
859 find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
861 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
862 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
863 windows_vst_discover (*x, cache_only || cancelled());
866 if (Config->get_verbose_plugin_scan()) {
867 info << _("--- Windows VST plugins Scan Done") << endmsg;
873 static std::string dll_info (std::string path) {
877 off_t pe_hdr_off = 0;
879 int fd = g_open(path.c_str(), O_RDONLY, 0444);
882 return _("cannot open dll"); // TODO strerror()
885 if (68 != read (fd, buf, 68)) {
886 rv = _("invalid dll, file too small");
889 if (buf[0] != 'M' && buf[1] != 'Z') {
894 pe_hdr_off = *((int32_t*) &buf[60]);
895 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
896 rv = _("cannot determine dll type");
899 if (6 != read (fd, buf, 6)) {
900 rv = _("cannot read dll PE header");
904 if (buf[0] != 'P' && buf[1] != 'E') {
905 rv = _("invalid dll PE header");
909 type = *((uint16_t*) &buf[4]);
912 rv = _("i386 (32-bit)");
918 rv = _("x64 (64-bit)");
921 rv = _("Native Architecture");
924 rv = _("Unknown Architecture");
928 assert (rv.length() > 0);
934 PluginManager::windows_vst_discover (string path, bool cache_only)
936 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
938 if (Config->get_verbose_plugin_scan()) {
940 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
942 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
946 _cancel_timeout = false;
947 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
948 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
950 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
951 // .err file scanner output etc.
953 if (finfos->empty()) {
954 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
955 if (Config->get_verbose_plugin_scan()) {
956 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
961 uint32_t discovered = 0;
962 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
966 if (!finfo->canProcessReplacing) {
967 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
968 finfo->name, PROGRAM_NAME)
973 PluginInfoPtr info (new WindowsVSTPluginInfo);
975 /* what a joke freeware VST is */
977 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
978 info->name = PBD::basename_nosuffix (path);
980 info->name = finfo->name;
984 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
985 info->unique_id = buf;
986 info->category = "VST";
988 info->creator = finfo->creator;
990 info->n_inputs.set_audio (finfo->numInputs);
991 info->n_outputs.set_audio (finfo->numOutputs);
992 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
993 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
994 info->type = ARDOUR::Windows_VST;
996 // TODO: check dup-IDs (lxvst AND windows vst)
997 bool duplicate = false;
999 if (!_windows_vst_plugin_info->empty()) {
1000 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
1001 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
1002 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1010 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1011 _windows_vst_plugin_info->push_back (info);
1013 if (Config->get_verbose_plugin_scan()) {
1014 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1019 vstfx_free_info_list (finfos);
1020 return discovered > 0 ? 0 : -1;
1023 #endif // WINDOWS_VST_SUPPORT
1025 #ifdef MACVST_SUPPORT
1027 PluginManager::mac_vst_refresh (bool cache_only)
1029 if (_mac_vst_plugin_info) {
1030 _mac_vst_plugin_info->clear ();
1032 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1035 mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1038 static bool mac_vst_filter (const string& str)
1040 string plist = Glib::build_filename (str, "Contents", "Info.plist");
1041 if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1044 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1048 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1050 if (Session::get_disable_all_loaded_plugins ()) {
1051 info << _("Disabled MacVST scan (safe mode)") << endmsg;
1055 Searchpath paths (path);
1056 /* customized version of run_functor_for_paths() */
1057 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1058 string expanded_path = path_expand (*i);
1059 if (!Glib::file_test (expanded_path, Glib::FILE_TEST_IS_DIR)) continue;
1061 Glib::Dir dir(expanded_path);
1062 for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
1063 string fullpath = Glib::build_filename (expanded_path, *di);
1065 /* we're only interested in bundles */
1066 if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
1070 if (mac_vst_filter (fullpath)) {
1071 ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled());
1072 mac_vst_discover (fullpath, cache_only || cancelled());
1076 /* don't descend into AU bundles in the VST dir */
1077 if (fullpath[0] == '.' || (fullpath.length() > 10 && strings_equal_ignore_case (".component", fullpath.substr(fullpath.length() - 10)))) {
1082 mac_vst_discover_from_path (fullpath, cache_only);
1084 } catch (Glib::FileError& err) { }
1091 PluginManager::mac_vst_discover (string path, bool cache_only)
1093 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1095 _cancel_timeout = false;
1097 vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1098 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1100 if (finfos->empty()) {
1101 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1105 uint32_t discovered = 0;
1106 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1107 VSTInfo* finfo = *x;
1110 if (!finfo->canProcessReplacing) {
1111 warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1112 finfo->name, PROGRAM_NAME)
1117 PluginInfoPtr info (new MacVSTPluginInfo);
1119 info->name = finfo->name;
1121 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1122 info->unique_id = buf;
1123 info->category = "MacVST";
1125 info->creator = finfo->creator;
1127 info->n_inputs.set_audio (finfo->numInputs);
1128 info->n_outputs.set_audio (finfo->numOutputs);
1129 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1130 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1131 info->type = ARDOUR::MacVST;
1133 bool duplicate = false;
1134 if (!_mac_vst_plugin_info->empty()) {
1135 for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1136 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1137 warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1145 _mac_vst_plugin_info->push_back (info);
1150 vstfx_free_info_list (finfos);
1151 return discovered > 0 ? 0 : -1;
1154 #endif // MAC_VST_SUPPORT
1156 #ifdef LXVST_SUPPORT
1159 PluginManager::lxvst_refresh (bool cache_only)
1161 if (_lxvst_plugin_info) {
1162 _lxvst_plugin_info->clear ();
1164 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1167 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1170 static bool lxvst_filter (const string& str, void *)
1172 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1174 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1178 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1180 vector<string> plugin_objects;
1181 vector<string>::iterator x;
1184 if (Session::get_disable_all_loaded_plugins ()) {
1185 info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
1193 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1195 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1197 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1198 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1199 lxvst_discover (*x, cache_only || cancelled());
1206 PluginManager::lxvst_discover (string path, bool cache_only)
1208 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1210 _cancel_timeout = false;
1211 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1212 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1214 if (finfos->empty()) {
1215 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1219 uint32_t discovered = 0;
1220 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1221 VSTInfo* finfo = *x;
1224 if (!finfo->canProcessReplacing) {
1225 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1226 finfo->name, PROGRAM_NAME)
1231 PluginInfoPtr info(new LXVSTPluginInfo);
1233 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1234 info->name = PBD::basename_nosuffix (path);
1236 info->name = finfo->name;
1240 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1241 info->unique_id = buf;
1242 info->category = "linuxVSTs";
1244 info->creator = finfo->creator;
1246 info->n_inputs.set_audio (finfo->numInputs);
1247 info->n_outputs.set_audio (finfo->numOutputs);
1248 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1249 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1250 info->type = ARDOUR::LXVST;
1252 /* Make sure we don't find the same plugin in more than one place along
1253 the LXVST_PATH We can't use a simple 'find' because the path is included
1254 in the PluginInfo, and that is the one thing we can be sure MUST be
1255 different if a duplicate instance is found. So we just compare the type
1256 and unique ID (which for some VSTs isn't actually unique...)
1259 // TODO: check dup-IDs with windowsVST, too
1260 bool duplicate = false;
1261 if (!_lxvst_plugin_info->empty()) {
1262 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1263 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1264 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1272 _lxvst_plugin_info->push_back (info);
1277 vstfx_free_info_list (finfos);
1278 return discovered > 0 ? 0 : -1;
1281 #endif // LXVST_SUPPORT
1284 PluginManager::PluginStatusType
1285 PluginManager::get_status (const PluginInfoPtr& pi) const
1287 PluginStatus ps (pi->type, pi->unique_id);
1288 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1289 if (i == statuses.end() ) {
1297 PluginManager::save_statuses ()
1299 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1302 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1303 switch ((*i).type) {
1314 ofs << "Windows-VST";
1329 switch ((*i).status) {
1342 ofs << (*i).unique_id;;
1345 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1346 PluginStatusesChanged (); /* EMIT SIGNAL */
1350 PluginManager::load_statuses ()
1352 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1354 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1357 stringstream ifs (fbuf);
1361 std::string sstatus;
1364 PluginStatusType status;
1381 /* rest of the line is the plugin ID */
1383 ifs.getline (buf, sizeof (buf), '\n');
1388 if (sstatus == "Normal") {
1390 } else if (sstatus == "Favorite") {
1392 } else if (sstatus == "Hidden") {
1395 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1401 if (stype == "LADSPA") {
1403 } else if (stype == "AudioUnit") {
1405 } else if (stype == "LV2") {
1407 } else if (stype == "Windows-VST") {
1409 } else if (stype == "LXVST") {
1411 } else if (stype == "MacVST") {
1413 } else if (stype == "Lua") {
1416 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1422 strip_whitespace_edges (id);
1423 set_status (type, id, status);
1428 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1430 PluginStatus ps (t, id, status);
1431 statuses.erase (ps);
1433 if (status == Normal) {
1437 statuses.insert (ps);
1440 const ARDOUR::PluginInfoList&
1441 PluginManager::windows_vst_plugin_info ()
1443 #ifdef WINDOWS_VST_SUPPORT
1444 if (!_windows_vst_plugin_info) {
1445 windows_vst_refresh ();
1447 return *_windows_vst_plugin_info;
1449 return _empty_plugin_info;
1453 const ARDOUR::PluginInfoList&
1454 PluginManager::mac_vst_plugin_info ()
1456 #ifdef MACVST_SUPPORT
1457 assert(_mac_vst_plugin_info);
1458 return *_mac_vst_plugin_info;
1460 return _empty_plugin_info;
1464 const ARDOUR::PluginInfoList&
1465 PluginManager::lxvst_plugin_info ()
1467 #ifdef LXVST_SUPPORT
1468 assert(_lxvst_plugin_info);
1469 return *_lxvst_plugin_info;
1471 return _empty_plugin_info;
1475 const ARDOUR::PluginInfoList&
1476 PluginManager::ladspa_plugin_info ()
1478 assert(_ladspa_plugin_info);
1479 return *_ladspa_plugin_info;
1482 const ARDOUR::PluginInfoList&
1483 PluginManager::lv2_plugin_info ()
1486 assert(_lv2_plugin_info);
1487 return *_lv2_plugin_info;
1489 return _empty_plugin_info;
1493 const ARDOUR::PluginInfoList&
1494 PluginManager::au_plugin_info ()
1496 #ifdef AUDIOUNIT_SUPPORT
1497 if (_au_plugin_info) {
1498 return *_au_plugin_info;
1501 return _empty_plugin_info;
1504 const ARDOUR::PluginInfoList&
1505 PluginManager::lua_plugin_info ()
1507 assert(_lua_plugin_info);
1508 return *_lua_plugin_info;