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>
32 #include <pbd/gstdio_compat.h>
38 #ifdef WINDOWS_VST_SUPPORT
39 #include "ardour/vst_info_file.h"
41 #include "pbd/basename.h"
43 #endif // WINDOWS_VST_SUPPORT
46 #include "ardour/vst_info_file.h"
47 #include "ardour/linux_vst_support.h"
48 #include "pbd/basename.h"
50 #endif //LXVST_SUPPORT
52 #include <pbd/gstdio_compat.h>
53 #include <glibmm/miscutils.h>
54 #include <glibmm/pattern.h>
55 #include <glibmm/fileutils.h>
56 #include <glibmm/miscutils.h>
58 #include "pbd/whitespace.h"
59 #include "pbd/file_utils.h"
61 #include "ardour/debug.h"
62 #include "ardour/filesystem_paths.h"
63 #include "ardour/ladspa.h"
64 #include "ardour/ladspa_plugin.h"
65 #include "ardour/plugin.h"
66 #include "ardour/plugin_manager.h"
67 #include "ardour/rc_configuration.h"
69 #include "ardour/search_paths.h"
72 #include "ardour/lv2_plugin.h"
75 #ifdef WINDOWS_VST_SUPPORT
76 #include "ardour/windows_vst_plugin.h"
80 #include "ardour/lxvst_plugin.h"
83 #ifdef AUDIOUNIT_SUPPORT
84 #include "ardour/audio_unit.h"
85 #include <Carbon/Carbon.h>
88 #include "pbd/error.h"
89 #include "pbd/stl_delete.h"
93 #include "ardour/debug.h"
95 using namespace ARDOUR;
99 PluginManager* PluginManager::_instance = 0;
100 std::string PluginManager::scanner_bin_path = "";
103 PluginManager::instance()
106 _instance = new PluginManager;
111 PluginManager::PluginManager ()
112 : _windows_vst_plugin_info(0)
113 , _lxvst_plugin_info(0)
114 , _ladspa_plugin_info(0)
115 , _lv2_plugin_info(0)
117 , _cancel_scan(false)
118 , _cancel_timeout(false)
123 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
124 // source-tree (ardev, etc)
125 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
127 #ifdef PLATFORM_WINDOWS
128 // on windows the .exe needs to be in the same folder with libardour.dll
129 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
131 // on Unices additional internal-use binaries are deployed to $libdir
132 vstsp += ARDOUR::ardour_dll_directory();
135 if (!PBD::find_file (vstsp,
136 #ifdef PLATFORM_WINDOWS
137 #ifdef DEBUGGABLE_SCANNER_APP
138 #if defined(DEBUG) || defined(_DEBUG)
139 "ardour-vst-scannerD.exe"
141 "ardour-vst-scannerRDC.exe"
144 "ardour-vst-scanner.exe"
149 , scanner_bin_path)) {
150 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
156 if ((s = getenv ("LADSPA_RDF_PATH"))){
160 if (lrdf_path.length() == 0) {
161 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
164 add_lrdf_data(lrdf_path);
165 add_ladspa_presets();
166 #ifdef WINDOWS_VST_SUPPORT
167 if (Config->get_use_windows_vst ()) {
168 add_windows_vst_presets ();
170 #endif /* WINDOWS_VST_SUPPORT */
173 if (Config->get_use_lxvst()) {
176 #endif /* Native LinuxVST support*/
178 if ((s = getenv ("VST_PATH"))) {
179 windows_vst_path = s;
180 } else if ((s = getenv ("VST_PLUGINS"))) {
181 windows_vst_path = s;
184 if (windows_vst_path.length() == 0) {
185 windows_vst_path = vst_search_path ();
188 if ((s = getenv ("LXVST_PATH"))) {
190 } else if ((s = getenv ("LXVST_PLUGINS"))) {
194 if (lxvst_path.length() == 0) {
195 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
196 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
197 "/usr/lib/vst:/usr/local/lib/vst";
200 /* first time setup, use 'default' path */
201 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
202 Config->set_plugin_path_lxvst(get_default_lxvst_path());
204 if (Config->get_plugin_path_vst() == X_("@default@")) {
205 Config->set_plugin_path_vst(get_default_windows_vst_path());
208 if (_instance == 0) {
212 BootMessage (_("Discovering Plugins"));
216 PluginManager::~PluginManager()
218 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
219 // don't bother, just exit quickly.
220 delete _windows_vst_plugin_info;
221 delete _lxvst_plugin_info;
222 delete _ladspa_plugin_info;
223 delete _lv2_plugin_info;
224 delete _au_plugin_info;
229 PluginManager::refresh (bool cache_only)
231 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
237 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
238 _cancel_scan = false;
240 BootMessage (_("Scanning LADSPA Plugins"));
243 BootMessage (_("Scanning LV2 Plugins"));
246 #ifdef WINDOWS_VST_SUPPORT
247 if (Config->get_use_windows_vst()) {
249 BootMessage (_("Scanning Windows VST Plugins"));
251 BootMessage (_("Discovering Windows VST Plugins"));
253 windows_vst_refresh (cache_only);
255 #endif // WINDOWS_VST_SUPPORT
258 if(Config->get_use_lxvst()) {
260 BootMessage (_("Scanning Linux VST Plugins"));
262 BootMessage (_("Discovering Linux VST Plugins"));
264 lxvst_refresh(cache_only);
266 #endif //Native linuxVST SUPPORT
268 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
270 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
271 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
273 if (g_file_get_contents(fn.c_str (), contents, NULL, NULL)) {
274 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
281 #ifdef AUDIOUNIT_SUPPORT
283 BootMessage (_("Scanning AU Plugins"));
285 BootMessage (_("Discovering AU Plugins"));
287 au_refresh (cache_only);
290 BootMessage (_("Plugin Scan Complete..."));
291 PluginListChanged (); /* EMIT SIGNAL */
292 PluginScanMessage(X_("closeme"), "", false);
293 _cancel_scan = false;
297 PluginManager::cancel_plugin_scan ()
303 PluginManager::cancel_plugin_timeout ()
305 _cancel_timeout = true;
309 PluginManager::clear_vst_cache ()
311 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
312 #ifdef WINDOWS_VST_SUPPORT
314 vector<string> fsi_files;
315 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
316 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
317 ::g_unlink(i->c_str());
321 vector<string> fsi_files;
322 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
323 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
324 ::g_unlink(i->c_str());
328 vector<string> fsi_files;
329 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
330 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
331 ::g_unlink(i->c_str());
338 vector<string> fsi_files;
339 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
340 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
341 ::g_unlink(i->c_str());
345 vector<string> fsi_files;
346 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
347 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
348 ::g_unlink(i->c_str());
352 vector<string> fsi_files;
353 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
354 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
355 ::g_unlink(i->c_str());
359 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
361 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
362 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
363 PBD::remove_directory (dir);
367 #endif // old cache cleanup
369 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
371 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
372 vector<string> fsi_files;
373 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
374 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
375 ::g_unlink(i->c_str());
382 PluginManager::clear_vst_blacklist ()
384 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
386 #ifdef WINDOWS_VST_SUPPORT
388 vector<string> fsi_files;
389 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
390 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
391 ::g_unlink(i->c_str());
398 vector<string> fsi_files;
399 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
400 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
401 ::g_unlink(i->c_str());
405 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
407 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
408 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
409 PBD::remove_directory (dir);
414 #endif // old blacklist cleanup
416 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
418 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
419 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
420 ::g_unlink (fn.c_str());
428 PluginManager::clear_au_cache ()
430 #ifdef AUDIOUNIT_SUPPORT
431 // AUPluginInfo::au_cache_path ()
432 string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
433 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
434 ::g_unlink(fn.c_str());
440 PluginManager::clear_au_blacklist ()
442 #ifdef AUDIOUNIT_SUPPORT
443 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
444 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
445 ::g_unlink(fn.c_str());
451 PluginManager::ladspa_refresh ()
453 if (_ladspa_plugin_info) {
454 _ladspa_plugin_info->clear ();
456 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
459 /* allow LADSPA_PATH to augment, not override standard locations */
461 /* Only add standard locations to ladspa_path if it doesn't
462 * already contain them. Check for trailing G_DIR_SEPARATOR too.
465 vector<string> ladspa_modules;
467 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
469 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
470 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
471 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
473 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
474 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
475 ladspa_discover (*i);
480 static bool rdf_filter (const string &str, void* /*arg*/)
482 return str[0] != '.' &&
483 ((str.find(".rdf") == (str.length() - 4)) ||
484 (str.find(".rdfs") == (str.length() - 5)) ||
485 (str.find(".n3") == (str.length() - 3)) ||
486 (str.find(".ttl") == (str.length() - 4)));
491 PluginManager::add_ladspa_presets()
493 add_presets ("ladspa");
497 PluginManager::add_windows_vst_presets()
499 add_presets ("windows-vst");
503 PluginManager::add_lxvst_presets()
505 add_presets ("lxvst");
509 PluginManager::add_presets(string domain)
512 vector<string> presets;
513 vector<string>::iterator x;
516 if ((envvar = getenv ("HOME")) == 0) {
520 string path = string_compose("%1/.%2/rdf", envvar, domain);
521 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
523 for (x = presets.begin(); x != presets.end (); ++x) {
524 string file = "file:" + *x;
525 if (lrdf_read_file(file.c_str())) {
526 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
534 PluginManager::add_lrdf_data (const string &path)
537 vector<string> rdf_files;
538 vector<string>::iterator x;
540 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
542 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
543 const string uri(string("file://") + *x);
545 if (lrdf_read_file(uri.c_str())) {
546 warning << "Could not parse rdf file: " << uri << endmsg;
553 PluginManager::ladspa_discover (string path)
555 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
557 Glib::Module module(path);
558 const LADSPA_Descriptor *descriptor;
559 LADSPA_Descriptor_Function dfunc;
563 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
564 path, Glib::Module::get_last_error()) << endmsg;
569 if (!module.get_symbol("ladspa_descriptor", func)) {
570 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
571 error << Glib::Module::get_last_error() << endmsg;
575 dfunc = (LADSPA_Descriptor_Function)func;
577 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
579 for (uint32_t i = 0; ; ++i) {
580 if ((descriptor = dfunc (i)) == 0) {
584 if (!ladspa_plugin_whitelist.empty()) {
585 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
590 PluginInfoPtr info(new LadspaPluginInfo);
591 info->name = descriptor->Name;
592 info->category = get_ladspa_category(descriptor->UniqueID);
593 info->creator = descriptor->Maker;
596 info->n_inputs = ChanCount();
597 info->n_outputs = ChanCount();
598 info->type = ARDOUR::LADSPA;
601 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
602 info->unique_id = buf;
604 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
605 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
606 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
607 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
609 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
610 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
615 if(_ladspa_plugin_info->empty()){
616 _ladspa_plugin_info->push_back (info);
619 //Ensure that the plugin is not already in the plugin list.
623 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
624 if(0 == info->unique_id.compare((*i)->unique_id)){
630 _ladspa_plugin_info->push_back (info);
633 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
636 // GDB WILL NOT LIKE YOU IF YOU DO THIS
643 PluginManager::get_ladspa_category (uint32_t plugin_id)
647 lrdf_statement pattern;
649 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
650 pattern.subject = buf;
651 pattern.predicate = const_cast<char*>(RDF_TYPE);
653 pattern.object_type = lrdf_uri;
655 lrdf_statement* matches1 = lrdf_matches (&pattern);
661 pattern.subject = matches1->object;
662 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
664 pattern.object_type = lrdf_literal;
666 lrdf_statement* matches2 = lrdf_matches (&pattern);
667 lrdf_free_statements(matches1);
673 string label = matches2->object;
674 lrdf_free_statements(matches2);
676 /* Kludge LADSPA class names to be singular and match LV2 class names.
677 This avoids duplicate plugin menus for every class, which is necessary
678 to make the plugin category menu at all usable, but is obviously a
681 In the short term, lrdf could be updated so the labels match and a new
682 release made. To support both specs, we should probably be mapping the
683 URIs to the same category in code and perhaps tweaking that hierarchy
684 dynamically to suit the user. Personally, I (drobilla) think that time
685 is better spent replacing the little-used LRDF.
687 In the longer term, we will abandon LRDF entirely in favour of LV2 and
688 use that class hierarchy. Aside from fixing this problem properly, that
689 will also allow for translated labels. SWH plugins have been LV2 for
690 ages; TAP needs porting. I don't know of anything else with LRDF data.
692 if (label == "Utilities") {
694 } else if (label == "Pitch shifters") {
695 return "Pitch Shifter";
696 } else if (label != "Dynamics" && label != "Chorus"
697 &&label[label.length() - 1] == 's'
698 && label[label.length() - 2] != 's') {
699 return label.substr(0, label.length() - 1);
710 PluginManager::lv2_refresh ()
712 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
713 delete _lv2_plugin_info;
714 _lv2_plugin_info = LV2PluginInfo::discover();
718 #ifdef AUDIOUNIT_SUPPORT
720 PluginManager::au_refresh (bool cache_only)
722 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
724 // disable automatic discovery in case we crash
725 bool discover_at_start = Config->get_discover_audio_units ();
726 Config->set_discover_audio_units (false);
727 Config->save_state();
729 delete _au_plugin_info;
730 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
732 // successful scan re-enabled automatic discovery if it was set
733 Config->set_discover_audio_units (discover_at_start);
734 Config->save_state();
739 #ifdef WINDOWS_VST_SUPPORT
742 PluginManager::windows_vst_refresh (bool cache_only)
744 if (_windows_vst_plugin_info) {
745 _windows_vst_plugin_info->clear ();
747 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
750 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
753 static bool windows_vst_filter (const string& str, void * /*arg*/)
755 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
756 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
760 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
762 vector<string> plugin_objects;
763 vector<string>::iterator x;
766 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
768 if (Config->get_verbose_plugin_scan()) {
769 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
772 find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
774 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
775 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
776 windows_vst_discover (*x, cache_only || cancelled());
779 if (Config->get_verbose_plugin_scan()) {
780 info << _("--- Windows VST plugins Scan Done") << endmsg;
787 PluginManager::windows_vst_discover (string path, bool cache_only)
789 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
791 if (Config->get_verbose_plugin_scan()) {
792 info << string_compose (_(" * %1 %2"), path, (cache_only ? _(" (cache only)") : "")) << endmsg;
795 _cancel_timeout = false;
796 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
797 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
799 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
800 // .err file scanner output etc.
802 if (finfos->empty()) {
803 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
804 if (Config->get_verbose_plugin_scan()) {
805 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
810 uint32_t discovered = 0;
811 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
815 if (!finfo->canProcessReplacing) {
816 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
817 finfo->name, PROGRAM_NAME)
822 PluginInfoPtr info (new WindowsVSTPluginInfo);
824 /* what a joke freeware VST is */
826 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
827 info->name = PBD::basename_nosuffix (path);
829 info->name = finfo->name;
833 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
834 info->unique_id = buf;
835 info->category = "VST";
837 info->creator = finfo->creator;
839 info->n_inputs.set_audio (finfo->numInputs);
840 info->n_outputs.set_audio (finfo->numOutputs);
841 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
842 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
843 info->type = ARDOUR::Windows_VST;
845 // TODO: check dup-IDs (lxvst AND windows vst)
846 bool duplicate = false;
848 if (!_windows_vst_plugin_info->empty()) {
849 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
850 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
851 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
859 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
860 _windows_vst_plugin_info->push_back (info);
862 if (Config->get_verbose_plugin_scan()) {
863 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
868 vstfx_free_info_list (finfos);
869 return discovered > 0 ? 0 : -1;
872 #endif // WINDOWS_VST_SUPPORT
877 PluginManager::lxvst_refresh (bool cache_only)
879 if (_lxvst_plugin_info) {
880 _lxvst_plugin_info->clear ();
882 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
885 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
888 static bool lxvst_filter (const string& str, void *)
890 /* Not a dotfile, has a prefix before a period, suffix is "so" */
892 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
896 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
898 vector<string> plugin_objects;
899 vector<string>::iterator x;
906 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
908 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
910 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
911 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
912 lxvst_discover (*x, cache_only || cancelled());
919 PluginManager::lxvst_discover (string path, bool cache_only)
921 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
923 _cancel_timeout = false;
924 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
925 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
927 if (finfos->empty()) {
928 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
932 uint32_t discovered = 0;
933 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
937 if (!finfo->canProcessReplacing) {
938 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
939 finfo->name, PROGRAM_NAME)
944 PluginInfoPtr info(new LXVSTPluginInfo);
946 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
947 info->name = PBD::basename_nosuffix (path);
949 info->name = finfo->name;
953 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
954 info->unique_id = buf;
955 info->category = "linuxVSTs";
957 info->creator = finfo->creator;
959 info->n_inputs.set_audio (finfo->numInputs);
960 info->n_outputs.set_audio (finfo->numOutputs);
961 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
962 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
963 info->type = ARDOUR::LXVST;
965 /* Make sure we don't find the same plugin in more than one place along
966 the LXVST_PATH We can't use a simple 'find' because the path is included
967 in the PluginInfo, and that is the one thing we can be sure MUST be
968 different if a duplicate instance is found. So we just compare the type
969 and unique ID (which for some VSTs isn't actually unique...)
972 // TODO: check dup-IDs with windowsVST, too
973 bool duplicate = false;
974 if (!_lxvst_plugin_info->empty()) {
975 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
976 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
977 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
985 _lxvst_plugin_info->push_back (info);
990 vstfx_free_info_list (finfos);
991 return discovered > 0 ? 0 : -1;
994 #endif // LXVST_SUPPORT
997 PluginManager::PluginStatusType
998 PluginManager::get_status (const PluginInfoPtr& pi)
1000 PluginStatus ps (pi->type, pi->unique_id);
1001 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1002 if (i == statuses.end() ) {
1010 PluginManager::save_statuses ()
1012 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1015 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1016 switch ((*i).type) {
1027 ofs << "Windows-VST";
1036 switch ((*i).status) {
1049 ofs << (*i).unique_id;;
1052 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1056 PluginManager::load_statuses ()
1058 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
1060 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1063 stringstream ifs (fbuf);
1067 std::string sstatus;
1070 PluginStatusType status;
1087 /* rest of the line is the plugin ID */
1089 ifs.getline (buf, sizeof (buf), '\n');
1094 if (sstatus == "Normal") {
1096 } else if (sstatus == "Favorite") {
1098 } else if (sstatus == "Hidden") {
1101 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1107 if (stype == "LADSPA") {
1109 } else if (stype == "AudioUnit") {
1111 } else if (stype == "LV2") {
1113 } else if (stype == "Windows-VST") {
1115 } else if (stype == "LXVST") {
1118 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1124 strip_whitespace_edges (id);
1125 set_status (type, id, status);
1130 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1132 PluginStatus ps (t, id, status);
1133 statuses.erase (ps);
1135 if (status == Normal) {
1139 statuses.insert (ps);
1142 ARDOUR::PluginInfoList&
1143 PluginManager::windows_vst_plugin_info ()
1145 #ifdef WINDOWS_VST_SUPPORT
1146 if (!_windows_vst_plugin_info) {
1147 windows_vst_refresh ();
1149 return *_windows_vst_plugin_info;
1151 return _empty_plugin_info;
1155 ARDOUR::PluginInfoList&
1156 PluginManager::lxvst_plugin_info ()
1158 #ifdef LXVST_SUPPORT
1159 assert(_lxvst_plugin_info);
1160 return *_lxvst_plugin_info;
1162 return _empty_plugin_info;
1166 ARDOUR::PluginInfoList&
1167 PluginManager::ladspa_plugin_info ()
1169 assert(_ladspa_plugin_info);
1170 return *_ladspa_plugin_info;
1173 ARDOUR::PluginInfoList&
1174 PluginManager::lv2_plugin_info ()
1177 assert(_lv2_plugin_info);
1178 return *_lv2_plugin_info;
1180 return _empty_plugin_info;
1184 ARDOUR::PluginInfoList&
1185 PluginManager::au_plugin_info ()
1187 #ifdef AUDIOUNIT_SUPPORT
1188 if (_au_plugin_info) {
1189 return *_au_plugin_info;
1192 return _empty_plugin_info;