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>
35 #ifdef WINDOWS_VST_SUPPORT
36 #include "ardour/vst_info_file.h"
38 #include "pbd/basename.h"
40 #endif // WINDOWS_VST_SUPPORT
43 #include "ardour/vst_info_file.h"
44 #include "ardour/linux_vst_support.h"
45 #include "pbd/basename.h"
47 #endif //LXVST_SUPPORT
49 #include <glib/gstdio.h>
50 #include <glibmm/miscutils.h>
51 #include <glibmm/pattern.h>
52 #include <glibmm/fileutils.h>
53 #include <glibmm/miscutils.h>
55 #include "pbd/whitespace.h"
56 #include "pbd/file_utils.h"
58 #include "ardour/debug.h"
59 #include "ardour/filesystem_paths.h"
60 #include "ardour/ladspa.h"
61 #include "ardour/ladspa_plugin.h"
62 #include "ardour/plugin.h"
63 #include "ardour/plugin_manager.h"
64 #include "ardour/rc_configuration.h"
66 #include "ardour/search_paths.h"
69 #include "ardour/lv2_plugin.h"
72 #ifdef WINDOWS_VST_SUPPORT
73 #include "ardour/windows_vst_plugin.h"
77 #include "ardour/lxvst_plugin.h"
80 #ifdef AUDIOUNIT_SUPPORT
81 #include "ardour/audio_unit.h"
82 #include <Carbon/Carbon.h>
85 #include "pbd/error.h"
86 #include "pbd/stl_delete.h"
90 #include "ardour/debug.h"
92 using namespace ARDOUR;
96 PluginManager* PluginManager::_instance = 0;
97 std::string PluginManager::scanner_bin_path = "";
100 PluginManager::instance()
103 _instance = new PluginManager;
108 PluginManager::PluginManager ()
109 : _windows_vst_plugin_info(0)
110 , _lxvst_plugin_info(0)
111 , _ladspa_plugin_info(0)
112 , _lv2_plugin_info(0)
114 , _cancel_scan(false)
115 , _cancel_timeout(false)
120 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
121 // source-tree (ardev, etc)
122 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
124 #ifdef PLATFORM_WINDOWS
125 // on windows the .exe needs to be in the same folder with libardour.dll
126 vstsp += Glib::build_filename(g_win32_get_package_installation_directory_of_module (0), "bin");
128 // on Unices additional internal-use binaries are deployed to $libdir
129 vstsp += ARDOUR::ardour_dll_directory();
132 if (!PBD::find_file (vstsp,
133 #ifdef PLATFORM_WINDOWS
134 #ifdef DEBUGGABLE_SCANNER_APP
135 #if defined(DEBUG) || defined(_DEBUG)
136 "ardour-vst-scannerD.exe"
138 "ardour-vst-scannerRDC.exe"
141 "ardour-vst-scanner.exe"
146 , scanner_bin_path)) {
147 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
153 if ((s = getenv ("LADSPA_RDF_PATH"))){
157 if (lrdf_path.length() == 0) {
158 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
161 add_lrdf_data(lrdf_path);
162 add_ladspa_presets();
163 #ifdef WINDOWS_VST_SUPPORT
164 if (Config->get_use_windows_vst ()) {
165 add_windows_vst_presets ();
167 #endif /* WINDOWS_VST_SUPPORT */
170 if (Config->get_use_lxvst()) {
173 #endif /* Native LinuxVST support*/
175 if ((s = getenv ("VST_PATH"))) {
176 windows_vst_path = s;
177 } else if ((s = getenv ("VST_PLUGINS"))) {
178 windows_vst_path = s;
181 if (windows_vst_path.length() == 0) {
182 windows_vst_path = vst_search_path ();
185 if ((s = getenv ("LXVST_PATH"))) {
187 } else if ((s = getenv ("LXVST_PLUGINS"))) {
191 if (lxvst_path.length() == 0) {
192 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
193 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
194 "/usr/lib/vst:/usr/local/lib/vst";
197 /* first time setup, use 'default' path */
198 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
199 Config->set_plugin_path_lxvst(get_default_lxvst_path());
201 if (Config->get_plugin_path_vst() == X_("@default@")) {
202 Config->set_plugin_path_vst(get_default_windows_vst_path());
205 if (_instance == 0) {
209 BootMessage (_("Discovering Plugins"));
213 PluginManager::~PluginManager()
215 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
216 // don't bother, just exit quickly.
217 delete _windows_vst_plugin_info;
218 delete _lxvst_plugin_info;
219 delete _ladspa_plugin_info;
220 delete _lv2_plugin_info;
221 delete _au_plugin_info;
226 PluginManager::refresh (bool cache_only)
228 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
234 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
235 _cancel_scan = false;
237 BootMessage (_("Scanning LADSPA Plugins"));
240 BootMessage (_("Scanning LV2 Plugins"));
243 #ifdef WINDOWS_VST_SUPPORT
244 if (Config->get_use_windows_vst()) {
246 BootMessage (_("Scanning Windows VST Plugins"));
248 BootMessage (_("Discovering Windows VST Plugins"));
250 windows_vst_refresh (cache_only);
252 #endif // WINDOWS_VST_SUPPORT
255 if(Config->get_use_lxvst()) {
257 BootMessage (_("Scanning Linux VST Plugins"));
259 BootMessage (_("Discovering Linux VST Plugins"));
261 lxvst_refresh(cache_only);
263 #endif //Native linuxVST SUPPORT
265 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
267 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
268 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
270 std::ifstream ifs (fn.c_str ());
271 bl.assign ((std::istreambuf_iterator<char> (ifs)), (std::istreambuf_iterator<char> ()));
272 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
277 #ifdef AUDIOUNIT_SUPPORT
279 BootMessage (_("Scanning AU Plugins"));
281 BootMessage (_("Discovering AU Plugins"));
283 au_refresh (cache_only);
286 BootMessage (_("Plugin Scan Complete..."));
287 PluginListChanged (); /* EMIT SIGNAL */
288 PluginScanMessage(X_("closeme"), "", false);
289 _cancel_scan = false;
293 PluginManager::cancel_plugin_scan ()
299 PluginManager::cancel_plugin_timeout ()
301 _cancel_timeout = true;
305 PluginManager::clear_vst_cache ()
307 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
308 #ifdef WINDOWS_VST_SUPPORT
310 vector<string> fsi_files;
311 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
312 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
313 ::g_unlink(i->c_str());
317 vector<string> fsi_files;
318 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
319 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
320 ::g_unlink(i->c_str());
324 vector<string> fsi_files;
325 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
326 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
327 ::g_unlink(i->c_str());
334 vector<string> fsi_files;
335 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
336 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
337 ::g_unlink(i->c_str());
341 vector<string> fsi_files;
342 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
343 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
344 ::g_unlink(i->c_str());
348 vector<string> fsi_files;
349 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
350 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
351 ::g_unlink(i->c_str());
355 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
357 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
358 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
359 PBD::remove_directory (dir);
363 #endif // old cache cleanup
365 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
367 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
368 vector<string> fsi_files;
369 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
370 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
371 ::g_unlink(i->c_str());
378 PluginManager::clear_vst_blacklist ()
380 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
382 #ifdef WINDOWS_VST_SUPPORT
384 vector<string> fsi_files;
385 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
386 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
387 ::g_unlink(i->c_str());
394 vector<string> fsi_files;
395 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
396 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
397 ::g_unlink(i->c_str());
401 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
403 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
404 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
405 PBD::remove_directory (dir);
410 #endif // old blacklist cleanup
412 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
414 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
415 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
416 ::g_unlink (fn.c_str());
424 PluginManager::clear_au_cache ()
426 #ifdef AUDIOUNIT_SUPPORT
427 // AUPluginInfo::au_cache_path ()
428 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
429 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
430 ::g_unlink(fn.c_str());
436 PluginManager::clear_au_blacklist ()
438 #ifdef AUDIOUNIT_SUPPORT
439 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
440 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
441 ::g_unlink(fn.c_str());
447 PluginManager::ladspa_refresh ()
449 if (_ladspa_plugin_info) {
450 _ladspa_plugin_info->clear ();
452 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
455 /* allow LADSPA_PATH to augment, not override standard locations */
457 /* Only add standard locations to ladspa_path if it doesn't
458 * already contain them. Check for trailing G_DIR_SEPARATOR too.
461 vector<string> ladspa_modules;
463 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
465 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
466 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
467 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
469 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
470 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
471 ladspa_discover (*i);
476 static bool rdf_filter (const string &str, void* /*arg*/)
478 return str[0] != '.' &&
479 ((str.find(".rdf") == (str.length() - 4)) ||
480 (str.find(".rdfs") == (str.length() - 5)) ||
481 (str.find(".n3") == (str.length() - 3)) ||
482 (str.find(".ttl") == (str.length() - 4)));
487 PluginManager::add_ladspa_presets()
489 add_presets ("ladspa");
493 PluginManager::add_windows_vst_presets()
495 add_presets ("windows-vst");
499 PluginManager::add_lxvst_presets()
501 add_presets ("lxvst");
505 PluginManager::add_presets(string domain)
508 vector<string> presets;
509 vector<string>::iterator x;
512 if ((envvar = getenv ("HOME")) == 0) {
516 string path = string_compose("%1/.%2/rdf", envvar, domain);
517 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
519 for (x = presets.begin(); x != presets.end (); ++x) {
520 string file = "file:" + *x;
521 if (lrdf_read_file(file.c_str())) {
522 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
530 PluginManager::add_lrdf_data (const string &path)
533 vector<string> rdf_files;
534 vector<string>::iterator x;
536 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
538 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
539 const string uri(string("file://") + *x);
541 if (lrdf_read_file(uri.c_str())) {
542 warning << "Could not parse rdf file: " << uri << endmsg;
549 PluginManager::ladspa_discover (string path)
551 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
553 Glib::Module module(path);
554 const LADSPA_Descriptor *descriptor;
555 LADSPA_Descriptor_Function dfunc;
559 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
560 path, Glib::Module::get_last_error()) << endmsg;
565 if (!module.get_symbol("ladspa_descriptor", func)) {
566 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
567 error << Glib::Module::get_last_error() << endmsg;
571 dfunc = (LADSPA_Descriptor_Function)func;
573 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
575 for (uint32_t i = 0; ; ++i) {
576 if ((descriptor = dfunc (i)) == 0) {
580 if (!ladspa_plugin_whitelist.empty()) {
581 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
586 PluginInfoPtr info(new LadspaPluginInfo);
587 info->name = descriptor->Name;
588 info->category = get_ladspa_category(descriptor->UniqueID);
589 info->creator = descriptor->Maker;
592 info->n_inputs = ChanCount();
593 info->n_outputs = ChanCount();
594 info->type = ARDOUR::LADSPA;
597 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
598 info->unique_id = buf;
600 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
601 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
602 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
603 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
605 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
606 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
611 if(_ladspa_plugin_info->empty()){
612 _ladspa_plugin_info->push_back (info);
615 //Ensure that the plugin is not already in the plugin list.
619 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
620 if(0 == info->unique_id.compare((*i)->unique_id)){
626 _ladspa_plugin_info->push_back (info);
629 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
632 // GDB WILL NOT LIKE YOU IF YOU DO THIS
639 PluginManager::get_ladspa_category (uint32_t plugin_id)
643 lrdf_statement pattern;
645 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
646 pattern.subject = buf;
647 pattern.predicate = const_cast<char*>(RDF_TYPE);
649 pattern.object_type = lrdf_uri;
651 lrdf_statement* matches1 = lrdf_matches (&pattern);
657 pattern.subject = matches1->object;
658 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
660 pattern.object_type = lrdf_literal;
662 lrdf_statement* matches2 = lrdf_matches (&pattern);
663 lrdf_free_statements(matches1);
669 string label = matches2->object;
670 lrdf_free_statements(matches2);
672 /* Kludge LADSPA class names to be singular and match LV2 class names.
673 This avoids duplicate plugin menus for every class, which is necessary
674 to make the plugin category menu at all usable, but is obviously a
677 In the short term, lrdf could be updated so the labels match and a new
678 release made. To support both specs, we should probably be mapping the
679 URIs to the same category in code and perhaps tweaking that hierarchy
680 dynamically to suit the user. Personally, I (drobilla) think that time
681 is better spent replacing the little-used LRDF.
683 In the longer term, we will abandon LRDF entirely in favour of LV2 and
684 use that class hierarchy. Aside from fixing this problem properly, that
685 will also allow for translated labels. SWH plugins have been LV2 for
686 ages; TAP needs porting. I don't know of anything else with LRDF data.
688 if (label == "Utilities") {
690 } else if (label == "Pitch shifters") {
691 return "Pitch Shifter";
692 } else if (label != "Dynamics" && label != "Chorus"
693 &&label[label.length() - 1] == 's'
694 && label[label.length() - 2] != 's') {
695 return label.substr(0, label.length() - 1);
706 PluginManager::lv2_refresh ()
708 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
709 delete _lv2_plugin_info;
710 _lv2_plugin_info = LV2PluginInfo::discover();
714 #ifdef AUDIOUNIT_SUPPORT
716 PluginManager::au_refresh (bool cache_only)
718 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
720 // disable automatic discovery in case we crash
721 bool discover_at_start = Config->get_discover_audio_units ();
722 Config->set_discover_audio_units (false);
723 Config->save_state();
725 delete _au_plugin_info;
726 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
728 // successful scan re-enabled automatic discovery if it was set
729 Config->set_discover_audio_units (discover_at_start);
730 Config->save_state();
735 #ifdef WINDOWS_VST_SUPPORT
738 PluginManager::windows_vst_refresh (bool cache_only)
740 if (_windows_vst_plugin_info) {
741 _windows_vst_plugin_info->clear ();
743 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
746 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
749 static bool windows_vst_filter (const string& str, void * /*arg*/)
751 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
752 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
756 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
758 vector<string> plugin_objects;
759 vector<string>::iterator x;
762 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
764 if (Config->get_verbose_plugin_scan()) {
765 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
768 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
770 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
771 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
772 windows_vst_discover (*x, cache_only || cancelled());
775 if (Config->get_verbose_plugin_scan()) {
776 info << _("--- Windows VST plugins Scan Done") << endmsg;
783 PluginManager::windows_vst_discover (string path, bool cache_only)
785 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
787 if (Config->get_verbose_plugin_scan()) {
788 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
791 _cancel_timeout = false;
792 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
793 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
795 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
796 // .err file scanner output etc.
798 if (finfos->empty()) {
799 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
800 if (Config->get_verbose_plugin_scan()) {
801 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
806 uint32_t discovered = 0;
807 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
811 if (!finfo->canProcessReplacing) {
812 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
813 finfo->name, PROGRAM_NAME)
818 PluginInfoPtr info (new WindowsVSTPluginInfo);
820 /* what a joke freeware VST is */
822 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
823 info->name = PBD::basename_nosuffix (path);
825 info->name = finfo->name;
829 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
830 info->unique_id = buf;
831 info->category = "VST";
833 info->creator = finfo->creator;
835 info->n_inputs.set_audio (finfo->numInputs);
836 info->n_outputs.set_audio (finfo->numOutputs);
837 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
838 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
839 info->type = ARDOUR::Windows_VST;
841 // TODO: check dup-IDs (lxvst AND windows vst)
842 bool duplicate = false;
844 if (!_windows_vst_plugin_info->empty()) {
845 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
846 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
847 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
855 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
856 _windows_vst_plugin_info->push_back (info);
858 if (Config->get_verbose_plugin_scan()) {
859 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
864 vstfx_free_info_list (finfos);
865 return discovered > 0 ? 0 : -1;
868 #endif // WINDOWS_VST_SUPPORT
873 PluginManager::lxvst_refresh (bool cache_only)
875 if (_lxvst_plugin_info) {
876 _lxvst_plugin_info->clear ();
878 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
881 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
884 static bool lxvst_filter (const string& str, void *)
886 /* Not a dotfile, has a prefix before a period, suffix is "so" */
888 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
892 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
894 vector<string> plugin_objects;
895 vector<string>::iterator x;
902 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
904 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
906 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
907 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
908 lxvst_discover (*x, cache_only || cancelled());
915 PluginManager::lxvst_discover (string path, bool cache_only)
917 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
919 _cancel_timeout = false;
920 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
921 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
923 if (finfos->empty()) {
924 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
928 uint32_t discovered = 0;
929 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
933 if (!finfo->canProcessReplacing) {
934 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
935 finfo->name, PROGRAM_NAME)
940 PluginInfoPtr info(new LXVSTPluginInfo);
942 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
943 info->name = PBD::basename_nosuffix (path);
945 info->name = finfo->name;
949 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
950 info->unique_id = buf;
951 info->category = "linuxVSTs";
953 info->creator = finfo->creator;
955 info->n_inputs.set_audio (finfo->numInputs);
956 info->n_outputs.set_audio (finfo->numOutputs);
957 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
958 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
959 info->type = ARDOUR::LXVST;
961 /* Make sure we don't find the same plugin in more than one place along
962 the LXVST_PATH We can't use a simple 'find' because the path is included
963 in the PluginInfo, and that is the one thing we can be sure MUST be
964 different if a duplicate instance is found. So we just compare the type
965 and unique ID (which for some VSTs isn't actually unique...)
968 // TODO: check dup-IDs with windowsVST, too
969 bool duplicate = false;
970 if (!_lxvst_plugin_info->empty()) {
971 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
972 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
973 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
981 _lxvst_plugin_info->push_back (info);
986 vstfx_free_info_list (finfos);
987 return discovered > 0 ? 0 : -1;
990 #endif // LXVST_SUPPORT
993 PluginManager::PluginStatusType
994 PluginManager::get_status (const PluginInfoPtr& pi)
996 PluginStatus ps (pi->type, pi->unique_id);
997 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
998 if (i == statuses.end() ) {
1006 PluginManager::save_statuses ()
1009 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1011 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
1017 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1018 switch ((*i).type) {
1029 ofs << "Windows-VST";
1038 switch ((*i).status) {
1051 ofs << (*i).unique_id;;
1059 PluginManager::load_statuses ()
1061 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1062 ifstream ifs (path.c_str());
1069 std::string sstatus;
1072 PluginStatusType status;
1089 /* rest of the line is the plugin ID */
1091 ifs.getline (buf, sizeof (buf), '\n');
1096 if (sstatus == "Normal") {
1098 } else if (sstatus == "Favorite") {
1100 } else if (sstatus == "Hidden") {
1103 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1109 if (stype == "LADSPA") {
1111 } else if (stype == "AudioUnit") {
1113 } else if (stype == "LV2") {
1115 } else if (stype == "Windows-VST") {
1117 } else if (stype == "LXVST") {
1120 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1126 strip_whitespace_edges (id);
1127 set_status (type, id, status);
1134 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1136 PluginStatus ps (t, id, status);
1137 statuses.erase (ps);
1139 if (status == Normal) {
1143 statuses.insert (ps);
1146 ARDOUR::PluginInfoList&
1147 PluginManager::windows_vst_plugin_info ()
1149 #ifdef WINDOWS_VST_SUPPORT
1150 if (!_windows_vst_plugin_info) {
1151 windows_vst_refresh ();
1153 return *_windows_vst_plugin_info;
1155 return _empty_plugin_info;
1159 ARDOUR::PluginInfoList&
1160 PluginManager::lxvst_plugin_info ()
1162 #ifdef LXVST_SUPPORT
1163 assert(_lxvst_plugin_info);
1164 return *_lxvst_plugin_info;
1166 return _empty_plugin_info;
1170 ARDOUR::PluginInfoList&
1171 PluginManager::ladspa_plugin_info ()
1173 assert(_ladspa_plugin_info);
1174 return *_ladspa_plugin_info;
1177 ARDOUR::PluginInfoList&
1178 PluginManager::lv2_plugin_info ()
1181 assert(_lv2_plugin_info);
1182 return *_lv2_plugin_info;
1184 return _empty_plugin_info;
1188 ARDOUR::PluginInfoList&
1189 PluginManager::au_plugin_info ()
1191 #ifdef AUDIOUNIT_SUPPORT
1192 if (_au_plugin_info) {
1193 return *_au_plugin_info;
1196 return _empty_plugin_info;