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);
306 #endif //Native Mac VST SUPPORT
308 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
310 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
311 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
313 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
314 if (Config->get_verbose_plugin_scan()) {
315 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
317 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
325 #ifdef AUDIOUNIT_SUPPORT
327 BootMessage (_("Scanning AU Plugins"));
329 BootMessage (_("Discovering AU Plugins"));
331 au_refresh (cache_only);
334 BootMessage (_("Plugin Scan Complete..."));
335 PluginListChanged (); /* EMIT SIGNAL */
336 PluginScanMessage(X_("closeme"), "", false);
337 _cancel_scan = false;
341 PluginManager::cancel_plugin_scan ()
347 PluginManager::cancel_plugin_timeout ()
349 _cancel_timeout = true;
353 PluginManager::clear_vst_cache ()
355 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
356 #ifdef WINDOWS_VST_SUPPORT
358 vector<string> fsi_files;
359 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
360 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
361 ::g_unlink(i->c_str());
365 vector<string> fsi_files;
366 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
367 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
368 ::g_unlink(i->c_str());
372 vector<string> fsi_files;
373 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
374 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
375 ::g_unlink(i->c_str());
382 vector<string> fsi_files;
383 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
384 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
385 ::g_unlink(i->c_str());
389 vector<string> fsi_files;
390 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
391 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
392 ::g_unlink(i->c_str());
396 vector<string> fsi_files;
397 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
398 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
399 ::g_unlink(i->c_str());
403 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
405 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
406 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
407 PBD::remove_directory (dir);
411 #endif // old cache cleanup
413 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
415 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
416 vector<string> fsi_files;
417 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
418 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
419 ::g_unlink(i->c_str());
426 PluginManager::clear_vst_blacklist ()
428 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
430 #ifdef WINDOWS_VST_SUPPORT
432 vector<string> fsi_files;
433 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
434 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
435 ::g_unlink(i->c_str());
442 vector<string> fsi_files;
443 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
444 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
445 ::g_unlink(i->c_str());
449 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
451 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
452 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
453 PBD::remove_directory (dir);
458 #endif // old blacklist cleanup
460 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
462 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
463 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
464 ::g_unlink (fn.c_str());
472 PluginManager::clear_au_cache ()
474 #ifdef AUDIOUNIT_SUPPORT
475 AUPluginInfo::clear_cache ();
480 PluginManager::clear_au_blacklist ()
482 #ifdef AUDIOUNIT_SUPPORT
483 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
484 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
485 ::g_unlink(fn.c_str());
491 PluginManager::lua_refresh ()
493 if (_lua_plugin_info) {
494 _lua_plugin_info->clear ();
496 _lua_plugin_info = new ARDOUR::PluginInfoList ();
498 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
499 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
500 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
501 _lua_plugin_info->push_back (lpi);
506 PluginManager::lua_refresh_cb ()
508 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
513 PluginListChanged (); /* EMIT SIGNAL */
517 PluginManager::ladspa_refresh ()
519 if (_ladspa_plugin_info) {
520 _ladspa_plugin_info->clear ();
522 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
525 /* allow LADSPA_PATH to augment, not override standard locations */
527 /* Only add standard locations to ladspa_path if it doesn't
528 * already contain them. Check for trailing G_DIR_SEPARATOR too.
531 vector<string> ladspa_modules;
533 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
535 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
536 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
537 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
539 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
540 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
541 ladspa_discover (*i);
546 static bool rdf_filter (const string &str, void* /*arg*/)
548 return str[0] != '.' &&
549 ((str.find(".rdf") == (str.length() - 4)) ||
550 (str.find(".rdfs") == (str.length() - 5)) ||
551 (str.find(".n3") == (str.length() - 3)) ||
552 (str.find(".ttl") == (str.length() - 4)));
557 PluginManager::add_ladspa_presets()
559 add_presets ("ladspa");
563 PluginManager::add_windows_vst_presets()
565 add_presets ("windows-vst");
569 PluginManager::add_mac_vst_presets()
571 add_presets ("mac-vst");
575 PluginManager::add_lxvst_presets()
577 add_presets ("lxvst");
581 PluginManager::add_presets(string domain)
584 vector<string> presets;
585 vector<string>::iterator x;
588 if ((envvar = getenv ("HOME")) == 0) {
592 string path = string_compose("%1/.%2/rdf", envvar, domain);
593 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
595 for (x = presets.begin(); x != presets.end (); ++x) {
596 string file = "file:" + *x;
597 if (lrdf_read_file(file.c_str())) {
598 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
606 PluginManager::add_lrdf_data (const string &path)
609 vector<string> rdf_files;
610 vector<string>::iterator x;
612 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
614 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
615 const string uri(string("file://") + *x);
617 if (lrdf_read_file(uri.c_str())) {
618 warning << "Could not parse rdf file: " << uri << endmsg;
625 PluginManager::ladspa_discover (string path)
627 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
629 Glib::Module module(path);
630 const LADSPA_Descriptor *descriptor;
631 LADSPA_Descriptor_Function dfunc;
635 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
636 path, Glib::Module::get_last_error()) << endmsg;
641 if (!module.get_symbol("ladspa_descriptor", func)) {
642 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
643 error << Glib::Module::get_last_error() << endmsg;
647 dfunc = (LADSPA_Descriptor_Function)func;
649 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
651 for (uint32_t i = 0; ; ++i) {
652 /* if a ladspa plugin allocates memory here
653 * it is never free()ed (or plugin-dependent only when unloading).
654 * For some plugins memory allocated is incremental, we should
655 * avoid re-scanning plugins and file bug reports.
657 if ((descriptor = dfunc (i)) == 0) {
661 if (!ladspa_plugin_whitelist.empty()) {
662 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
667 PluginInfoPtr info(new LadspaPluginInfo);
668 info->name = descriptor->Name;
669 info->category = get_ladspa_category(descriptor->UniqueID);
670 info->creator = descriptor->Maker;
673 info->n_inputs = ChanCount();
674 info->n_outputs = ChanCount();
675 info->type = ARDOUR::LADSPA;
678 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
679 info->unique_id = buf;
681 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
682 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
683 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
684 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
686 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
687 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
692 if(_ladspa_plugin_info->empty()){
693 _ladspa_plugin_info->push_back (info);
696 //Ensure that the plugin is not already in the plugin list.
700 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
701 if(0 == info->unique_id.compare((*i)->unique_id)){
707 _ladspa_plugin_info->push_back (info);
710 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
713 // GDB WILL NOT LIKE YOU IF YOU DO THIS
720 PluginManager::get_ladspa_category (uint32_t plugin_id)
724 lrdf_statement pattern;
726 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
727 pattern.subject = buf;
728 pattern.predicate = const_cast<char*>(RDF_TYPE);
730 pattern.object_type = lrdf_uri;
732 lrdf_statement* matches1 = lrdf_matches (&pattern);
738 pattern.subject = matches1->object;
739 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
741 pattern.object_type = lrdf_literal;
743 lrdf_statement* matches2 = lrdf_matches (&pattern);
744 lrdf_free_statements(matches1);
750 string label = matches2->object;
751 lrdf_free_statements(matches2);
753 /* Kludge LADSPA class names to be singular and match LV2 class names.
754 This avoids duplicate plugin menus for every class, which is necessary
755 to make the plugin category menu at all usable, but is obviously a
758 In the short term, lrdf could be updated so the labels match and a new
759 release made. To support both specs, we should probably be mapping the
760 URIs to the same category in code and perhaps tweaking that hierarchy
761 dynamically to suit the user. Personally, I (drobilla) think that time
762 is better spent replacing the little-used LRDF.
764 In the longer term, we will abandon LRDF entirely in favour of LV2 and
765 use that class hierarchy. Aside from fixing this problem properly, that
766 will also allow for translated labels. SWH plugins have been LV2 for
767 ages; TAP needs porting. I don't know of anything else with LRDF data.
769 if (label == "Utilities") {
771 } else if (label == "Pitch shifters") {
772 return "Pitch Shifter";
773 } else if (label != "Dynamics" && label != "Chorus"
774 &&label[label.length() - 1] == 's'
775 && label[label.length() - 2] != 's') {
776 return label.substr(0, label.length() - 1);
787 PluginManager::lv2_refresh ()
789 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
790 delete _lv2_plugin_info;
791 _lv2_plugin_info = LV2PluginInfo::discover();
795 #ifdef AUDIOUNIT_SUPPORT
797 PluginManager::au_refresh (bool cache_only)
799 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
801 // disable automatic discovery in case we crash
802 bool discover_at_start = Config->get_discover_audio_units ();
803 Config->set_discover_audio_units (false);
804 Config->save_state();
806 delete _au_plugin_info;
807 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
809 // successful scan re-enabled automatic discovery if it was set
810 Config->set_discover_audio_units (discover_at_start);
811 Config->save_state();
816 #ifdef WINDOWS_VST_SUPPORT
819 PluginManager::windows_vst_refresh (bool cache_only)
821 if (_windows_vst_plugin_info) {
822 _windows_vst_plugin_info->clear ();
824 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
827 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
830 static bool windows_vst_filter (const string& str, void * /*arg*/)
832 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
833 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
837 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
839 vector<string> plugin_objects;
840 vector<string>::iterator x;
843 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
845 if (Config->get_verbose_plugin_scan()) {
846 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
849 find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
851 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
852 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
853 windows_vst_discover (*x, cache_only || cancelled());
856 if (Config->get_verbose_plugin_scan()) {
857 info << _("--- Windows VST plugins Scan Done") << endmsg;
863 static std::string dll_info (std::string path) {
867 off_t pe_hdr_off = 0;
869 int fd = g_open(path.c_str(), O_RDONLY, 0444);
872 return _("cannot open dll"); // TODO strerror()
875 if (68 != read (fd, buf, 68)) {
876 rv = _("invalid dll, file too small");
879 if (buf[0] != 'M' && buf[1] != 'Z') {
884 pe_hdr_off = *((int32_t*) &buf[60]);
885 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
886 rv = _("cannot determine dll type");
889 if (6 != read (fd, buf, 6)) {
890 rv = _("cannot read dll PE header");
894 if (buf[0] != 'P' && buf[1] != 'E') {
895 rv = _("invalid dll PE header");
899 type = *((uint16_t*) &buf[4]);
902 rv = _("i386 (32-bit)");
908 rv = _("x64 (64-bit)");
911 rv = _("Native Architecture");
914 rv = _("Unknown Architecture");
918 assert (rv.length() > 0);
924 PluginManager::windows_vst_discover (string path, bool cache_only)
926 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
928 if (Config->get_verbose_plugin_scan()) {
930 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
932 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
936 _cancel_timeout = false;
937 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
938 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
940 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
941 // .err file scanner output etc.
943 if (finfos->empty()) {
944 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
945 if (Config->get_verbose_plugin_scan()) {
946 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
951 uint32_t discovered = 0;
952 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
956 if (!finfo->canProcessReplacing) {
957 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
958 finfo->name, PROGRAM_NAME)
963 PluginInfoPtr info (new WindowsVSTPluginInfo);
965 /* what a joke freeware VST is */
967 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
968 info->name = PBD::basename_nosuffix (path);
970 info->name = finfo->name;
974 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
975 info->unique_id = buf;
976 info->category = "VST";
978 info->creator = finfo->creator;
980 info->n_inputs.set_audio (finfo->numInputs);
981 info->n_outputs.set_audio (finfo->numOutputs);
982 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
983 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
984 info->type = ARDOUR::Windows_VST;
986 // TODO: check dup-IDs (lxvst AND windows vst)
987 bool duplicate = false;
989 if (!_windows_vst_plugin_info->empty()) {
990 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
991 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
992 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1000 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1001 _windows_vst_plugin_info->push_back (info);
1003 if (Config->get_verbose_plugin_scan()) {
1004 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1009 vstfx_free_info_list (finfos);
1010 return discovered > 0 ? 0 : -1;
1013 #endif // WINDOWS_VST_SUPPORT
1015 #ifdef MACVST_SUPPORT
1017 PluginManager::mac_vst_refresh (bool cache_only)
1019 if (_mac_vst_plugin_info) {
1020 _mac_vst_plugin_info->clear ();
1022 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1025 mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1028 static bool mac_vst_filter (const string& str, void *)
1030 if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
1033 string plist = Glib::build_filename (str, "Contents", "Info.plist");
1034 if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1037 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1041 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1043 vector<string> plugin_objects;
1044 vector<string>::iterator x;
1046 find_paths_matching_filter (plugin_objects, path, mac_vst_filter, 0, true, true, false);
1048 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1049 ARDOUR::PluginScanMessage(_("MacVST"), *x, !cache_only && !cancelled());
1050 mac_vst_discover (*x, cache_only || cancelled());
1056 PluginManager::mac_vst_discover (string path, bool cache_only)
1058 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1060 _cancel_timeout = false;
1062 vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1063 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1065 if (finfos->empty()) {
1066 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1070 uint32_t discovered = 0;
1071 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1072 VSTInfo* finfo = *x;
1075 if (!finfo->canProcessReplacing) {
1076 warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1077 finfo->name, PROGRAM_NAME)
1082 PluginInfoPtr info (new MacVSTPluginInfo);
1084 info->name = finfo->name;
1086 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1087 info->unique_id = buf;
1088 info->category = "MacVST";
1090 info->creator = finfo->creator;
1092 info->n_inputs.set_audio (finfo->numInputs);
1093 info->n_outputs.set_audio (finfo->numOutputs);
1094 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1095 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1096 info->type = ARDOUR::MacVST;
1098 bool duplicate = false;
1099 if (!_mac_vst_plugin_info->empty()) {
1100 for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1101 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1102 warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1110 _mac_vst_plugin_info->push_back (info);
1115 vstfx_free_info_list (finfos);
1116 return discovered > 0 ? 0 : -1;
1119 #endif // MAC_VST_SUPPORT
1121 #ifdef LXVST_SUPPORT
1124 PluginManager::lxvst_refresh (bool cache_only)
1126 if (_lxvst_plugin_info) {
1127 _lxvst_plugin_info->clear ();
1129 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1132 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1135 static bool lxvst_filter (const string& str, void *)
1137 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1139 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1143 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1145 vector<string> plugin_objects;
1146 vector<string>::iterator x;
1153 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1155 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1157 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1158 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1159 lxvst_discover (*x, cache_only || cancelled());
1166 PluginManager::lxvst_discover (string path, bool cache_only)
1168 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1170 _cancel_timeout = false;
1171 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1172 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1174 if (finfos->empty()) {
1175 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1179 uint32_t discovered = 0;
1180 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1181 VSTInfo* finfo = *x;
1184 if (!finfo->canProcessReplacing) {
1185 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1186 finfo->name, PROGRAM_NAME)
1191 PluginInfoPtr info(new LXVSTPluginInfo);
1193 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1194 info->name = PBD::basename_nosuffix (path);
1196 info->name = finfo->name;
1200 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1201 info->unique_id = buf;
1202 info->category = "linuxVSTs";
1204 info->creator = finfo->creator;
1206 info->n_inputs.set_audio (finfo->numInputs);
1207 info->n_outputs.set_audio (finfo->numOutputs);
1208 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1209 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1210 info->type = ARDOUR::LXVST;
1212 /* Make sure we don't find the same plugin in more than one place along
1213 the LXVST_PATH We can't use a simple 'find' because the path is included
1214 in the PluginInfo, and that is the one thing we can be sure MUST be
1215 different if a duplicate instance is found. So we just compare the type
1216 and unique ID (which for some VSTs isn't actually unique...)
1219 // TODO: check dup-IDs with windowsVST, too
1220 bool duplicate = false;
1221 if (!_lxvst_plugin_info->empty()) {
1222 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1223 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1224 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1232 _lxvst_plugin_info->push_back (info);
1237 vstfx_free_info_list (finfos);
1238 return discovered > 0 ? 0 : -1;
1241 #endif // LXVST_SUPPORT
1244 PluginManager::PluginStatusType
1245 PluginManager::get_status (const PluginInfoPtr& pi) const
1247 PluginStatus ps (pi->type, pi->unique_id);
1248 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1249 if (i == statuses.end() ) {
1257 PluginManager::save_statuses ()
1259 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1262 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1263 switch ((*i).type) {
1274 ofs << "Windows-VST";
1289 switch ((*i).status) {
1302 ofs << (*i).unique_id;;
1305 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1306 PluginStatusesChanged (); /* EMIT SIGNAL */
1310 PluginManager::load_statuses ()
1312 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1314 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1317 stringstream ifs (fbuf);
1321 std::string sstatus;
1324 PluginStatusType status;
1341 /* rest of the line is the plugin ID */
1343 ifs.getline (buf, sizeof (buf), '\n');
1348 if (sstatus == "Normal") {
1350 } else if (sstatus == "Favorite") {
1352 } else if (sstatus == "Hidden") {
1355 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1361 if (stype == "LADSPA") {
1363 } else if (stype == "AudioUnit") {
1365 } else if (stype == "LV2") {
1367 } else if (stype == "Windows-VST") {
1369 } else if (stype == "LXVST") {
1371 } else if (stype == "Lua") {
1374 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1380 strip_whitespace_edges (id);
1381 set_status (type, id, status);
1386 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1388 PluginStatus ps (t, id, status);
1389 statuses.erase (ps);
1391 if (status == Normal) {
1395 statuses.insert (ps);
1398 ARDOUR::PluginInfoList&
1399 PluginManager::windows_vst_plugin_info ()
1401 #ifdef WINDOWS_VST_SUPPORT
1402 if (!_windows_vst_plugin_info) {
1403 windows_vst_refresh ();
1405 return *_windows_vst_plugin_info;
1407 return _empty_plugin_info;
1411 ARDOUR::PluginInfoList&
1412 PluginManager::mac_vst_plugin_info ()
1414 #ifdef MACVST_SUPPORT
1415 assert(_mac_vst_plugin_info);
1416 return *_mac_vst_plugin_info;
1418 return _empty_plugin_info;
1422 ARDOUR::PluginInfoList&
1423 PluginManager::lxvst_plugin_info ()
1425 #ifdef LXVST_SUPPORT
1426 assert(_lxvst_plugin_info);
1427 return *_lxvst_plugin_info;
1429 return _empty_plugin_info;
1433 ARDOUR::PluginInfoList&
1434 PluginManager::ladspa_plugin_info ()
1436 assert(_ladspa_plugin_info);
1437 return *_ladspa_plugin_info;
1440 ARDOUR::PluginInfoList&
1441 PluginManager::lv2_plugin_info ()
1444 assert(_lv2_plugin_info);
1445 return *_lv2_plugin_info;
1447 return _empty_plugin_info;
1451 ARDOUR::PluginInfoList&
1452 PluginManager::au_plugin_info ()
1454 #ifdef AUDIOUNIT_SUPPORT
1455 if (_au_plugin_info) {
1456 return *_au_plugin_info;
1459 return _empty_plugin_info;
1462 ARDOUR::PluginInfoList&
1463 PluginManager::lua_plugin_info ()
1465 assert(_lua_plugin_info);
1466 return *_lua_plugin_info;