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/plugin.h"
71 #include "ardour/plugin_manager.h"
72 #include "ardour/rc_configuration.h"
74 #include "ardour/search_paths.h"
77 #include "ardour/lv2_plugin.h"
80 #ifdef WINDOWS_VST_SUPPORT
81 #include "ardour/windows_vst_plugin.h"
85 #include "ardour/lxvst_plugin.h"
88 #ifdef AUDIOUNIT_SUPPORT
89 #include "ardour/audio_unit.h"
90 #include <Carbon/Carbon.h>
93 #include "pbd/error.h"
94 #include "pbd/stl_delete.h"
98 #include "ardour/debug.h"
100 using namespace ARDOUR;
104 PluginManager* PluginManager::_instance = 0;
105 std::string PluginManager::scanner_bin_path = "";
108 PluginManager::instance()
111 _instance = new PluginManager;
116 PluginManager::PluginManager ()
117 : _windows_vst_plugin_info(0)
118 , _lxvst_plugin_info(0)
119 , _ladspa_plugin_info(0)
120 , _lv2_plugin_info(0)
122 , _cancel_scan(false)
123 , _cancel_timeout(false)
128 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
129 // source-tree (ardev, etc)
130 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
132 #ifdef PLATFORM_WINDOWS
133 // on windows the .exe needs to be in the same folder with libardour.dll
134 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
136 // on Unices additional internal-use binaries are deployed to $libdir
137 vstsp += ARDOUR::ardour_dll_directory();
140 if (!PBD::find_file (vstsp,
141 #ifdef PLATFORM_WINDOWS
142 #ifdef DEBUGGABLE_SCANNER_APP
143 #if defined(DEBUG) || defined(_DEBUG)
144 "ardour-vst-scannerD.exe"
146 "ardour-vst-scannerRDC.exe"
149 "ardour-vst-scanner.exe"
154 , scanner_bin_path)) {
155 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
161 if ((s = getenv ("LADSPA_RDF_PATH"))){
165 if (lrdf_path.length() == 0) {
166 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
169 add_lrdf_data(lrdf_path);
170 add_ladspa_presets();
171 #ifdef WINDOWS_VST_SUPPORT
172 if (Config->get_use_windows_vst ()) {
173 add_windows_vst_presets ();
175 #endif /* WINDOWS_VST_SUPPORT */
178 if (Config->get_use_lxvst()) {
181 #endif /* Native LinuxVST support*/
183 if ((s = getenv ("VST_PATH"))) {
184 windows_vst_path = s;
185 } else if ((s = getenv ("VST_PLUGINS"))) {
186 windows_vst_path = s;
189 if (windows_vst_path.length() == 0) {
190 windows_vst_path = vst_search_path ();
193 if ((s = getenv ("LXVST_PATH"))) {
195 } else if ((s = getenv ("LXVST_PLUGINS"))) {
199 if (lxvst_path.length() == 0) {
200 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
201 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
202 "/usr/lib/vst:/usr/local/lib/vst";
205 /* first time setup, use 'default' path */
206 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
207 Config->set_plugin_path_lxvst(get_default_lxvst_path());
209 if (Config->get_plugin_path_vst() == X_("@default@")) {
210 Config->set_plugin_path_vst(get_default_windows_vst_path());
213 if (_instance == 0) {
217 BootMessage (_("Discovering Plugins"));
221 PluginManager::~PluginManager()
223 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
224 // don't bother, just exit quickly.
225 delete _windows_vst_plugin_info;
226 delete _lxvst_plugin_info;
227 delete _ladspa_plugin_info;
228 delete _lv2_plugin_info;
229 delete _au_plugin_info;
234 PluginManager::refresh (bool cache_only)
236 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
242 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
243 _cancel_scan = false;
245 BootMessage (_("Scanning LADSPA Plugins"));
248 BootMessage (_("Scanning LV2 Plugins"));
251 #ifdef WINDOWS_VST_SUPPORT
252 if (Config->get_use_windows_vst()) {
254 BootMessage (_("Scanning Windows VST Plugins"));
256 BootMessage (_("Discovering Windows VST Plugins"));
258 windows_vst_refresh (cache_only);
260 #endif // WINDOWS_VST_SUPPORT
263 if(Config->get_use_lxvst()) {
265 BootMessage (_("Scanning Linux VST Plugins"));
267 BootMessage (_("Discovering Linux VST Plugins"));
269 lxvst_refresh(cache_only);
271 #endif //Native linuxVST SUPPORT
273 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
275 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
276 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
278 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
279 if (Config->get_verbose_plugin_scan()) {
280 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
282 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
290 #ifdef AUDIOUNIT_SUPPORT
292 BootMessage (_("Scanning AU Plugins"));
294 BootMessage (_("Discovering AU Plugins"));
296 au_refresh (cache_only);
299 BootMessage (_("Plugin Scan Complete..."));
300 PluginListChanged (); /* EMIT SIGNAL */
301 PluginScanMessage(X_("closeme"), "", false);
302 _cancel_scan = false;
306 PluginManager::cancel_plugin_scan ()
312 PluginManager::cancel_plugin_timeout ()
314 _cancel_timeout = true;
318 PluginManager::clear_vst_cache ()
320 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
321 #ifdef WINDOWS_VST_SUPPORT
323 vector<string> fsi_files;
324 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
325 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
326 ::g_unlink(i->c_str());
330 vector<string> fsi_files;
331 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
332 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
333 ::g_unlink(i->c_str());
337 vector<string> fsi_files;
338 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
339 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
340 ::g_unlink(i->c_str());
347 vector<string> fsi_files;
348 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
349 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
350 ::g_unlink(i->c_str());
354 vector<string> fsi_files;
355 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
356 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
357 ::g_unlink(i->c_str());
361 vector<string> fsi_files;
362 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
363 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
364 ::g_unlink(i->c_str());
368 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
370 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
371 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
372 PBD::remove_directory (dir);
376 #endif // old cache cleanup
378 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
380 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
381 vector<string> fsi_files;
382 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
383 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
384 ::g_unlink(i->c_str());
391 PluginManager::clear_vst_blacklist ()
393 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
395 #ifdef WINDOWS_VST_SUPPORT
397 vector<string> fsi_files;
398 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
399 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
400 ::g_unlink(i->c_str());
407 vector<string> fsi_files;
408 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
409 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
410 ::g_unlink(i->c_str());
414 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
416 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
417 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
418 PBD::remove_directory (dir);
423 #endif // old blacklist cleanup
425 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
427 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
428 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
429 ::g_unlink (fn.c_str());
437 PluginManager::clear_au_cache ()
439 #ifdef AUDIOUNIT_SUPPORT
440 // AUPluginInfo::au_cache_path ()
441 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
442 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
443 ::g_unlink(fn.c_str());
449 PluginManager::clear_au_blacklist ()
451 #ifdef AUDIOUNIT_SUPPORT
452 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
453 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
454 ::g_unlink(fn.c_str());
460 PluginManager::ladspa_refresh ()
462 if (_ladspa_plugin_info) {
463 _ladspa_plugin_info->clear ();
465 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
468 /* allow LADSPA_PATH to augment, not override standard locations */
470 /* Only add standard locations to ladspa_path if it doesn't
471 * already contain them. Check for trailing G_DIR_SEPARATOR too.
474 vector<string> ladspa_modules;
476 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
478 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
479 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
480 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
482 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
483 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
484 ladspa_discover (*i);
489 static bool rdf_filter (const string &str, void* /*arg*/)
491 return str[0] != '.' &&
492 ((str.find(".rdf") == (str.length() - 4)) ||
493 (str.find(".rdfs") == (str.length() - 5)) ||
494 (str.find(".n3") == (str.length() - 3)) ||
495 (str.find(".ttl") == (str.length() - 4)));
500 PluginManager::add_ladspa_presets()
502 add_presets ("ladspa");
506 PluginManager::add_windows_vst_presets()
508 add_presets ("windows-vst");
512 PluginManager::add_lxvst_presets()
514 add_presets ("lxvst");
518 PluginManager::add_presets(string domain)
521 vector<string> presets;
522 vector<string>::iterator x;
525 if ((envvar = getenv ("HOME")) == 0) {
529 string path = string_compose("%1/.%2/rdf", envvar, domain);
530 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
532 for (x = presets.begin(); x != presets.end (); ++x) {
533 string file = "file:" + *x;
534 if (lrdf_read_file(file.c_str())) {
535 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
543 PluginManager::add_lrdf_data (const string &path)
546 vector<string> rdf_files;
547 vector<string>::iterator x;
549 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
551 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
552 const string uri(string("file://") + *x);
554 if (lrdf_read_file(uri.c_str())) {
555 warning << "Could not parse rdf file: " << uri << endmsg;
562 PluginManager::ladspa_discover (string path)
564 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
566 Glib::Module module(path);
567 const LADSPA_Descriptor *descriptor;
568 LADSPA_Descriptor_Function dfunc;
572 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
573 path, Glib::Module::get_last_error()) << endmsg;
578 if (!module.get_symbol("ladspa_descriptor", func)) {
579 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
580 error << Glib::Module::get_last_error() << endmsg;
584 dfunc = (LADSPA_Descriptor_Function)func;
586 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
588 for (uint32_t i = 0; ; ++i) {
589 if ((descriptor = dfunc (i)) == 0) {
593 if (!ladspa_plugin_whitelist.empty()) {
594 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
599 PluginInfoPtr info(new LadspaPluginInfo);
600 info->name = descriptor->Name;
601 info->category = get_ladspa_category(descriptor->UniqueID);
602 info->creator = descriptor->Maker;
605 info->n_inputs = ChanCount();
606 info->n_outputs = ChanCount();
607 info->type = ARDOUR::LADSPA;
610 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
611 info->unique_id = buf;
613 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
614 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
615 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
616 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
618 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
619 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
624 if(_ladspa_plugin_info->empty()){
625 _ladspa_plugin_info->push_back (info);
628 //Ensure that the plugin is not already in the plugin list.
632 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
633 if(0 == info->unique_id.compare((*i)->unique_id)){
639 _ladspa_plugin_info->push_back (info);
642 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
645 // GDB WILL NOT LIKE YOU IF YOU DO THIS
652 PluginManager::get_ladspa_category (uint32_t plugin_id)
656 lrdf_statement pattern;
658 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
659 pattern.subject = buf;
660 pattern.predicate = const_cast<char*>(RDF_TYPE);
662 pattern.object_type = lrdf_uri;
664 lrdf_statement* matches1 = lrdf_matches (&pattern);
670 pattern.subject = matches1->object;
671 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
673 pattern.object_type = lrdf_literal;
675 lrdf_statement* matches2 = lrdf_matches (&pattern);
676 lrdf_free_statements(matches1);
682 string label = matches2->object;
683 lrdf_free_statements(matches2);
685 /* Kludge LADSPA class names to be singular and match LV2 class names.
686 This avoids duplicate plugin menus for every class, which is necessary
687 to make the plugin category menu at all usable, but is obviously a
690 In the short term, lrdf could be updated so the labels match and a new
691 release made. To support both specs, we should probably be mapping the
692 URIs to the same category in code and perhaps tweaking that hierarchy
693 dynamically to suit the user. Personally, I (drobilla) think that time
694 is better spent replacing the little-used LRDF.
696 In the longer term, we will abandon LRDF entirely in favour of LV2 and
697 use that class hierarchy. Aside from fixing this problem properly, that
698 will also allow for translated labels. SWH plugins have been LV2 for
699 ages; TAP needs porting. I don't know of anything else with LRDF data.
701 if (label == "Utilities") {
703 } else if (label == "Pitch shifters") {
704 return "Pitch Shifter";
705 } else if (label != "Dynamics" && label != "Chorus"
706 &&label[label.length() - 1] == 's'
707 && label[label.length() - 2] != 's') {
708 return label.substr(0, label.length() - 1);
719 PluginManager::lv2_refresh ()
721 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
722 delete _lv2_plugin_info;
723 _lv2_plugin_info = LV2PluginInfo::discover();
727 #ifdef AUDIOUNIT_SUPPORT
729 PluginManager::au_refresh (bool cache_only)
731 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
733 // disable automatic discovery in case we crash
734 bool discover_at_start = Config->get_discover_audio_units ();
735 Config->set_discover_audio_units (false);
736 Config->save_state();
738 delete _au_plugin_info;
739 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
741 // successful scan re-enabled automatic discovery if it was set
742 Config->set_discover_audio_units (discover_at_start);
743 Config->save_state();
748 #ifdef WINDOWS_VST_SUPPORT
751 PluginManager::windows_vst_refresh (bool cache_only)
753 if (_windows_vst_plugin_info) {
754 _windows_vst_plugin_info->clear ();
756 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
759 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
762 static bool windows_vst_filter (const string& str, void * /*arg*/)
764 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
765 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
769 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
771 vector<string> plugin_objects;
772 vector<string>::iterator x;
775 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
777 if (Config->get_verbose_plugin_scan()) {
778 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
781 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
783 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
784 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
785 windows_vst_discover (*x, cache_only || cancelled());
788 if (Config->get_verbose_plugin_scan()) {
789 info << _("--- Windows VST plugins Scan Done") << endmsg;
795 static std::string dll_info (std::string path) {
799 off_t pe_hdr_off = 0;
801 int fd = g_open(path.c_str(), O_RDONLY, 0444);
804 return _("cannot open dll"); // TODO strerror()
807 if (68 != read (fd, buf, 68)) {
808 rv = _("invalid dll, file too small");
811 if (buf[0] != 'M' && buf[1] != 'Z') {
816 pe_hdr_off = *((int32_t*) &buf[60]);
817 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
818 rv = _("cannot determine dll type");
821 if (6 != read (fd, buf, 6)) {
822 rv = _("cannot read dll PE header");
826 if (buf[0] != 'P' && buf[1] != 'E') {
827 rv = _("invalid dll PE header");
831 type = *((uint16_t*) &buf[4]);
834 rv = _("i386 (32-bit)");
840 rv = _("x64 (64-bit)");
843 rv = _("Native Architecture");
846 rv = _("Unknown Architecture");
850 assert (rv.length() > 0);
856 PluginManager::windows_vst_discover (string path, bool cache_only)
858 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
860 if (Config->get_verbose_plugin_scan()) {
862 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
864 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
868 _cancel_timeout = false;
869 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
870 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
872 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
873 // .err file scanner output etc.
875 if (finfos->empty()) {
876 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
877 if (Config->get_verbose_plugin_scan()) {
878 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
883 uint32_t discovered = 0;
884 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
888 if (!finfo->canProcessReplacing) {
889 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
890 finfo->name, PROGRAM_NAME)
895 PluginInfoPtr info (new WindowsVSTPluginInfo);
897 /* what a joke freeware VST is */
899 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
900 info->name = PBD::basename_nosuffix (path);
902 info->name = finfo->name;
906 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
907 info->unique_id = buf;
908 info->category = "VST";
910 info->creator = finfo->creator;
912 info->n_inputs.set_audio (finfo->numInputs);
913 info->n_outputs.set_audio (finfo->numOutputs);
914 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
915 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
916 info->type = ARDOUR::Windows_VST;
918 // TODO: check dup-IDs (lxvst AND windows vst)
919 bool duplicate = false;
921 if (!_windows_vst_plugin_info->empty()) {
922 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
923 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
924 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
932 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
933 _windows_vst_plugin_info->push_back (info);
935 if (Config->get_verbose_plugin_scan()) {
936 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
941 vstfx_free_info_list (finfos);
942 return discovered > 0 ? 0 : -1;
945 #endif // WINDOWS_VST_SUPPORT
950 PluginManager::lxvst_refresh (bool cache_only)
952 if (_lxvst_plugin_info) {
953 _lxvst_plugin_info->clear ();
955 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
958 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
961 static bool lxvst_filter (const string& str, void *)
963 /* Not a dotfile, has a prefix before a period, suffix is "so" */
965 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
969 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
971 vector<string> plugin_objects;
972 vector<string>::iterator x;
979 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
981 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
983 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
984 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
985 lxvst_discover (*x, cache_only || cancelled());
992 PluginManager::lxvst_discover (string path, bool cache_only)
994 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
996 _cancel_timeout = false;
997 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
998 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1000 if (finfos->empty()) {
1001 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1005 uint32_t discovered = 0;
1006 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1007 VSTInfo* finfo = *x;
1010 if (!finfo->canProcessReplacing) {
1011 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1012 finfo->name, PROGRAM_NAME)
1017 PluginInfoPtr info(new LXVSTPluginInfo);
1019 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1020 info->name = PBD::basename_nosuffix (path);
1022 info->name = finfo->name;
1026 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
1027 info->unique_id = buf;
1028 info->category = "linuxVSTs";
1030 info->creator = finfo->creator;
1032 info->n_inputs.set_audio (finfo->numInputs);
1033 info->n_outputs.set_audio (finfo->numOutputs);
1034 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
1035 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
1036 info->type = ARDOUR::LXVST;
1038 /* Make sure we don't find the same plugin in more than one place along
1039 the LXVST_PATH We can't use a simple 'find' because the path is included
1040 in the PluginInfo, and that is the one thing we can be sure MUST be
1041 different if a duplicate instance is found. So we just compare the type
1042 and unique ID (which for some VSTs isn't actually unique...)
1045 // TODO: check dup-IDs with windowsVST, too
1046 bool duplicate = false;
1047 if (!_lxvst_plugin_info->empty()) {
1048 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1049 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1050 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1058 _lxvst_plugin_info->push_back (info);
1063 vstfx_free_info_list (finfos);
1064 return discovered > 0 ? 0 : -1;
1067 #endif // LXVST_SUPPORT
1070 PluginManager::PluginStatusType
1071 PluginManager::get_status (const PluginInfoPtr& pi)
1073 PluginStatus ps (pi->type, pi->unique_id);
1074 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1075 if (i == statuses.end() ) {
1083 PluginManager::save_statuses ()
1085 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1088 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1089 switch ((*i).type) {
1100 ofs << "Windows-VST";
1113 switch ((*i).status) {
1126 ofs << (*i).unique_id;;
1129 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1130 PluginStatusesChanged (); /* EMIT SIGNAL */
1134 PluginManager::load_statuses ()
1136 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1138 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1141 stringstream ifs (fbuf);
1145 std::string sstatus;
1148 PluginStatusType status;
1165 /* rest of the line is the plugin ID */
1167 ifs.getline (buf, sizeof (buf), '\n');
1172 if (sstatus == "Normal") {
1174 } else if (sstatus == "Favorite") {
1176 } else if (sstatus == "Hidden") {
1179 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1185 if (stype == "LADSPA") {
1187 } else if (stype == "AudioUnit") {
1189 } else if (stype == "LV2") {
1191 } else if (stype == "Windows-VST") {
1193 } else if (stype == "LXVST") {
1196 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1202 strip_whitespace_edges (id);
1203 set_status (type, id, status);
1208 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1210 PluginStatus ps (t, id, status);
1211 statuses.erase (ps);
1213 if (status == Normal) {
1217 statuses.insert (ps);
1220 ARDOUR::PluginInfoList&
1221 PluginManager::windows_vst_plugin_info ()
1223 #ifdef WINDOWS_VST_SUPPORT
1224 if (!_windows_vst_plugin_info) {
1225 windows_vst_refresh ();
1227 return *_windows_vst_plugin_info;
1229 return _empty_plugin_info;
1233 ARDOUR::PluginInfoList&
1234 PluginManager::lxvst_plugin_info ()
1236 #ifdef LXVST_SUPPORT
1237 assert(_lxvst_plugin_info);
1238 return *_lxvst_plugin_info;
1240 return _empty_plugin_info;
1244 ARDOUR::PluginInfoList&
1245 PluginManager::ladspa_plugin_info ()
1247 assert(_ladspa_plugin_info);
1248 return *_ladspa_plugin_info;
1251 ARDOUR::PluginInfoList&
1252 PluginManager::lv2_plugin_info ()
1255 assert(_lv2_plugin_info);
1256 return *_lv2_plugin_info;
1258 return _empty_plugin_info;
1262 ARDOUR::PluginInfoList&
1263 PluginManager::au_plugin_info ()
1265 #ifdef AUDIOUNIT_SUPPORT
1266 if (_au_plugin_info) {
1267 return *_au_plugin_info;
1270 return _empty_plugin_info;