2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
26 #include <sys/types.h>
31 #include "pbd/gstdio_compat.h"
37 #ifdef WINDOWS_VST_SUPPORT
38 #include "ardour/vst_info_file.h"
40 #include "pbd/basename.h"
49 #endif // WINDOWS_VST_SUPPORT
52 #include "ardour/vst_info_file.h"
53 #include "ardour/linux_vst_support.h"
54 #include "pbd/basename.h"
56 #endif //LXVST_SUPPORT
59 #include "ardour/vst_info_file.h"
60 #include "ardour/mac_vst_support.h"
61 #include "ardour/mac_vst_plugin.h"
62 #include "pbd/basename.h"
63 #include "pbd/pathexpand.h"
65 #endif //MACVST_SUPPORT
67 #include <glibmm/miscutils.h>
68 #include <glibmm/pattern.h>
69 #include <glibmm/fileutils.h>
70 #include <glibmm/miscutils.h>
72 #include "pbd/convert.h"
73 #include "pbd/file_utils.h"
74 #include "pbd/tokenizer.h"
75 #include "pbd/whitespace.h"
77 #include "ardour/directory_names.h"
78 #include "ardour/debug.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/ladspa.h"
81 #include "ardour/ladspa_plugin.h"
82 #include "ardour/luascripting.h"
83 #include "ardour/luaproc.h"
84 #include "ardour/plugin.h"
85 #include "ardour/plugin_manager.h"
86 #include "ardour/rc_configuration.h"
88 #include "ardour/search_paths.h"
91 #include "ardour/lv2_plugin.h"
94 #ifdef WINDOWS_VST_SUPPORT
95 #include "ardour/windows_vst_plugin.h"
99 #include "ardour/lxvst_plugin.h"
102 #ifdef AUDIOUNIT_SUPPORT
103 #include "ardour/audio_unit.h"
104 #include <Carbon/Carbon.h>
107 #include "pbd/error.h"
108 #include "pbd/stl_delete.h"
110 #include "pbd/i18n.h"
112 #include "ardour/debug.h"
114 using namespace ARDOUR;
118 PluginManager* PluginManager::_instance = 0;
119 std::string PluginManager::scanner_bin_path = "";
122 PluginManager::instance()
125 _instance = new PluginManager;
130 PluginManager::PluginManager ()
131 : _windows_vst_plugin_info(0)
132 , _lxvst_plugin_info(0)
133 , _mac_vst_plugin_info(0)
134 , _ladspa_plugin_info(0)
135 , _lv2_plugin_info(0)
137 , _lua_plugin_info(0)
138 , _cancel_scan(false)
139 , _cancel_timeout(false)
144 #if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
145 // source-tree (ardev, etc)
146 PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
148 #ifdef PLATFORM_WINDOWS
149 // on windows the .exe needs to be in the same folder with libardour.dll
150 vstsp += Glib::build_filename(windows_package_directory_path(), "bin");
152 // on Unices additional internal-use binaries are deployed to $libdir
153 vstsp += ARDOUR::ardour_dll_directory();
156 if (!PBD::find_file (vstsp,
157 #ifdef PLATFORM_WINDOWS
158 #ifdef DEBUGGABLE_SCANNER_APP
159 #if defined(DEBUG) || defined(_DEBUG)
160 "ardour-vst-scannerD.exe"
162 "ardour-vst-scannerRDC.exe"
165 "ardour-vst-scanner.exe"
170 , scanner_bin_path)) {
171 PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg;
179 if ((s = getenv ("LADSPA_RDF_PATH"))){
183 if (lrdf_path.length() == 0) {
184 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
187 add_lrdf_data(lrdf_path);
188 add_ladspa_presets();
189 #ifdef WINDOWS_VST_SUPPORT
190 if (Config->get_use_windows_vst ()) {
191 add_windows_vst_presets ();
193 #endif /* WINDOWS_VST_SUPPORT */
196 if (Config->get_use_lxvst()) {
199 #endif /* Native LinuxVST support*/
201 #ifdef MACVST_SUPPORT
202 if (Config->get_use_macvst ()) {
203 add_mac_vst_presets ();
207 if ((s = getenv ("VST_PATH"))) {
208 windows_vst_path = s;
209 } else if ((s = getenv ("VST_PLUGINS"))) {
210 windows_vst_path = s;
213 if (windows_vst_path.length() == 0) {
214 windows_vst_path = vst_search_path ();
217 if ((s = getenv ("LXVST_PATH"))) {
219 } else if ((s = getenv ("LXVST_PLUGINS"))) {
223 if (lxvst_path.length() == 0) {
224 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
225 "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
226 "/usr/lib/vst:/usr/local/lib/vst";
229 /* first time setup, use 'default' path */
230 if (Config->get_plugin_path_lxvst() == X_("@default@")) {
231 Config->set_plugin_path_lxvst(get_default_lxvst_path());
233 if (Config->get_plugin_path_vst() == X_("@default@")) {
234 Config->set_plugin_path_vst(get_default_windows_vst_path());
237 if (_instance == 0) {
241 BootMessage (_("Discovering Plugins"));
243 LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
247 PluginManager::~PluginManager()
249 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
250 // don't bother, just exit quickly.
251 delete _windows_vst_plugin_info;
252 delete _lxvst_plugin_info;
253 delete _mac_vst_plugin_info;
254 delete _ladspa_plugin_info;
255 delete _lv2_plugin_info;
256 delete _au_plugin_info;
257 delete _lua_plugin_info;
262 PluginManager::refresh (bool cache_only)
264 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
270 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
271 _cancel_scan = false;
273 BootMessage (_("Scanning LADSPA Plugins"));
275 BootMessage (_("Scanning Lua DSP Processors"));
278 BootMessage (_("Scanning LV2 Plugins"));
281 #ifdef WINDOWS_VST_SUPPORT
282 if (Config->get_use_windows_vst()) {
284 BootMessage (_("Scanning Windows VST Plugins"));
286 BootMessage (_("Discovering Windows VST Plugins"));
288 windows_vst_refresh (cache_only);
290 #endif // WINDOWS_VST_SUPPORT
293 if(Config->get_use_lxvst()) {
295 BootMessage (_("Scanning Linux VST Plugins"));
297 BootMessage (_("Discovering Linux VST Plugins"));
299 lxvst_refresh(cache_only);
301 #endif //Native linuxVST SUPPORT
303 #ifdef MACVST_SUPPORT
304 if(Config->get_use_macvst ()) {
306 BootMessage (_("Scanning Mac VST Plugins"));
308 BootMessage (_("Discovering Mac VST Plugins"));
310 mac_vst_refresh (cache_only);
311 } else if (_mac_vst_plugin_info) {
312 _mac_vst_plugin_info->clear ();
314 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
316 #endif //Native Mac VST SUPPORT
318 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
320 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
321 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
323 if (g_file_get_contents(fn.c_str (), &bl, NULL, NULL)) {
324 if (Config->get_verbose_plugin_scan()) {
325 PBD::info << _("VST Blacklist: ") << fn << "\n" << bl << "-----" << endmsg;
327 PBD::info << _("VST Blacklist:") << "\n" << bl << "-----" << endmsg;
335 #ifdef AUDIOUNIT_SUPPORT
337 BootMessage (_("Scanning AU Plugins"));
339 BootMessage (_("Discovering AU Plugins"));
341 au_refresh (cache_only);
344 BootMessage (_("Plugin Scan Complete..."));
345 PluginListChanged (); /* EMIT SIGNAL */
346 PluginScanMessage(X_("closeme"), "", false);
347 _cancel_scan = false;
351 PluginManager::cancel_plugin_scan ()
357 PluginManager::cancel_plugin_timeout ()
359 _cancel_timeout = true;
363 PluginManager::clear_vst_cache ()
365 #if 1 // clean old cache and error files. (remove this code after 4.3 or 5.0)
366 #ifdef WINDOWS_VST_SUPPORT
368 vector<string> fsi_files;
369 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_INFOFILE "$", true);
370 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
371 ::g_unlink(i->c_str());
375 vector<string> fsi_files;
376 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.fsi$", true);
377 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
378 ::g_unlink(i->c_str());
382 vector<string> fsi_files;
383 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\.err$", true);
384 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
385 ::g_unlink(i->c_str());
392 vector<string> fsi_files;
393 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_INFOFILE "$", true);
394 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
395 ::g_unlink(i->c_str());
399 vector<string> fsi_files;
400 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.fsi$", true);
401 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
402 ::g_unlink(i->c_str());
406 vector<string> fsi_files;
407 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\.err$", true);
408 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
409 ::g_unlink(i->c_str());
413 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
415 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_info");
416 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
417 PBD::remove_directory (dir);
421 #endif // old cache cleanup
423 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
425 string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
426 vector<string> fsi_files;
427 find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false);
428 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
429 ::g_unlink(i->c_str());
436 PluginManager::clear_vst_blacklist ()
438 #if 1 // remove old blacklist files. (remove this code after 4.3 or 5.0)
440 #ifdef WINDOWS_VST_SUPPORT
442 vector<string> fsi_files;
443 find_files_matching_regex (fsi_files, Config->get_plugin_path_vst(), "\\" VST_EXT_BLACKLIST "$", true);
444 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
445 ::g_unlink(i->c_str());
452 vector<string> fsi_files;
453 find_files_matching_regex (fsi_files, Config->get_plugin_path_lxvst(), "\\" VST_EXT_BLACKLIST "$", true);
454 for (vector<string>::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) {
455 ::g_unlink(i->c_str());
459 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
461 string dir = Glib::build_filename (ARDOUR::user_cache_directory(), "fst_blacklist");
462 if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
463 PBD::remove_directory (dir);
468 #endif // old blacklist cleanup
470 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
472 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
473 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
474 ::g_unlink (fn.c_str());
482 PluginManager::clear_au_cache ()
484 #ifdef AUDIOUNIT_SUPPORT
485 AUPluginInfo::clear_cache ();
490 PluginManager::clear_au_blacklist ()
492 #ifdef AUDIOUNIT_SUPPORT
493 string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_blacklist.txt");
494 if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
495 ::g_unlink(fn.c_str());
501 PluginManager::lua_refresh ()
503 if (_lua_plugin_info) {
504 _lua_plugin_info->clear ();
506 _lua_plugin_info = new ARDOUR::PluginInfoList ();
508 ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
509 for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
510 LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
511 _lua_plugin_info->push_back (lpi);
512 set_tags (lpi->type, lpi->unique_id, lpi->category, lpi->name, FromPlug);
517 PluginManager::lua_refresh_cb ()
519 Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
524 PluginListChanged (); /* EMIT SIGNAL */
528 PluginManager::ladspa_refresh ()
530 if (_ladspa_plugin_info) {
531 _ladspa_plugin_info->clear ();
533 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
536 /* allow LADSPA_PATH to augment, not override standard locations */
538 /* Only add standard locations to ladspa_path if it doesn't
539 * already contain them. Check for trailing G_DIR_SEPARATOR too.
542 vector<string> ladspa_modules;
544 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
546 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.so");
547 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dylib");
548 find_files_matching_pattern (ladspa_modules, ladspa_search_path (), "*.dll");
550 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
551 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
552 ladspa_discover (*i);
557 static bool rdf_filter (const string &str, void* /*arg*/)
559 return str[0] != '.' &&
560 ((str.find(".rdf") == (str.length() - 4)) ||
561 (str.find(".rdfs") == (str.length() - 5)) ||
562 (str.find(".n3") == (str.length() - 3)) ||
563 (str.find(".ttl") == (str.length() - 4)));
568 PluginManager::add_ladspa_presets()
570 add_presets ("ladspa");
574 PluginManager::add_windows_vst_presets()
576 add_presets ("windows-vst");
580 PluginManager::add_mac_vst_presets()
582 add_presets ("mac-vst");
586 PluginManager::add_lxvst_presets()
588 add_presets ("lxvst");
592 PluginManager::add_presets(string domain)
595 vector<string> presets;
596 vector<string>::iterator x;
599 if ((envvar = getenv ("HOME")) == 0) {
603 string path = string_compose("%1/.%2/rdf", envvar, domain);
604 find_files_matching_filter (presets, path, rdf_filter, 0, false, true);
606 for (x = presets.begin(); x != presets.end (); ++x) {
607 string file = "file:" + *x;
608 if (lrdf_read_file(file.c_str())) {
609 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
617 PluginManager::add_lrdf_data (const string &path)
620 vector<string> rdf_files;
621 vector<string>::iterator x;
623 find_files_matching_filter (rdf_files, path, rdf_filter, 0, false, true);
625 for (x = rdf_files.begin(); x != rdf_files.end (); ++x) {
626 const string uri(string("file://") + *x);
628 if (lrdf_read_file(uri.c_str())) {
629 warning << "Could not parse rdf file: " << uri << endmsg;
636 PluginManager::ladspa_discover (string path)
638 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
640 Glib::Module module(path);
641 const LADSPA_Descriptor *descriptor;
642 LADSPA_Descriptor_Function dfunc;
646 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
647 path, Glib::Module::get_last_error()) << endmsg;
652 if (!module.get_symbol("ladspa_descriptor", func)) {
653 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
654 error << Glib::Module::get_last_error() << endmsg;
658 dfunc = (LADSPA_Descriptor_Function)func;
660 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
662 for (uint32_t i = 0; ; ++i) {
663 /* if a ladspa plugin allocates memory here
664 * it is never free()ed (or plugin-dependent only when unloading).
665 * For some plugins memory allocated is incremental, we should
666 * avoid re-scanning plugins and file bug reports.
668 if ((descriptor = dfunc (i)) == 0) {
672 if (!ladspa_plugin_whitelist.empty()) {
673 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
678 PluginInfoPtr info(new LadspaPluginInfo);
679 info->name = descriptor->Name;
680 info->category = get_ladspa_category(descriptor->UniqueID);
683 info->n_inputs = ChanCount();
684 info->n_outputs = ChanCount();
685 info->type = ARDOUR::LADSPA;
687 string::size_type pos = 0;
688 string creator = descriptor->Maker;
689 /* stupid LADSPA creator strings */
690 #ifdef PLATFORM_WINDOWS
691 while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
693 while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
696 /* If there were too few characters to create a
697 * meaningful name, mark this creator as 'Unknown'
699 if (creator.length() < 2 || pos < 3) {
700 info->creator = "Unknown";
702 info->creator = creator.substr (0, pos);
706 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
707 info->unique_id = buf;
709 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
710 if (LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n])) {
711 if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n])) {
712 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
714 else if (LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n])) {
715 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
720 if(_ladspa_plugin_info->empty()){
721 _ladspa_plugin_info->push_back (info);
724 //Ensure that the plugin is not already in the plugin list.
728 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
729 if(0 == info->unique_id.compare((*i)->unique_id)){
735 _ladspa_plugin_info->push_back (info);
736 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
739 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
742 // GDB WILL NOT LIKE YOU IF YOU DO THIS
749 PluginManager::get_ladspa_category (uint32_t plugin_id)
753 lrdf_statement pattern;
755 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
756 pattern.subject = buf;
757 pattern.predicate = const_cast<char*>(RDF_TYPE);
759 pattern.object_type = lrdf_uri;
761 lrdf_statement* matches1 = lrdf_matches (&pattern);
767 pattern.subject = matches1->object;
768 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
770 pattern.object_type = lrdf_literal;
772 lrdf_statement* matches2 = lrdf_matches (&pattern);
773 lrdf_free_statements(matches1);
779 string label = matches2->object;
780 lrdf_free_statements(matches2);
782 /* Kludge LADSPA class names to be singular and match LV2 class names.
783 This avoids duplicate plugin menus for every class, which is necessary
784 to make the plugin category menu at all usable, but is obviously a
787 In the short term, lrdf could be updated so the labels match and a new
788 release made. To support both specs, we should probably be mapping the
789 URIs to the same category in code and perhaps tweaking that hierarchy
790 dynamically to suit the user. Personally, I (drobilla) think that time
791 is better spent replacing the little-used LRDF.
793 In the longer term, we will abandon LRDF entirely in favour of LV2 and
794 use that class hierarchy. Aside from fixing this problem properly, that
795 will also allow for translated labels. SWH plugins have been LV2 for
796 ages; TAP needs porting. I don't know of anything else with LRDF data.
798 if (label == "Utilities") {
800 } else if (label == "Pitch shifters") {
801 return "Pitch Shifter";
802 } else if (label != "Dynamics" && label != "Chorus"
803 &&label[label.length() - 1] == 's'
804 && label[label.length() - 2] != 's') {
805 return label.substr(0, label.length() - 1);
816 PluginManager::lv2_refresh ()
818 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
819 delete _lv2_plugin_info;
820 _lv2_plugin_info = LV2PluginInfo::discover();
822 for (PluginInfoList::iterator i = _lv2_plugin_info->begin(); i != _lv2_plugin_info->end(); ++i) {
823 set_tags ((*i)->type, (*i)->unique_id, (*i)->category, (*i)->name, FromPlug);
828 #ifdef AUDIOUNIT_SUPPORT
830 PluginManager::au_refresh (bool cache_only)
832 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
834 // disable automatic discovery in case we crash
835 bool discover_at_start = Config->get_discover_audio_units ();
836 Config->set_discover_audio_units (false);
837 Config->save_state();
839 delete _au_plugin_info;
840 _au_plugin_info = AUPluginInfo::discover(cache_only && !discover_at_start);
842 // successful scan re-enabled automatic discovery if it was set
843 Config->set_discover_audio_units (discover_at_start);
844 Config->save_state();
846 for (PluginInfoList::iterator i = _au_plugin_info->begin(); i != _au_plugin_info->end(); ++i) {
847 set_tags ((*i)->type, (*i)->unique_id, (*i)->category, (*i)->name, FromPlug);
853 #ifdef WINDOWS_VST_SUPPORT
856 PluginManager::windows_vst_refresh (bool cache_only)
858 if (_windows_vst_plugin_info) {
859 _windows_vst_plugin_info->clear ();
861 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
864 windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
867 static bool windows_vst_filter (const string& str, void * /*arg*/)
869 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
870 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".dll", str.substr(str.length() - 4));
874 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
876 vector<string> plugin_objects;
877 vector<string>::iterator x;
880 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
882 if (Session::get_disable_all_loaded_plugins ()) {
883 info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
887 if (Config->get_verbose_plugin_scan()) {
888 info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
891 find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
893 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
894 ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
895 windows_vst_discover (*x, cache_only || cancelled());
898 if (Config->get_verbose_plugin_scan()) {
899 info << _("--- Windows VST plugins Scan Done") << endmsg;
905 static std::string dll_info (std::string path) {
909 off_t pe_hdr_off = 0;
911 int fd = g_open(path.c_str(), O_RDONLY, 0444);
914 return _("cannot open dll"); // TODO strerror()
917 if (68 != read (fd, buf, 68)) {
918 rv = _("invalid dll, file too small");
921 if (buf[0] != 'M' && buf[1] != 'Z') {
926 pe_hdr_off = *((int32_t*) &buf[60]);
927 if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) {
928 rv = _("cannot determine dll type");
931 if (6 != read (fd, buf, 6)) {
932 rv = _("cannot read dll PE header");
936 if (buf[0] != 'P' && buf[1] != 'E') {
937 rv = _("invalid dll PE header");
941 type = *((uint16_t*) &buf[4]);
944 rv = _("i386 (32-bit)");
950 rv = _("x64 (64-bit)");
953 rv = _("Native Architecture");
956 rv = _("Unknown Architecture");
960 assert (rv.length() > 0);
966 PluginManager::windows_vst_discover (string path, bool cache_only)
968 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
970 if (Config->get_verbose_plugin_scan()) {
972 info << string_compose (_(" * %1 (cache only)"), path) << endmsg;
974 info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg;
978 _cancel_timeout = false;
979 vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
980 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
982 // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat,
983 // .err file scanner output etc.
985 if (finfos->empty()) {
986 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
987 if (Config->get_verbose_plugin_scan()) {
988 info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg;
993 uint32_t discovered = 0;
994 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
997 if (!finfo->canProcessReplacing) {
998 warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"),
999 finfo->name, PROGRAM_NAME)
1004 PluginInfoPtr info (new WindowsVSTPluginInfo (finfo));
1007 /* what a joke freeware VST is */
1008 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1009 info->name = PBD::basename_nosuffix (path);
1012 /* if we don't have any tags for this plugin, make some up. */
1013 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1015 // TODO: check dup-IDs (lxvst AND windows vst)
1016 bool duplicate = false;
1018 if (!_windows_vst_plugin_info->empty()) {
1019 for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
1020 if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) {
1021 warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg;
1029 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
1030 _windows_vst_plugin_info->push_back (info);
1032 if (Config->get_verbose_plugin_scan()) {
1033 PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg;
1038 vstfx_free_info_list (finfos);
1039 return discovered > 0 ? 0 : -1;
1042 #endif // WINDOWS_VST_SUPPORT
1044 #ifdef MACVST_SUPPORT
1046 PluginManager::mac_vst_refresh (bool cache_only)
1048 if (_mac_vst_plugin_info) {
1049 _mac_vst_plugin_info->clear ();
1051 _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
1054 mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
1057 static bool mac_vst_filter (const string& str)
1059 string plist = Glib::build_filename (str, "Contents", "Info.plist");
1060 if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
1063 return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
1067 PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
1069 if (Session::get_disable_all_loaded_plugins ()) {
1070 info << _("Disabled MacVST scan (safe mode)") << endmsg;
1074 Searchpath paths (path);
1075 /* customized version of run_functor_for_paths() */
1076 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
1077 string expanded_path = path_expand (*i);
1078 if (!Glib::file_test (expanded_path, Glib::FILE_TEST_IS_DIR)) continue;
1080 Glib::Dir dir(expanded_path);
1081 for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
1082 string fullpath = Glib::build_filename (expanded_path, *di);
1084 /* we're only interested in bundles */
1085 if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
1089 if (mac_vst_filter (fullpath)) {
1090 ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled());
1091 mac_vst_discover (fullpath, cache_only || cancelled());
1095 /* don't descend into AU bundles in the VST dir */
1096 if (fullpath[0] == '.' || (fullpath.length() > 10 && strings_equal_ignore_case (".component", fullpath.substr(fullpath.length() - 10)))) {
1101 mac_vst_discover_from_path (fullpath, cache_only);
1103 } catch (Glib::FileError& err) { }
1110 PluginManager::mac_vst_discover (string path, bool cache_only)
1112 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
1114 _cancel_timeout = false;
1116 vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
1117 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1119 if (finfos->empty()) {
1120 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
1124 uint32_t discovered = 0;
1125 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1126 VSTInfo* finfo = *x;
1128 if (!finfo->canProcessReplacing) {
1129 warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1130 finfo->name, PROGRAM_NAME)
1135 PluginInfoPtr info (new MacVSTPluginInfo (finfo));
1138 /* if we don't have any tags for this plugin, make some up. */
1139 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1141 bool duplicate = false;
1142 if (!_mac_vst_plugin_info->empty()) {
1143 for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
1144 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1145 warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
1153 _mac_vst_plugin_info->push_back (info);
1158 vstfx_free_info_list (finfos);
1159 return discovered > 0 ? 0 : -1;
1162 #endif // MAC_VST_SUPPORT
1164 #ifdef LXVST_SUPPORT
1167 PluginManager::lxvst_refresh (bool cache_only)
1169 if (_lxvst_plugin_info) {
1170 _lxvst_plugin_info->clear ();
1172 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
1175 lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
1178 static bool lxvst_filter (const string& str, void *)
1180 /* Not a dotfile, has a prefix before a period, suffix is "so" */
1182 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
1186 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
1188 vector<string> plugin_objects;
1189 vector<string>::iterator x;
1192 if (Session::get_disable_all_loaded_plugins ()) {
1193 info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
1201 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
1203 find_files_matching_filter (plugin_objects, Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true, true);
1205 for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
1206 ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled());
1207 lxvst_discover (*x, cache_only || cancelled());
1214 PluginManager::lxvst_discover (string path, bool cache_only)
1216 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
1218 _cancel_timeout = false;
1219 vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
1220 cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
1222 if (finfos->empty()) {
1223 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
1227 uint32_t discovered = 0;
1228 for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
1229 VSTInfo* finfo = *x;
1231 if (!finfo->canProcessReplacing) {
1232 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
1233 finfo->name, PROGRAM_NAME)
1238 PluginInfoPtr info(new LXVSTPluginInfo (finfo));
1241 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
1242 info->name = PBD::basename_nosuffix (path);
1245 set_tags (info->type, info->unique_id, info->category, info->name, FromPlug);
1247 /* Make sure we don't find the same plugin in more than one place along
1248 * the LXVST_PATH We can't use a simple 'find' because the path is included
1249 * in the PluginInfo, and that is the one thing we can be sure MUST be
1250 * different if a duplicate instance is found. So we just compare the type
1251 * and unique ID (which for some VSTs isn't actually unique...)
1254 // TODO: check dup-IDs with windowsVST, too
1255 bool duplicate = false;
1256 if (!_lxvst_plugin_info->empty()) {
1257 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
1258 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
1259 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
1267 _lxvst_plugin_info->push_back (info);
1272 vstfx_free_info_list (finfos);
1273 return discovered > 0 ? 0 : -1;
1276 #endif // LXVST_SUPPORT
1279 PluginManager::PluginStatusType
1280 PluginManager::get_status (const PluginInfoPtr& pi) const
1282 PluginStatus ps (pi->type, pi->unique_id);
1283 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
1284 if (i == statuses.end()) {
1292 PluginManager::save_statuses ()
1294 std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_statuses");
1297 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
1298 switch ((*i).type) {
1309 ofs << "Windows-VST";
1324 switch ((*i).status) {
1338 ofs << (*i).unique_id;;
1341 g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
1345 PluginManager::load_statuses ()
1348 find_file (plugin_metadata_search_path(), "plugin_statuses", path); //note: if no user folder is found, this will find the resources path
1350 if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL)) {
1353 stringstream ifs (fbuf);
1357 std::string sstatus;
1360 PluginStatusType status;
1377 /* rest of the line is the plugin ID */
1379 ifs.getline (buf, sizeof (buf), '\n');
1384 if (sstatus == "Normal") {
1386 } else if (sstatus == "Favorite") {
1388 } else if (sstatus == "Hidden") {
1391 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
1397 if (stype == "LADSPA") {
1399 } else if (stype == "AudioUnit") {
1401 } else if (stype == "LV2") {
1403 } else if (stype == "Windows-VST") {
1405 } else if (stype == "LXVST") {
1407 } else if (stype == "MacVST") {
1409 } else if (stype == "Lua") {
1412 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1418 strip_whitespace_edges (id);
1419 set_status (type, id, status);
1424 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1426 PluginStatus ps (t, id, status);
1427 statuses.erase (ps);
1429 if (status != Normal) {
1430 statuses.insert (ps);
1433 PluginStatusChanged (t, id, status); /* EMIT SIGNAL */
1437 PluginManager::to_generic_vst (const PluginType t)
1451 bool operator() (std::string a, std::string b) {
1452 return a.compare (b) < 0;
1457 PluginManager::get_tags (const PluginInfoPtr& pi) const
1459 vector<std::string> tags;
1461 PluginTag ps (to_generic_vst(pi->type), pi->unique_id, "", "", FromPlug);
1462 PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1463 if (i != ptags.end ()) {
1464 PBD::tokenize (i->tags, string(" "), std::back_inserter (tags), true);
1466 sort (tags.begin(), tags.end(), sorter);
1472 PluginManager::get_tags_as_string (PluginInfoPtr const& pi) const
1476 vector<std::string> tags = get_tags(pi);
1477 for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1478 if (t != tags.begin ()) {
1488 PluginManager::user_plugin_metadata_dir () const
1490 std::string dir = Glib::build_filename (user_config_directory(), plugin_metadata_dir_name);
1491 g_mkdir_with_parents (dir.c_str(), 0744);
1496 PluginManager::load_plugin_order_file (XMLNode &n) const
1498 std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_order");
1500 info << string_compose (_("Loading plugin order file %1"), path) << endmsg;
1501 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1506 if (tree.read (path)) {
1510 error << string_compose (_("Cannot parse Plugin Order info from %1"), path) << endmsg;
1517 PluginManager::save_plugin_order_file (XMLNode &elem) const
1519 std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_order");
1521 info << string_compose (_("Saving plugin order file %1"), path) << endmsg;
1524 tree.set_root (&elem);
1525 if (!tree.write (path)) {
1526 error << string_compose (_("Could not save Plugin Order info to %1"), path) << endmsg;
1528 tree.set_root (0); //note: must disconnect the elem from XMLTree, or it will try to delete memory it didn't allocate
1533 PluginManager::save_tags ()
1535 std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_tags");
1536 XMLNode* root = new XMLNode (X_("PluginTags"));
1538 for (PluginTagList::iterator i = ptags.begin(); i != ptags.end(); ++i) {
1539 if ( (*i).tagtype == FromFactoryFile || (*i).tagtype == FromUserFile ) {
1540 /* user file should contain only plugins that are (a) newly user-tagged or (b) previously unknown */
1543 XMLNode* node = new XMLNode (X_("Plugin"));
1544 node->set_property (X_("type"), to_generic_vst ((*i).type));
1545 node->set_property (X_("id"), (*i).unique_id);
1546 node->set_property (X_("tags"), (*i).tags);
1547 node->set_property (X_("name"), (*i).name);
1548 if ( (*i).tagtype >= FromUserFile ) {
1549 node->set_property (X_("user-set"), "1");
1551 root->add_child_nocopy (*node);
1555 tree.set_root (root);
1556 if (!tree.write (path)) {
1557 error << string_compose (_("Could not save Plugin Tags info to %1"), path) << endmsg;
1562 PluginManager::load_tags ()
1564 vector<std::string> tmp;
1565 find_files_matching_pattern (tmp, plugin_metadata_search_path (), "plugin_tags");
1567 for (vector<std::string>::const_reverse_iterator p = tmp.rbegin ();
1568 p != (vector<std::string>::const_reverse_iterator)tmp.rend(); ++p) {
1569 std::string path = *p;
1570 info << string_compose (_("Loading plugin meta data file %1"), path) << endmsg;
1571 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1576 if (!tree.read (path)) {
1577 error << string_compose (_("Cannot parse plugin tag info from %1"), path) << endmsg;
1581 for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) {
1587 if (!(*i)->get_property (X_("type"), type) ||
1588 !(*i)->get_property (X_("id"), id) ||
1589 !(*i)->get_property (X_("tags"), tags) ||
1590 !(*i)->get_property (X_("name"), name)) {
1592 if (!(*i)->get_property (X_("user-set"), user_set)) {
1595 strip_whitespace_edges (tags);
1596 set_tags (type, id, tags, name, user_set ? FromUserFile : FromFactoryFile );
1602 PluginManager::set_tags (PluginType t, string id, string tag, std::string name, TagType ttype )
1604 string sanitized = sanitize_tag (tag);
1606 PluginTag ps (to_generic_vst (t), id, sanitized, name, ttype );
1607 PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1608 if (i == ptags.end()) {
1610 } else if ( (uint32_t) ttype >= (uint32_t) (*i).tagtype ) { // only overwrite if we are more important than the existing. Gui > UserFile > FactoryFile > Plugin
1614 if ( ttype == FromGui ) {
1615 PluginTagChanged (t, id, sanitized); /* EMIT SIGNAL */
1620 PluginManager::reset_tags (PluginInfoPtr const& pi)
1622 PluginTag ps (pi->type, pi->unique_id, pi->category, pi->name, FromPlug);
1624 PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
1625 if (i != ptags.end()) {
1632 PluginManager::sanitize_tag (const std::string to_sanitize) const
1634 if (to_sanitize.empty ()) {
1637 string sanitized = to_sanitize;
1638 vector<string> tags;
1639 if (!PBD::tokenize (sanitized, string(" ,\n"), std::back_inserter (tags), true)) {
1641 cerr << _("PluginManager::sanitize_tag could not tokenize string: ") << sanitized << endmsg;
1646 /* convert tokens to lower-case, space-separated list */
1648 for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1649 if (t != tags.begin ()) {
1650 sanitized.append(" ");
1652 sanitized.append (downcase (*t));
1658 std::vector<std::string>
1659 PluginManager::get_all_tags (TagFilter tag_filter) const
1661 std::vector<std::string> ret;
1663 PluginTagList::const_iterator pt;
1664 for (pt = ptags.begin(); pt != ptags.end(); ++pt) {
1665 if ((*pt).tags.empty ()) {
1669 /* if favorites_only then we need to check the info ptr and maybe skip */
1670 if (tag_filter == OnlyFavorites) {
1671 PluginStatus stat ((*pt).type, (*pt).unique_id);
1672 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), stat);
1673 if ((i != statuses.end()) && (i->status == Favorite)) {
1674 /* it's a favorite! */
1679 if (tag_filter == NoHidden) {
1680 PluginStatus stat ((*pt).type, (*pt).unique_id);
1681 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), stat);
1682 if ((i != statuses.end()) && (i->status == Hidden)) {
1687 /* parse each plugin's tag string into separate tags */
1688 vector<string> tags;
1689 if (!PBD::tokenize ((*pt).tags, string(" "), std::back_inserter (tags), true)) {
1691 cerr << _("PluginManager: Could not tokenize string: ") << (*pt).tags << endmsg;
1696 /* maybe add the tags we've found */
1697 for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
1698 /* if this tag isn't already in the list, add it */
1699 vector<string>::iterator i = find (ret.begin(), ret.end(), *t);
1700 if (i == ret.end()) {
1706 /* sort in alphabetical order */
1708 sort (ret.begin(), ret.end(), sorter);
1714 const ARDOUR::PluginInfoList&
1715 PluginManager::windows_vst_plugin_info ()
1717 #ifdef WINDOWS_VST_SUPPORT
1718 if (!_windows_vst_plugin_info) {
1719 windows_vst_refresh ();
1721 return *_windows_vst_plugin_info;
1723 return _empty_plugin_info;
1727 const ARDOUR::PluginInfoList&
1728 PluginManager::mac_vst_plugin_info ()
1730 #ifdef MACVST_SUPPORT
1731 assert(_mac_vst_plugin_info);
1732 return *_mac_vst_plugin_info;
1734 return _empty_plugin_info;
1738 const ARDOUR::PluginInfoList&
1739 PluginManager::lxvst_plugin_info ()
1741 #ifdef LXVST_SUPPORT
1742 assert(_lxvst_plugin_info);
1743 return *_lxvst_plugin_info;
1745 return _empty_plugin_info;
1749 const ARDOUR::PluginInfoList&
1750 PluginManager::ladspa_plugin_info ()
1752 assert(_ladspa_plugin_info);
1753 return *_ladspa_plugin_info;
1756 const ARDOUR::PluginInfoList&
1757 PluginManager::lv2_plugin_info ()
1760 assert(_lv2_plugin_info);
1761 return *_lv2_plugin_info;
1763 return _empty_plugin_info;
1767 const ARDOUR::PluginInfoList&
1768 PluginManager::au_plugin_info ()
1770 #ifdef AUDIOUNIT_SUPPORT
1771 if (_au_plugin_info) {
1772 return *_au_plugin_info;
1775 return _empty_plugin_info;
1778 const ARDOUR::PluginInfoList&
1779 PluginManager::lua_plugin_info ()
1781 assert(_lua_plugin_info);
1782 return *_lua_plugin_info;