2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
26 #include <sys/types.h>
31 #include "pbd/gstdio_compat.h"
37 #ifdef WINDOWS_VST_SUPPORT
38 #include "ardour/vst_info_file.h"
40 #include "pbd/basename.h"
49 #endif // WINDOWS_VST_SUPPORT
52 #include "ardour/vst_info_file.h"
53 #include "ardour/linux_vst_support.h"
54 #include "pbd/basename.h"
56 #endif //LXVST_SUPPORT
58 #include <glibmm/miscutils.h>
59 #include <glibmm/pattern.h>
60 #include <glibmm/fileutils.h>
61 #include <glibmm/miscutils.h>
63 #include "pbd/whitespace.h"
64 #include "pbd/file_utils.h"
66 #include "ardour/debug.h"
67 #include "ardour/filesystem_paths.h"
68 #include "ardour/ladspa.h"
69 #include "ardour/ladspa_plugin.h"
70 #include "ardour/luascripting.h"
71 #include "ardour/luaproc.h"
72 #include "ardour/plugin.h"
73 #include "ardour/plugin_manager.h"
74 #include "ardour/rc_configuration.h"
76 #include "ardour/search_paths.h"
79 #include "ardour/lv2_plugin.h"
82 #ifdef WINDOWS_VST_SUPPORT
83 #include "ardour/windows_vst_plugin.h"
87 #include "ardour/lxvst_plugin.h"
90 #ifdef AUDIOUNIT_SUPPORT
91 #include "ardour/audio_unit.h"
92 #include <Carbon/Carbon.h>
95 #include "pbd/error.h"
96 #include "pbd/stl_delete.h"
100 #include "ardour/debug.h"
102 using namespace ARDOUR;
106 PluginManager* PluginManager::_instance = 0;
107 std::string PluginManager::scanner_bin_path = "";
110 PluginManager::instance()
113 _instance = new PluginManager;
118 PluginManager::PluginManager ()
119 : _windows_vst_plugin_info(0)
120 , _lxvst_plugin_info(0)
121 , _ladspa_plugin_info(0)
122 , _lv2_plugin_info(0)
124 , _lua_plugin_info(0)
125 , _cancel_scan(false)
126 , _cancel_timeout(false)
131 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
132 // source-tree (ardev, etc)
133 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
135 #ifdef PLATFORM_WINDOWS
136 // on windows the .exe needs to be in the same folder with libardour.dll
137 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
139 // on Unices additional internal-use binaries are deployed to $libdir
140 vstsp += ARDOUR::ardour_dll_directory();
143 if (!PBD::find_file (vstsp,
144 #ifdef PLATFORM_WINDOWS
145 #ifdef DEBUGGABLE_SCANNER_APP
146 #if defined(DEBUG) || defined(_DEBUG)
147 "ardour-vst-scannerD.exe"
149 "ardour-vst-scannerRDC.exe"
152 "ardour-vst-scanner.exe"
157 , scanner_bin_path)) {
158 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
164 if ((s = getenv ("LADSPA_RDF_PATH"))){
168 if (lrdf_path.length() == 0) {
169 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
172 add_lrdf_data(lrdf_path);
173 add_ladspa_presets();
174 #ifdef WINDOWS_VST_SUPPORT
175 if (Config->get_use_windows_vst ()) {
176 add_windows_vst_presets ();
178 #endif /* WINDOWS_VST_SUPPORT */
181 if (Config->get_use_lxvst()) {
184 #endif /* Native LinuxVST support*/
186 if ((s = getenv ("VST_PATH"))) {
187 windows_vst_path = s;
188 } else if ((s = getenv ("VST_PLUGINS"))) {
189 windows_vst_path = s;
192 if (windows_vst_path.length() == 0) {
193 windows_vst_path = vst_search_path ();
196 if ((s = getenv ("LXVST_PATH"))) {
198 } else if ((s = getenv ("LXVST_PLUGINS"))) {
202 if (lxvst_path.length() == 0) {
203 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
204 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
205 "/usr/lib/vst:/usr/local/lib/vst";
208 /* first time setup, use 'default' path */
209 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
210 Config->set_plugin_path_lxvst(get_default_lxvst_path());
212 if (Config->get_plugin_path_vst() == X_("@default@")) {
213 Config->set_plugin_path_vst(get_default_windows_vst_path());
216 if (_instance == 0) {
220 BootMessage (_("Discovering Plugins"));
222 LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
226 PluginManager::~PluginManager()
228 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
229 // don't bother, just exit quickly.
230 delete _windows_vst_plugin_info;
231 delete _lxvst_plugin_info;
232 delete _ladspa_plugin_info;
233 delete _lv2_plugin_info;
234 delete _au_plugin_info;
235 delete _lua_plugin_info;
240 PluginManager::refresh (bool cache_only)
242 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
248 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
249 _cancel_scan = false;
251 BootMessage (_("Scanning LADSPA Plugins"));
253 BootMessage (_("Scanning Lua DSP Processors"));
256 BootMessage (_("Scanning LV2 Plugins"));
259 #ifdef WINDOWS_VST_SUPPORT
260 if (Config->get_use_windows_vst()) {
262 BootMessage (_("Scanning Windows VST Plugins"));
264 BootMessage (_("Discovering Windows VST Plugins"));
266 windows_vst_refresh (cache_only);
268 #endif // WINDOWS_VST_SUPPORT
271 if(Config->get_use_lxvst()) {
273 BootMessage (_("Scanning Linux VST Plugins"));
275 BootMessage (_("Discovering Linux VST Plugins"));
277 lxvst_refresh(cache_only);
279 #endif //Native linuxVST SUPPORT
281 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
283 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
284 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
286 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
287 if (Config->get_verbose_plugin_scan()) {
288 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
290 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
298 #ifdef AUDIOUNIT_SUPPORT
300 BootMessage (_("Scanning AU Plugins"));
302 BootMessage (_("Discovering AU Plugins"));
304 au_refresh (cache_only);
307 BootMessage (_("Plugin Scan Complete..."));
308 PluginListChanged (); /* EMIT SIGNAL */
309 PluginScanMessage(X_("closeme"), "", false);
310 _cancel_scan = false;
314 PluginManager::cancel_plugin_scan ()
320 PluginManager::cancel_plugin_timeout ()
322 _cancel_timeout = true;
326 PluginManager::clear_vst_cache ()
328 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
329 #ifdef WINDOWS_VST_SUPPORT
331 vector<string> fsi_files;
332 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
333 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
334 ::g_unlink(i->c_str());
338 vector<string> fsi_files;
339 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
340 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
341 ::g_unlink(i->c_str());
345 vector<string> fsi_files;
346 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
347 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
348 ::g_unlink(i->c_str());
355 vector<string> fsi_files;
356 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
357 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
358 ::g_unlink(i->c_str());
362 vector<string> fsi_files;
363 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", 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_lxvst(), "\\.err$", true);
371 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
372 ::g_unlink(i->c_str());
376 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
378 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
379 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
380 PBD::remove_directory (dir);
384 #endif // old cache cleanup
386 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
388 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
389 vector<string> fsi_files;
390 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
391 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
392 ::g_unlink(i->c_str());
399 PluginManager::clear_vst_blacklist ()
401 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
403 #ifdef WINDOWS_VST_SUPPORT
405 vector<string> fsi_files;
406 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
407 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
408 ::g_unlink(i->c_str());
415 vector<string> fsi_files;
416 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
417 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
418 ::g_unlink(i->c_str());
422 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
424 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
425 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
426 PBD::remove_directory (dir);
431 #endif // old blacklist cleanup
433 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
435 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
436 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
437 ::g_unlink (fn.c_str());
445 PluginManager::clear_au_cache ()
447 #ifdef AUDIOUNIT_SUPPORT
448 AUPluginInfo::clear_cache ();
453 PluginManager::clear_au_blacklist ()
455 #ifdef AUDIOUNIT_SUPPORT
456 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
457 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
458 ::g_unlink(fn.c_str());
464 PluginManager::lua_refresh ()
466 if (_lua_plugin_info) {
467 _lua_plugin_info->clear ();
469 _lua_plugin_info = new ARDOUR::PluginInfoList ();
471 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
472 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
473 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
474 _lua_plugin_info->push_back (lpi);
479 PluginManager::lua_refresh_cb ()
481 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
486 PluginListChanged (); /* EMIT SIGNAL */
490 PluginManager::ladspa_refresh ()
492 if (_ladspa_plugin_info) {
493 _ladspa_plugin_info->clear ();
495 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
498 /* allow LADSPA_PATH to augment, not override standard locations */
500 /* Only add standard locations to ladspa_path if it doesn't
501 * already contain them. Check for trailing G_DIR_SEPARATOR too.
504 vector<string> ladspa_modules;
506 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
508 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
509 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
510 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
512 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
513 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
514 ladspa_discover (*i);
519 static bool rdf_filter (const string &str, void* /*arg*/)
521 return str[0] != '.' &&
522 ((str.find(".rdf") == (str.length() - 4)) ||
523 (str.find(".rdfs") == (str.length() - 5)) ||
524 (str.find(".n3") == (str.length() - 3)) ||
525 (str.find(".ttl") == (str.length() - 4)));
530 PluginManager::add_ladspa_presets()
532 add_presets ("ladspa");
536 PluginManager::add_windows_vst_presets()
538 add_presets ("windows-vst");
542 PluginManager::add_lxvst_presets()
544 add_presets ("lxvst");
548 PluginManager::add_presets(string domain)
551 vector<string> presets;
552 vector<string>::iterator x;
555 if ((envvar = getenv ("HOME")) == 0) {
559 string path = string_compose("%1/.%2/rdf", envvar, domain);
560 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
562 for (x = presets.begin(); x != presets.end (); ++x) {
563 string file = "file:" + *x;
564 if (lrdf_read_file(file.c_str())) {
565 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
573 PluginManager::add_lrdf_data (const string &path)
576 vector<string> rdf_files;
577 vector<string>::iterator x;
579 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
581 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
582 const string uri(string("file://") + *x);
584 if (lrdf_read_file(uri.c_str())) {
585 warning << "Could not parse rdf file: " << uri << endmsg;
592 PluginManager::ladspa_discover (string path)
594 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
596 Glib::Module module(path);
597 const LADSPA_Descriptor *descriptor;
598 LADSPA_Descriptor_Function dfunc;
602 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
603 path, Glib::Module::get_last_error()) << endmsg;
608 if (!module.get_symbol("ladspa_descriptor", func)) {
609 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
610 error << Glib::Module::get_last_error() << endmsg;
614 dfunc = (LADSPA_Descriptor_Function)func;
616 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
618 for (uint32_t i = 0; ; ++i) {
619 /* if a ladspa plugin allocates memory here
620 * it is never free()ed (or plugin-dependent only when unloading).
621 * For some plugins memory allocated is incremental, we should
622 * avoid re-scanning plugins and file bug reports.
624 if ((descriptor = dfunc (i)) == 0) {
628 if (!ladspa_plugin_whitelist.empty()) {
629 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
634 PluginInfoPtr info(new LadspaPluginInfo);
635 info->name = descriptor->Name;
636 info->category = get_ladspa_category(descriptor->UniqueID);
637 info->creator = descriptor->Maker;
640 info->n_inputs = ChanCount();
641 info->n_outputs = ChanCount();
642 info->type = ARDOUR::LADSPA;
645 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
646 info->unique_id = buf;
648 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
649 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
650 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
651 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
653 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
654 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
659 if(_ladspa_plugin_info->empty()){
660 _ladspa_plugin_info->push_back (info);
663 //Ensure that the plugin is not already in the plugin list.
667 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
668 if(0 == info->unique_id.compare((*i)->unique_id)){
674 _ladspa_plugin_info->push_back (info);
677 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
680 // GDB WILL NOT LIKE YOU IF YOU DO THIS
687 PluginManager::get_ladspa_category (uint32_t plugin_id)
691 lrdf_statement pattern;
693 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
694 pattern.subject = buf;
695 pattern.predicate = const_cast<char*>(RDF_TYPE);
697 pattern.object_type = lrdf_uri;
699 lrdf_statement* matches1 = lrdf_matches (&pattern);
705 pattern.subject = matches1->object;
706 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
708 pattern.object_type = lrdf_literal;
710 lrdf_statement* matches2 = lrdf_matches (&pattern);
711 lrdf_free_statements(matches1);
717 string label = matches2->object;
718 lrdf_free_statements(matches2);
720 /* Kludge LADSPA class names to be singular and match LV2 class names.
721 This avoids duplicate plugin menus for every class, which is necessary
722 to make the plugin category menu at all usable, but is obviously a
725 In the short term, lrdf could be updated so the labels match and a new
726 release made. To support both specs, we should probably be mapping the
727 URIs to the same category in code and perhaps tweaking that hierarchy
728 dynamically to suit the user. Personally, I (drobilla) think that time
729 is better spent replacing the little-used LRDF.
731 In the longer term, we will abandon LRDF entirely in favour of LV2 and
732 use that class hierarchy. Aside from fixing this problem properly, that
733 will also allow for translated labels. SWH plugins have been LV2 for
734 ages; TAP needs porting. I don't know of anything else with LRDF data.
736 if (label == "Utilities") {
738 } else if (label == "Pitch shifters") {
739 return "Pitch Shifter";
740 } else if (label != "Dynamics" && label != "Chorus"
741 &&label[label.length() - 1] == 's'
742 && label[label.length() - 2] != 's') {
743 return label.substr(0, label.length() - 1);
754 PluginManager::lv2_refresh ()
756 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
757 delete _lv2_plugin_info;
758 _lv2_plugin_info = LV2PluginInfo::discover();
762 #ifdef AUDIOUNIT_SUPPORT
764 PluginManager::au_refresh (bool cache_only)
766 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
768 // disable automatic discovery in case we crash
769 bool discover_at_start = Config->get_discover_audio_units ();
770 Config->set_discover_audio_units (false);
771 Config->save_state();
773 delete _au_plugin_info;
774 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
776 // successful scan re-enabled automatic discovery if it was set
777 Config->set_discover_audio_units (discover_at_start);
778 Config->save_state();
783 #ifdef WINDOWS_VST_SUPPORT
786 PluginManager::windows_vst_refresh (bool cache_only)
788 if (_windows_vst_plugin_info) {
789 _windows_vst_plugin_info->clear ();
791 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
794 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
797 static bool windows_vst_filter (const string& str, void * /*arg*/)
799 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
800 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
804 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
806 vector<string> plugin_objects;
807 vector<string>::iterator x;
810 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
812 if (Config->get_verbose_plugin_scan()) {
813 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
816 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
818 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
819 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
820 windows_vst_discover (*x, cache_only || cancelled());
823 if (Config->get_verbose_plugin_scan()) {
824 info << _("--- Windows VST plugins Scan Done") << endmsg;
830 static std::string dll_info (std::string path) {
834 off_t pe_hdr_off = 0;
836 int fd = g_open(path.c_str(), O_RDONLY, 0444);
839 return _("cannot open dll"); // TODO strerror()
842 if (68 != read (fd, buf, 68)) {
843 rv = _("invalid dll, file too small");
846 if (buf[0] != 'M' && buf[1] != 'Z') {
851 pe_hdr_off = *((int32_t*) &buf[60]);
852 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
853 rv = _("cannot determine dll type");
856 if (6 != read (fd, buf, 6)) {
857 rv = _("cannot read dll PE header");
861 if (buf[0] != 'P' && buf[1] != 'E') {
862 rv = _("invalid dll PE header");
866 type = *((uint16_t*) &buf[4]);
869 rv = _("i386 (32-bit)");
875 rv = _("x64 (64-bit)");
878 rv = _("Native Architecture");
881 rv = _("Unknown Architecture");
885 assert (rv.length() > 0);
891 PluginManager::windows_vst_discover (string path, bool cache_only)
893 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
895 if (Config->get_verbose_plugin_scan()) {
897 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
899 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
903 _cancel_timeout = false;
904 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
905 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
907 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
908 // .err file scanner output etc.
910 if (finfos->empty()) {
911 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
912 if (Config->get_verbose_plugin_scan()) {
913 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
918 uint32_t discovered = 0;
919 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
923 if (!finfo->canProcessReplacing) {
924 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
925 finfo->name, PROGRAM_NAME)
930 PluginInfoPtr info (new WindowsVSTPluginInfo);
932 /* what a joke freeware VST is */
934 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
935 info->name = PBD::basename_nosuffix (path);
937 info->name = finfo->name;
941 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
942 info->unique_id = buf;
943 info->category = "VST";
945 info->creator = finfo->creator;
947 info->n_inputs.set_audio (finfo->numInputs);
948 info->n_outputs.set_audio (finfo->numOutputs);
949 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
950 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
951 info->type = ARDOUR::Windows_VST;
953 // TODO: check dup-IDs (lxvst AND windows vst)
954 bool duplicate = false;
956 if (!_windows_vst_plugin_info->empty()) {
957 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
958 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
959 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
967 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
968 _windows_vst_plugin_info->push_back (info);
970 if (Config->get_verbose_plugin_scan()) {
971 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
976 vstfx_free_info_list (finfos);
977 return discovered > 0 ? 0 : -1;
980 #endif // WINDOWS_VST_SUPPORT
985 PluginManager::lxvst_refresh (bool cache_only)
987 if (_lxvst_plugin_info) {
988 _lxvst_plugin_info->clear ();
990 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
993 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
996 static bool lxvst_filter (const string& str, void *)
998 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1000 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1004 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1006 vector<string> plugin_objects;
1007 vector<string>::iterator x;
1014 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1016 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1018 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1019 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1020 lxvst_discover (*x, cache_only || cancelled());
1027 PluginManager::lxvst_discover (string path, bool cache_only)
1029 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1031 _cancel_timeout = false;
1032 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1033 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1035 if (finfos->empty()) {
1036 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1040 uint32_t discovered = 0;
1041 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1042 VSTInfo* finfo = *x;
1045 if (!finfo->canProcessReplacing) {
1046 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1047 finfo->name, PROGRAM_NAME)
1052 PluginInfoPtr info(new LXVSTPluginInfo);
1054 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1055 info->name = PBD::basename_nosuffix (path);
1057 info->name = finfo->name;
1061 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1062 info->unique_id = buf;
1063 info->category = "linuxVSTs";
1065 info->creator = finfo->creator;
1067 info->n_inputs.set_audio (finfo->numInputs);
1068 info->n_outputs.set_audio (finfo->numOutputs);
1069 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1070 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1071 info->type = ARDOUR::LXVST;
1073 /* Make sure we don't find the same plugin in more than one place along
1074 the LXVST_PATH We can't use a simple 'find' because the path is included
1075 in the PluginInfo, and that is the one thing we can be sure MUST be
1076 different if a duplicate instance is found. So we just compare the type
1077 and unique ID (which for some VSTs isn't actually unique...)
1080 // TODO: check dup-IDs with windowsVST, too
1081 bool duplicate = false;
1082 if (!_lxvst_plugin_info->empty()) {
1083 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1084 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1085 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1093 _lxvst_plugin_info->push_back (info);
1098 vstfx_free_info_list (finfos);
1099 return discovered > 0 ? 0 : -1;
1102 #endif // LXVST_SUPPORT
1105 PluginManager::PluginStatusType
1106 PluginManager::get_status (const PluginInfoPtr& pi)
1108 PluginStatus ps (pi->type, pi->unique_id);
1109 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1110 if (i == statuses.end() ) {
1118 PluginManager::save_statuses ()
1120 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1123 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1124 switch ((*i).type) {
1135 ofs << "Windows-VST";
1147 switch ((*i).status) {
1160 ofs << (*i).unique_id;;
1163 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1164 PluginStatusesChanged (); /* EMIT SIGNAL */
1168 PluginManager::load_statuses ()
1170 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1172 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1175 stringstream ifs (fbuf);
1179 std::string sstatus;
1182 PluginStatusType status;
1199 /* rest of the line is the plugin ID */
1201 ifs.getline (buf, sizeof (buf), '\n');
1206 if (sstatus == "Normal") {
1208 } else if (sstatus == "Favorite") {
1210 } else if (sstatus == "Hidden") {
1213 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1219 if (stype == "LADSPA") {
1221 } else if (stype == "AudioUnit") {
1223 } else if (stype == "LV2") {
1225 } else if (stype == "Windows-VST") {
1227 } else if (stype == "LXVST") {
1229 } else if (stype == "Lua") {
1232 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1238 strip_whitespace_edges (id);
1239 set_status (type, id, status);
1244 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1246 PluginStatus ps (t, id, status);
1247 statuses.erase (ps);
1249 if (status == Normal) {
1253 statuses.insert (ps);
1256 ARDOUR::PluginInfoList&
1257 PluginManager::windows_vst_plugin_info ()
1259 #ifdef WINDOWS_VST_SUPPORT
1260 if (!_windows_vst_plugin_info) {
1261 windows_vst_refresh ();
1263 return *_windows_vst_plugin_info;
1265 return _empty_plugin_info;
1269 ARDOUR::PluginInfoList&
1270 PluginManager::lxvst_plugin_info ()
1272 #ifdef LXVST_SUPPORT
1273 assert(_lxvst_plugin_info);
1274 return *_lxvst_plugin_info;
1276 return _empty_plugin_info;
1280 ARDOUR::PluginInfoList&
1281 PluginManager::ladspa_plugin_info ()
1283 assert(_ladspa_plugin_info);
1284 return *_ladspa_plugin_info;
1287 ARDOUR::PluginInfoList&
1288 PluginManager::lv2_plugin_info ()
1291 assert(_lv2_plugin_info);
1292 return *_lv2_plugin_info;
1294 return _empty_plugin_info;
1298 ARDOUR::PluginInfoList&
1299 PluginManager::au_plugin_info ()
1301 #ifdef AUDIOUNIT_SUPPORT
1302 if (_au_plugin_info) {
1303 return *_au_plugin_info;
1306 return _empty_plugin_info;
1309 ARDOUR::PluginInfoList&
1310 PluginManager::lua_plugin_info ()
1312 assert(_lua_plugin_info);
1313 return *_lua_plugin_info;