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 #ifdef AUDIOUNIT_SUPPORT
267 BootMessage (_("Scanning AU Plugins"));
269 BootMessage (_("Discovering AU Plugins"));
271 au_refresh (cache_only);
274 BootMessage (_("Plugin Scan Complete..."));
275 PluginListChanged (); /* EMIT SIGNAL */
276 PluginScanMessage(X_("closeme"), "", false);
277 _cancel_scan = false;
281 PluginManager::cancel_plugin_scan ()
287 PluginManager::cancel_plugin_timeout ()
289 _cancel_timeout = true;
293 PluginManager::clear_vst_cache ()
295 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
296 #ifdef WINDOWS_VST_SUPPORT
298 vector<string> fsi_files;
299 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
300 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
301 ::g_unlink(i->c_str());
305 vector<string> fsi_files;
306 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
307 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
308 ::g_unlink(i->c_str());
312 vector<string> fsi_files;
313 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
314 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
315 ::g_unlink(i->c_str());
322 vector<string> fsi_files;
323 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
324 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
325 ::g_unlink(i->c_str());
329 vector<string> fsi_files;
330 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
331 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
332 ::g_unlink(i->c_str());
336 vector<string> fsi_files;
337 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
338 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
339 ::g_unlink(i->c_str());
343 #endif // old cache cleanup
345 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
347 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
348 vector<string> fsi_files;
349 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
350 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
351 ::g_unlink(i->c_str());
358 PluginManager::clear_vst_blacklist ()
360 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
362 #ifdef WINDOWS_VST_SUPPORT
364 vector<string> fsi_files;
365 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
366 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
367 ::g_unlink(i->c_str());
374 vector<string> fsi_files;
375 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
376 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
377 ::g_unlink(i->c_str());
382 #endif // old blacklist cleanup
384 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
386 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
387 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
388 ::g_unlink (fn.c_str());
396 PluginManager::clear_au_cache ()
398 #ifdef AUDIOUNIT_SUPPORT
399 // AUPluginInfo::au_cache_path ()
400 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
401 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
402 ::g_unlink(fn.c_str());
408 PluginManager::clear_au_blacklist ()
410 #ifdef AUDIOUNIT_SUPPORT
411 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
412 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
413 ::g_unlink(fn.c_str());
419 PluginManager::ladspa_refresh ()
421 if (_ladspa_plugin_info) {
422 _ladspa_plugin_info->clear ();
424 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
427 /* allow LADSPA_PATH to augment, not override standard locations */
429 /* Only add standard locations to ladspa_path if it doesn't
430 * already contain them. Check for trailing G_DIR_SEPARATOR too.
433 vector<string> ladspa_modules;
435 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
437 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
438 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
439 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
441 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
442 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
443 ladspa_discover (*i);
448 static bool rdf_filter (const string &str, void* /*arg*/)
450 return str[0] != '.' &&
451 ((str.find(".rdf") == (str.length() - 4)) ||
452 (str.find(".rdfs") == (str.length() - 5)) ||
453 (str.find(".n3") == (str.length() - 3)) ||
454 (str.find(".ttl") == (str.length() - 4)));
459 PluginManager::add_ladspa_presets()
461 add_presets ("ladspa");
465 PluginManager::add_windows_vst_presets()
467 add_presets ("windows-vst");
471 PluginManager::add_lxvst_presets()
473 add_presets ("lxvst");
477 PluginManager::add_presets(string domain)
480 vector<string> presets;
481 vector<string>::iterator x;
484 if ((envvar = getenv ("HOME")) == 0) {
488 string path = string_compose("%1/.%2/rdf", envvar, domain);
489 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
491 for (x = presets.begin(); x != presets.end (); ++x) {
492 string file = "file:" + *x;
493 if (lrdf_read_file(file.c_str())) {
494 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
502 PluginManager::add_lrdf_data (const string &path)
505 vector<string> rdf_files;
506 vector<string>::iterator x;
508 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
510 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
511 const string uri(string("file://") + *x);
513 if (lrdf_read_file(uri.c_str())) {
514 warning << "Could not parse rdf file: " << uri << endmsg;
521 PluginManager::ladspa_discover (string path)
523 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
525 Glib::Module module(path);
526 const LADSPA_Descriptor *descriptor;
527 LADSPA_Descriptor_Function dfunc;
531 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
532 path, Glib::Module::get_last_error()) << endmsg;
537 if (!module.get_symbol("ladspa_descriptor", func)) {
538 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
539 error << Glib::Module::get_last_error() << endmsg;
543 dfunc = (LADSPA_Descriptor_Function)func;
545 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
547 for (uint32_t i = 0; ; ++i) {
548 if ((descriptor = dfunc (i)) == 0) {
552 if (!ladspa_plugin_whitelist.empty()) {
553 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
558 PluginInfoPtr info(new LadspaPluginInfo);
559 info->name = descriptor->Name;
560 info->category = get_ladspa_category(descriptor->UniqueID);
561 info->creator = descriptor->Maker;
564 info->n_inputs = ChanCount();
565 info->n_outputs = ChanCount();
566 info->type = ARDOUR::LADSPA;
569 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
570 info->unique_id = buf;
572 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
573 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
574 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
575 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
577 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
578 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
583 if(_ladspa_plugin_info->empty()){
584 _ladspa_plugin_info->push_back (info);
587 //Ensure that the plugin is not already in the plugin list.
591 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
592 if(0 == info->unique_id.compare((*i)->unique_id)){
598 _ladspa_plugin_info->push_back (info);
601 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
604 // GDB WILL NOT LIKE YOU IF YOU DO THIS
611 PluginManager::get_ladspa_category (uint32_t plugin_id)
615 lrdf_statement pattern;
617 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
618 pattern.subject = buf;
619 pattern.predicate = const_cast<char*>(RDF_TYPE);
621 pattern.object_type = lrdf_uri;
623 lrdf_statement* matches1 = lrdf_matches (&pattern);
629 pattern.subject = matches1->object;
630 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
632 pattern.object_type = lrdf_literal;
634 lrdf_statement* matches2 = lrdf_matches (&pattern);
635 lrdf_free_statements(matches1);
641 string label = matches2->object;
642 lrdf_free_statements(matches2);
644 /* Kludge LADSPA class names to be singular and match LV2 class names.
645 This avoids duplicate plugin menus for every class, which is necessary
646 to make the plugin category menu at all usable, but is obviously a
649 In the short term, lrdf could be updated so the labels match and a new
650 release made. To support both specs, we should probably be mapping the
651 URIs to the same category in code and perhaps tweaking that hierarchy
652 dynamically to suit the user. Personally, I (drobilla) think that time
653 is better spent replacing the little-used LRDF.
655 In the longer term, we will abandon LRDF entirely in favour of LV2 and
656 use that class hierarchy. Aside from fixing this problem properly, that
657 will also allow for translated labels. SWH plugins have been LV2 for
658 ages; TAP needs porting. I don't know of anything else with LRDF data.
660 if (label == "Utilities") {
662 } else if (label == "Pitch shifters") {
663 return "Pitch Shifter";
664 } else if (label != "Dynamics" && label != "Chorus"
665 &&label[label.length() - 1] == 's'
666 && label[label.length() - 2] != 's') {
667 return label.substr(0, label.length() - 1);
678 PluginManager::lv2_refresh ()
680 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
681 delete _lv2_plugin_info;
682 _lv2_plugin_info = LV2PluginInfo::discover();
686 #ifdef AUDIOUNIT_SUPPORT
688 PluginManager::au_refresh (bool cache_only)
690 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
692 // disable automatic discovery in case we crash
693 bool discover_at_start = Config->get_discover_audio_units ();
694 Config->set_discover_audio_units (false);
695 Config->save_state();
697 delete _au_plugin_info;
698 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
700 // successful scan re-enabled automatic discovery if it was set
701 Config->set_discover_audio_units (discover_at_start);
702 Config->save_state();
707 #ifdef WINDOWS_VST_SUPPORT
710 PluginManager::windows_vst_refresh (bool cache_only)
712 if (_windows_vst_plugin_info) {
713 _windows_vst_plugin_info->clear ();
715 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
718 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
721 static bool windows_vst_filter (const string& str, void * /*arg*/)
723 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
724 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
728 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
730 vector<string> plugin_objects;
731 vector<string>::iterator x;
734 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
736 if (Config->get_verbose_plugin_scan()) {
737 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
740 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
742 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
743 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
744 windows_vst_discover (*x, cache_only || cancelled());
747 if (Config->get_verbose_plugin_scan()) {
748 info << _("--- Windows VST plugins Scan Done") << endmsg;
755 PluginManager::windows_vst_discover (string path, bool cache_only)
757 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
759 if (Config->get_verbose_plugin_scan()) {
760 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
763 _cancel_timeout = false;
764 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
765 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
767 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
768 // .err file scanner output etc.
770 if (finfos->empty()) {
771 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
772 if (Config->get_verbose_plugin_scan()) {
773 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
778 uint32_t discovered = 0;
779 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
783 if (!finfo->canProcessReplacing) {
784 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
785 finfo->name, PROGRAM_NAME)
790 PluginInfoPtr info (new WindowsVSTPluginInfo);
792 /* what a joke freeware VST is */
794 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
795 info->name = PBD::basename_nosuffix (path);
797 info->name = finfo->name;
801 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
802 info->unique_id = buf;
803 info->category = "VST";
805 info->creator = finfo->creator;
807 info->n_inputs.set_audio (finfo->numInputs);
808 info->n_outputs.set_audio (finfo->numOutputs);
809 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
810 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
811 info->type = ARDOUR::Windows_VST;
813 // TODO: check dup-IDs (lxvst AND windows vst)
814 bool duplicate = false;
816 if (!_windows_vst_plugin_info->empty()) {
817 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
818 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
819 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
827 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
828 _windows_vst_plugin_info->push_back (info);
830 if (Config->get_verbose_plugin_scan()) {
831 PBD::info << string_compose (_(" -> OK. (VST Plugin \"%1\" added)."), info->name) << endmsg;
836 vstfx_free_info_list (finfos);
837 return discovered > 0 ? 0 : -1;
840 #endif // WINDOWS_VST_SUPPORT
845 PluginManager::lxvst_refresh (bool cache_only)
847 if (_lxvst_plugin_info) {
848 _lxvst_plugin_info->clear ();
850 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
853 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
856 static bool lxvst_filter (const string& str, void *)
858 /* Not a dotfile, has a prefix before a period, suffix is "so" */
860 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
864 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
866 vector<string> plugin_objects;
867 vector<string>::iterator x;
874 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
876 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
878 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
879 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
880 lxvst_discover (*x, cache_only || cancelled());
887 PluginManager::lxvst_discover (string path, bool cache_only)
889 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
891 _cancel_timeout = false;
892 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
893 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
895 if (finfos->empty()) {
896 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
900 uint32_t discovered = 0;
901 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
905 if (!finfo->canProcessReplacing) {
906 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
907 finfo->name, PROGRAM_NAME)
912 PluginInfoPtr info(new LXVSTPluginInfo);
914 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
915 info->name = PBD::basename_nosuffix (path);
917 info->name = finfo->name;
921 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
922 info->unique_id = buf;
923 info->category = "linuxVSTs";
925 info->creator = finfo->creator;
927 info->n_inputs.set_audio (finfo->numInputs);
928 info->n_outputs.set_audio (finfo->numOutputs);
929 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
930 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
931 info->type = ARDOUR::LXVST;
933 /* Make sure we don't find the same plugin in more than one place along
934 the LXVST_PATH We can't use a simple 'find' because the path is included
935 in the PluginInfo, and that is the one thing we can be sure MUST be
936 different if a duplicate instance is found. So we just compare the type
937 and unique ID (which for some VSTs isn't actually unique...)
940 // TODO: check dup-IDs with windowsVST, too
941 bool duplicate = false;
942 if (!_lxvst_plugin_info->empty()) {
943 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
944 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
945 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
953 _lxvst_plugin_info->push_back (info);
958 vstfx_free_info_list (finfos);
959 return discovered > 0 ? 0 : -1;
962 #endif // LXVST_SUPPORT
965 PluginManager::PluginStatusType
966 PluginManager::get_status (const PluginInfoPtr& pi)
968 PluginStatus ps (pi->type, pi->unique_id);
969 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
970 if (i == statuses.end() ) {
978 PluginManager::save_statuses ()
981 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
983 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
989 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1001 ofs << "Windows-VST";
1010 switch ((*i).status) {
1023 ofs << (*i).unique_id;;
1031 PluginManager::load_statuses ()
1033 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1034 ifstream ifs (path.c_str());
1041 std::string sstatus;
1044 PluginStatusType status;
1061 /* rest of the line is the plugin ID */
1063 ifs.getline (buf, sizeof (buf), '\n');
1068 if (sstatus == "Normal") {
1070 } else if (sstatus == "Favorite") {
1072 } else if (sstatus == "Hidden") {
1075 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1081 if (stype == "LADSPA") {
1083 } else if (stype == "AudioUnit") {
1085 } else if (stype == "LV2") {
1087 } else if (stype == "Windows-VST") {
1089 } else if (stype == "LXVST") {
1092 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1098 strip_whitespace_edges (id);
1099 set_status (type, id, status);
1106 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1108 PluginStatus ps (t, id, status);
1109 statuses.erase (ps);
1111 if (status == Normal) {
1115 statuses.insert (ps);
1118 ARDOUR::PluginInfoList&
1119 PluginManager::windows_vst_plugin_info ()
1121 #ifdef WINDOWS_VST_SUPPORT
1122 if (!_windows_vst_plugin_info) {
1123 windows_vst_refresh ();
1125 return *_windows_vst_plugin_info;
1127 return _empty_plugin_info;
1131 ARDOUR::PluginInfoList&
1132 PluginManager::lxvst_plugin_info ()
1134 #ifdef LXVST_SUPPORT
1135 assert(_lxvst_plugin_info);
1136 return *_lxvst_plugin_info;
1138 return _empty_plugin_info;
1142 ARDOUR::PluginInfoList&
1143 PluginManager::ladspa_plugin_info ()
1145 assert(_ladspa_plugin_info);
1146 return *_ladspa_plugin_info;
1149 ARDOUR::PluginInfoList&
1150 PluginManager::lv2_plugin_info ()
1153 assert(_lv2_plugin_info);
1154 return *_lv2_plugin_info;
1156 return _empty_plugin_info;
1160 ARDOUR::PluginInfoList&
1161 PluginManager::au_plugin_info ()
1163 #ifdef AUDIOUNIT_SUPPORT
1164 if (_au_plugin_info) {
1165 return *_au_plugin_info;
1168 return _empty_plugin_info;