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"
42 #endif // WINDOWS_VST_SUPPORT
45 #include "ardour/vst_info_file.h"
46 #include "ardour/linux_vst_support.h"
47 #include "pbd/basename.h"
49 #endif //LXVST_SUPPORT
51 #include <glibmm/miscutils.h>
52 #include <glibmm/pattern.h>
53 #include <glibmm/fileutils.h>
54 #include <glibmm/miscutils.h>
56 #include "pbd/whitespace.h"
57 #include "pbd/file_utils.h"
59 #include "ardour/debug.h"
60 #include "ardour/filesystem_paths.h"
61 #include "ardour/ladspa.h"
62 #include "ardour/ladspa_plugin.h"
63 #include "ardour/plugin.h"
64 #include "ardour/plugin_manager.h"
65 #include "ardour/rc_configuration.h"
67 #include "ardour/search_paths.h"
70 #include "ardour/lv2_plugin.h"
73 #ifdef WINDOWS_VST_SUPPORT
74 #include "ardour/windows_vst_plugin.h"
78 #include "ardour/lxvst_plugin.h"
81 #ifdef AUDIOUNIT_SUPPORT
82 #include "ardour/audio_unit.h"
83 #include <Carbon/Carbon.h>
86 #include "pbd/error.h"
87 #include "pbd/stl_delete.h"
91 #include "ardour/debug.h"
93 using namespace ARDOUR;
97 PluginManager* PluginManager::_instance = 0;
98 std::string PluginManager::scanner_bin_path = "";
101 PluginManager::instance()
104 _instance = new PluginManager;
109 PluginManager::PluginManager ()
110 : _windows_vst_plugin_info(0)
111 , _lxvst_plugin_info(0)
112 , _ladspa_plugin_info(0)
113 , _lv2_plugin_info(0)
115 , _cancel_scan(false)
116 , _cancel_timeout(false)
121 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
122 // source-tree (ardev, etc)
123 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
125 #ifdef PLATFORM_WINDOWS
126 // on windows the .exe needs to be in the same folder with libardour.dll
127 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
129 // on Unices additional internal-use binaries are deployed to $libdir
130 vstsp += ARDOUR::ardour_dll_directory();
133 if (!PBD::find_file (vstsp,
134 #ifdef PLATFORM_WINDOWS
135 #ifdef DEBUGGABLE_SCANNER_APP
136 #if defined(DEBUG) || defined(_DEBUG)
137 "ardour-vst-scannerD.exe"
139 "ardour-vst-scannerRDC.exe"
142 "ardour-vst-scanner.exe"
147 , scanner_bin_path)) {
148 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
154 if ((s = getenv ("LADSPA_RDF_PATH"))){
158 if (lrdf_path.length() == 0) {
159 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
162 add_lrdf_data(lrdf_path);
163 add_ladspa_presets();
164 #ifdef WINDOWS_VST_SUPPORT
165 if (Config->get_use_windows_vst ()) {
166 add_windows_vst_presets ();
168 #endif /* WINDOWS_VST_SUPPORT */
171 if (Config->get_use_lxvst()) {
174 #endif /* Native LinuxVST support*/
176 if ((s = getenv ("VST_PATH"))) {
177 windows_vst_path = s;
178 } else if ((s = getenv ("VST_PLUGINS"))) {
179 windows_vst_path = s;
182 if (windows_vst_path.length() == 0) {
183 windows_vst_path = vst_search_path ();
186 if ((s = getenv ("LXVST_PATH"))) {
188 } else if ((s = getenv ("LXVST_PLUGINS"))) {
192 if (lxvst_path.length() == 0) {
193 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
194 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
195 "/usr/lib/vst:/usr/local/lib/vst";
198 /* first time setup, use 'default' path */
199 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
200 Config->set_plugin_path_lxvst(get_default_lxvst_path());
202 if (Config->get_plugin_path_vst() == X_("@default@")) {
203 Config->set_plugin_path_vst(get_default_windows_vst_path());
206 if (_instance == 0) {
210 BootMessage (_("Discovering Plugins"));
214 PluginManager::~PluginManager()
216 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
217 // don't bother, just exit quickly.
218 delete _windows_vst_plugin_info;
219 delete _lxvst_plugin_info;
220 delete _ladspa_plugin_info;
221 delete _lv2_plugin_info;
222 delete _au_plugin_info;
227 PluginManager::refresh (bool cache_only)
229 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
235 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
236 _cancel_scan = false;
238 BootMessage (_("Scanning LADSPA Plugins"));
241 BootMessage (_("Scanning LV2 Plugins"));
244 #ifdef WINDOWS_VST_SUPPORT
245 if (Config->get_use_windows_vst()) {
247 BootMessage (_("Scanning Windows VST Plugins"));
249 BootMessage (_("Discovering Windows VST Plugins"));
251 windows_vst_refresh (cache_only);
253 #endif // WINDOWS_VST_SUPPORT
256 if(Config->get_use_lxvst()) {
258 BootMessage (_("Scanning Linux VST Plugins"));
260 BootMessage (_("Discovering Linux VST Plugins"));
262 lxvst_refresh(cache_only);
264 #endif //Native linuxVST SUPPORT
266 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
268 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
269 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
271 if (g_file_get_contents(fn.c_str (), bl, NULL, NULL)) {
272 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
279 #ifdef AUDIOUNIT_SUPPORT
281 BootMessage (_("Scanning AU Plugins"));
283 BootMessage (_("Discovering AU Plugins"));
285 au_refresh (cache_only);
288 BootMessage (_("Plugin Scan Complete..."));
289 PluginListChanged (); /* EMIT SIGNAL */
290 PluginScanMessage(X_("closeme"), "", false);
291 _cancel_scan = false;
295 PluginManager::cancel_plugin_scan ()
301 PluginManager::cancel_plugin_timeout ()
303 _cancel_timeout = true;
307 PluginManager::clear_vst_cache ()
309 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
310 #ifdef WINDOWS_VST_SUPPORT
312 vector<string> fsi_files;
313 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
314 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
315 ::g_unlink(i->c_str());
319 vector<string> fsi_files;
320 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
321 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
322 ::g_unlink(i->c_str());
326 vector<string> fsi_files;
327 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
328 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
329 ::g_unlink(i->c_str());
336 vector<string> fsi_files;
337 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
338 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
339 ::g_unlink(i->c_str());
343 vector<string> fsi_files;
344 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
345 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
346 ::g_unlink(i->c_str());
350 vector<string> fsi_files;
351 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
352 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
353 ::g_unlink(i->c_str());
357 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
359 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
360 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
361 PBD::remove_directory (dir);
365 #endif // old cache cleanup
367 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
369 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
370 vector<string> fsi_files;
371 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
372 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
373 ::g_unlink(i->c_str());
380 PluginManager::clear_vst_blacklist ()
382 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
384 #ifdef WINDOWS_VST_SUPPORT
386 vector<string> fsi_files;
387 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
388 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
389 ::g_unlink(i->c_str());
396 vector<string> fsi_files;
397 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", 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_blacklist");
406 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
407 PBD::remove_directory (dir);
412 #endif // old blacklist cleanup
414 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
416 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
417 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
418 ::g_unlink (fn.c_str());
426 PluginManager::clear_au_cache ()
428 #ifdef AUDIOUNIT_SUPPORT
429 // AUPluginInfo::au_cache_path ()
430 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
431 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
432 ::g_unlink(fn.c_str());
438 PluginManager::clear_au_blacklist ()
440 #ifdef AUDIOUNIT_SUPPORT
441 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
442 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
443 ::g_unlink(fn.c_str());
449 PluginManager::ladspa_refresh ()
451 if (_ladspa_plugin_info) {
452 _ladspa_plugin_info->clear ();
454 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
457 /* allow LADSPA_PATH to augment, not override standard locations */
459 /* Only add standard locations to ladspa_path if it doesn't
460 * already contain them. Check for trailing G_DIR_SEPARATOR too.
463 vector<string> ladspa_modules;
465 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
467 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
468 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
469 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
471 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
472 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
473 ladspa_discover (*i);
478 static bool rdf_filter (const string &str, void* /*arg*/)
480 return str[0] != '.' &&
481 ((str.find(".rdf") == (str.length() - 4)) ||
482 (str.find(".rdfs") == (str.length() - 5)) ||
483 (str.find(".n3") == (str.length() - 3)) ||
484 (str.find(".ttl") == (str.length() - 4)));
489 PluginManager::add_ladspa_presets()
491 add_presets ("ladspa");
495 PluginManager::add_windows_vst_presets()
497 add_presets ("windows-vst");
501 PluginManager::add_lxvst_presets()
503 add_presets ("lxvst");
507 PluginManager::add_presets(string domain)
510 vector<string> presets;
511 vector<string>::iterator x;
514 if ((envvar = getenv ("HOME")) == 0) {
518 string path = string_compose("%1/.%2/rdf", envvar, domain);
519 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
521 for (x = presets.begin(); x != presets.end (); ++x) {
522 string file = "file:" + *x;
523 if (lrdf_read_file(file.c_str())) {
524 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
532 PluginManager::add_lrdf_data (const string &path)
535 vector<string> rdf_files;
536 vector<string>::iterator x;
538 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
540 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
541 const string uri(string("file://") + *x);
543 if (lrdf_read_file(uri.c_str())) {
544 warning << "Could not parse rdf file: " << uri << endmsg;
551 PluginManager::ladspa_discover (string path)
553 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
555 Glib::Module module(path);
556 const LADSPA_Descriptor *descriptor;
557 LADSPA_Descriptor_Function dfunc;
561 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
562 path, Glib::Module::get_last_error()) << endmsg;
567 if (!module.get_symbol("ladspa_descriptor", func)) {
568 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
569 error << Glib::Module::get_last_error() << endmsg;
573 dfunc = (LADSPA_Descriptor_Function)func;
575 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
577 for (uint32_t i = 0; ; ++i) {
578 if ((descriptor = dfunc (i)) == 0) {
582 if (!ladspa_plugin_whitelist.empty()) {
583 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
588 PluginInfoPtr info(new LadspaPluginInfo);
589 info->name = descriptor->Name;
590 info->category = get_ladspa_category(descriptor->UniqueID);
591 info->creator = descriptor->Maker;
594 info->n_inputs = ChanCount();
595 info->n_outputs = ChanCount();
596 info->type = ARDOUR::LADSPA;
599 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
600 info->unique_id = buf;
602 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
603 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
604 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
605 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
607 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
608 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
613 if(_ladspa_plugin_info->empty()){
614 _ladspa_plugin_info->push_back (info);
617 //Ensure that the plugin is not already in the plugin list.
621 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
622 if(0 == info->unique_id.compare((*i)->unique_id)){
628 _ladspa_plugin_info->push_back (info);
631 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
634 // GDB WILL NOT LIKE YOU IF YOU DO THIS
641 PluginManager::get_ladspa_category (uint32_t plugin_id)
645 lrdf_statement pattern;
647 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
648 pattern.subject = buf;
649 pattern.predicate = const_cast<char*>(RDF_TYPE);
651 pattern.object_type = lrdf_uri;
653 lrdf_statement* matches1 = lrdf_matches (&pattern);
659 pattern.subject = matches1->object;
660 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
662 pattern.object_type = lrdf_literal;
664 lrdf_statement* matches2 = lrdf_matches (&pattern);
665 lrdf_free_statements(matches1);
671 string label = matches2->object;
672 lrdf_free_statements(matches2);
674 /* Kludge LADSPA class names to be singular and match LV2 class names.
675 This avoids duplicate plugin menus for every class, which is necessary
676 to make the plugin category menu at all usable, but is obviously a
679 In the short term, lrdf could be updated so the labels match and a new
680 release made. To support both specs, we should probably be mapping the
681 URIs to the same category in code and perhaps tweaking that hierarchy
682 dynamically to suit the user. Personally, I (drobilla) think that time
683 is better spent replacing the little-used LRDF.
685 In the longer term, we will abandon LRDF entirely in favour of LV2 and
686 use that class hierarchy. Aside from fixing this problem properly, that
687 will also allow for translated labels. SWH plugins have been LV2 for
688 ages; TAP needs porting. I don't know of anything else with LRDF data.
690 if (label == "Utilities") {
692 } else if (label == "Pitch shifters") {
693 return "Pitch Shifter";
694 } else if (label != "Dynamics" && label != "Chorus"
695 &&label[label.length() - 1] == 's'
696 && label[label.length() - 2] != 's') {
697 return label.substr(0, label.length() - 1);
708 PluginManager::lv2_refresh ()
710 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
711 delete _lv2_plugin_info;
712 _lv2_plugin_info = LV2PluginInfo::discover();
716 #ifdef AUDIOUNIT_SUPPORT
718 PluginManager::au_refresh (bool cache_only)
720 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
722 // disable automatic discovery in case we crash
723 bool discover_at_start = Config->get_discover_audio_units ();
724 Config->set_discover_audio_units (false);
725 Config->save_state();
727 delete _au_plugin_info;
728 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
730 // successful scan re-enabled automatic discovery if it was set
731 Config->set_discover_audio_units (discover_at_start);
732 Config->save_state();
737 #ifdef WINDOWS_VST_SUPPORT
740 PluginManager::windows_vst_refresh (bool cache_only)
742 if (_windows_vst_plugin_info) {
743 _windows_vst_plugin_info->clear ();
745 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
748 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
751 static bool windows_vst_filter (const string& str, void * /*arg*/)
753 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
754 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
758 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
760 vector<string> plugin_objects;
761 vector<string>::iterator x;
764 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
766 if (Config->get_verbose_plugin_scan()) {
767 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
770 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
772 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
773 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
774 windows_vst_discover (*x, cache_only || cancelled());
777 if (Config->get_verbose_plugin_scan()) {
778 info << _("--- Windows VST plugins Scan Done") << endmsg;
785 PluginManager::windows_vst_discover (string path, bool cache_only)
787 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
789 if (Config->get_verbose_plugin_scan()) {
790 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
793 _cancel_timeout = false;
794 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
795 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
797 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
798 // .err file scanner output etc.
800 if (finfos->empty()) {
801 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
802 if (Config->get_verbose_plugin_scan()) {
803 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
808 uint32_t discovered = 0;
809 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
813 if (!finfo->canProcessReplacing) {
814 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
815 finfo->name, PROGRAM_NAME)
820 PluginInfoPtr info (new WindowsVSTPluginInfo);
822 /* what a joke freeware VST is */
824 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
825 info->name = PBD::basename_nosuffix (path);
827 info->name = finfo->name;
831 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
832 info->unique_id = buf;
833 info->category = "VST";
835 info->creator = finfo->creator;
837 info->n_inputs.set_audio (finfo->numInputs);
838 info->n_outputs.set_audio (finfo->numOutputs);
839 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
840 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
841 info->type = ARDOUR::Windows_VST;
843 // TODO: check dup-IDs (lxvst AND windows vst)
844 bool duplicate = false;
846 if (!_windows_vst_plugin_info->empty()) {
847 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
848 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
849 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
857 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
858 _windows_vst_plugin_info->push_back (info);
860 if (Config->get_verbose_plugin_scan()) {
861 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
866 vstfx_free_info_list (finfos);
867 return discovered > 0 ? 0 : -1;
870 #endif // WINDOWS_VST_SUPPORT
875 PluginManager::lxvst_refresh (bool cache_only)
877 if (_lxvst_plugin_info) {
878 _lxvst_plugin_info->clear ();
880 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
883 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
886 static bool lxvst_filter (const string& str, void *)
888 /* Not a dotfile, has a prefix before a period, suffix is "so" */
890 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
894 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
896 vector<string> plugin_objects;
897 vector<string>::iterator x;
904 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
906 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
908 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
909 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
910 lxvst_discover (*x, cache_only || cancelled());
917 PluginManager::lxvst_discover (string path, bool cache_only)
919 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
921 _cancel_timeout = false;
922 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
923 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
925 if (finfos->empty()) {
926 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
930 uint32_t discovered = 0;
931 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
935 if (!finfo->canProcessReplacing) {
936 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
937 finfo->name, PROGRAM_NAME)
942 PluginInfoPtr info(new LXVSTPluginInfo);
944 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
945 info->name = PBD::basename_nosuffix (path);
947 info->name = finfo->name;
951 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
952 info->unique_id = buf;
953 info->category = "linuxVSTs";
955 info->creator = finfo->creator;
957 info->n_inputs.set_audio (finfo->numInputs);
958 info->n_outputs.set_audio (finfo->numOutputs);
959 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
960 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
961 info->type = ARDOUR::LXVST;
963 /* Make sure we don't find the same plugin in more than one place along
964 the LXVST_PATH We can't use a simple 'find' because the path is included
965 in the PluginInfo, and that is the one thing we can be sure MUST be
966 different if a duplicate instance is found. So we just compare the type
967 and unique ID (which for some VSTs isn't actually unique...)
970 // TODO: check dup-IDs with windowsVST, too
971 bool duplicate = false;
972 if (!_lxvst_plugin_info->empty()) {
973 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
974 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
975 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
983 _lxvst_plugin_info->push_back (info);
988 vstfx_free_info_list (finfos);
989 return discovered > 0 ? 0 : -1;
992 #endif // LXVST_SUPPORT
995 PluginManager::PluginStatusType
996 PluginManager::get_status (const PluginInfoPtr& pi)
998 PluginStatus ps (pi->type, pi->unique_id);
999 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1000 if (i == statuses.end() ) {
1008 PluginManager::save_statuses ()
1010 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1013 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1014 switch ((*i).type) {
1025 ofs << "Windows-VST";
1034 switch ((*i).status) {
1047 ofs << (*i).unique_id;;
1050 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1054 PluginManager::load_statuses ()
1056 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1058 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1061 stringstream ifs (fbuf);
1065 std::string sstatus;
1068 PluginStatusType status;
1085 /* rest of the line is the plugin ID */
1087 ifs.getline (buf, sizeof (buf), '\n');
1092 if (sstatus == "Normal") {
1094 } else if (sstatus == "Favorite") {
1096 } else if (sstatus == "Hidden") {
1099 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1105 if (stype == "LADSPA") {
1107 } else if (stype == "AudioUnit") {
1109 } else if (stype == "LV2") {
1111 } else if (stype == "Windows-VST") {
1113 } else if (stype == "LXVST") {
1116 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1122 strip_whitespace_edges (id);
1123 set_status (type, id, status);
1128 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1130 PluginStatus ps (t, id, status);
1131 statuses.erase (ps);
1133 if (status == Normal) {
1137 statuses.insert (ps);
1140 ARDOUR::PluginInfoList&
1141 PluginManager::windows_vst_plugin_info ()
1143 #ifdef WINDOWS_VST_SUPPORT
1144 if (!_windows_vst_plugin_info) {
1145 windows_vst_refresh ();
1147 return *_windows_vst_plugin_info;
1149 return _empty_plugin_info;
1153 ARDOUR::PluginInfoList&
1154 PluginManager::lxvst_plugin_info ()
1156 #ifdef LXVST_SUPPORT
1157 assert(_lxvst_plugin_info);
1158 return *_lxvst_plugin_info;
1160 return _empty_plugin_info;
1164 ARDOUR::PluginInfoList&
1165 PluginManager::ladspa_plugin_info ()
1167 assert(_ladspa_plugin_info);
1168 return *_ladspa_plugin_info;
1171 ARDOUR::PluginInfoList&
1172 PluginManager::lv2_plugin_info ()
1175 assert(_lv2_plugin_info);
1176 return *_lv2_plugin_info;
1178 return _empty_plugin_info;
1182 ARDOUR::PluginInfoList&
1183 PluginManager::au_plugin_info ()
1185 #ifdef AUDIOUNIT_SUPPORT
1186 if (_au_plugin_info) {
1187 return *_au_plugin_info;
1190 return _empty_plugin_info;