2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
26 #include <sys/types.h>
35 #ifdef WINDOWS_VST_SUPPORT
37 #include "pbd/basename.h"
39 #endif // WINDOWS_VST_SUPPORT
42 #include "ardour/linux_vst_support.h"
43 #include "pbd/basename.h"
45 #endif //LXVST_SUPPORT
47 #include <glibmm/miscutils.h>
48 #include <glibmm/pattern.h>
50 #include "pbd/pathscanner.h"
51 #include "pbd/whitespace.h"
52 #include "pbd/file_utils.h"
54 #include "ardour/debug.h"
55 #include "ardour/filesystem_paths.h"
56 #include "ardour/ladspa.h"
57 #include "ardour/ladspa_plugin.h"
58 #include "ardour/plugin.h"
59 #include "ardour/plugin_manager.h"
60 #include "ardour/rc_configuration.h"
66 #include "ardour/ladspa_search_path.h"
69 #include "ardour/lv2_plugin.h"
72 #ifdef WINDOWS_VST_SUPPORT
73 #include "ardour/windows_vst_plugin.h"
77 #include "ardour/lxvst_plugin.h"
80 #ifdef AUDIOUNIT_SUPPORT
81 #include "ardour/audio_unit.h"
82 #include <Carbon/Carbon.h>
85 #include "pbd/error.h"
86 #include "pbd/stl_delete.h"
90 #include "ardour/debug.h"
92 using namespace ARDOUR;
96 PluginManager* PluginManager::_instance = 0;
99 PluginManager::instance()
102 _instance = new PluginManager;
107 PluginManager::PluginManager ()
108 : _windows_vst_plugin_info(0)
109 , _lxvst_plugin_info(0)
110 , _ladspa_plugin_info(0)
111 , _lv2_plugin_info(0)
119 if ((s = getenv ("LADSPA_RDF_PATH"))){
123 if (lrdf_path.length() == 0) {
124 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
127 add_lrdf_data(lrdf_path);
128 add_ladspa_presets();
129 #ifdef WINDOWS_VST_SUPPORT
130 if (Config->get_use_windows_vst ()) {
131 add_windows_vst_presets ();
133 #endif /* WINDOWS_VST_SUPPORT */
136 if (Config->get_use_lxvst()) {
139 #endif /* Native LinuxVST support*/
141 if ((s = getenv ("VST_PATH"))) {
142 windows_vst_path = s;
143 } else if ((s = getenv ("VST_PLUGINS"))) {
144 windows_vst_path = s;
147 if ((s = getenv ("LXVST_PATH"))) {
149 } else if ((s = getenv ("LXVST_PLUGINS"))) {
153 if (_instance == 0) {
157 /* the plugin manager is constructed too early to use Profile */
159 if (getenv ("ARDOUR_SAE")) {
160 ladspa_plugin_whitelist.push_back (1203); // single band parametric
161 ladspa_plugin_whitelist.push_back (1772); // caps compressor
162 ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter
163 ladspa_plugin_whitelist.push_back (1075); // simple RMS expander
164 ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s)
165 ladspa_plugin_whitelist.push_back (1216); // gverb
166 ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
169 BootMessage (_("Discovering Plugins"));
173 PluginManager::~PluginManager()
179 PluginManager::refresh ()
181 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
187 #ifdef WINDOWS_VST_SUPPORT
188 if (Config->get_use_windows_vst()) {
189 windows_vst_refresh ();
191 #endif // WINDOWS_VST_SUPPORT
194 if(Config->get_use_lxvst()) {
197 #endif //Native linuxVST SUPPORT
199 #ifdef AUDIOUNIT_SUPPORT
203 PluginListChanged (); /* EMIT SIGNAL */
207 PluginManager::ladspa_refresh ()
209 if (_ladspa_plugin_info) {
210 _ladspa_plugin_info->clear ();
212 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
215 /* allow LADSPA_PATH to augment, not override standard locations */
217 /* Only add standard locations to ladspa_path if it doesn't
218 * already contain them. Check for trailing G_DIR_SEPARATOR too.
221 vector<string> ladspa_modules;
223 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
225 Glib::PatternSpec so_extension_pattern("*.so");
226 Glib::PatternSpec dylib_extension_pattern("*.dylib");
227 Glib::PatternSpec dll_extension_pattern("*.dll");
229 find_matching_files_in_search_path (ladspa_search_path (),
230 so_extension_pattern, ladspa_modules);
232 find_matching_files_in_search_path (ladspa_search_path (),
233 dylib_extension_pattern, ladspa_modules);
235 find_matching_files_in_search_path (ladspa_search_path (),
236 dll_extension_pattern, ladspa_modules);
238 for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
239 ladspa_discover (*i);
243 static bool rdf_filter (const string &str, void* /*arg*/)
245 return str[0] != '.' &&
246 ((str.find(".rdf") == (str.length() - 4)) ||
247 (str.find(".rdfs") == (str.length() - 5)) ||
248 (str.find(".n3") == (str.length() - 3)) ||
249 (str.find(".ttl") == (str.length() - 4)));
253 PluginManager::add_ladspa_presets()
255 add_presets ("ladspa");
259 PluginManager::add_windows_vst_presets()
261 add_presets ("windows-vst");
265 PluginManager::add_lxvst_presets()
267 add_presets ("lxvst");
271 PluginManager::add_presets(string domain)
275 vector<string *> *presets;
276 vector<string *>::iterator x;
279 if ((envvar = getenv ("HOME")) == 0) {
283 string path = string_compose("%1/.%2/rdf", envvar, domain);
284 presets = scanner (path, rdf_filter, 0, false, true);
287 for (x = presets->begin(); x != presets->end (); ++x) {
288 string file = "file:" + **x;
289 if (lrdf_read_file(file.c_str())) {
290 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
294 vector_delete (presets);
300 PluginManager::add_lrdf_data (const string &path)
304 vector<string *>* rdf_files;
305 vector<string *>::iterator x;
307 rdf_files = scanner (path, rdf_filter, 0, false, true);
310 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
311 const string uri(string("file://") + **x);
313 if (lrdf_read_file(uri.c_str())) {
314 warning << "Could not parse rdf file: " << uri << endmsg;
318 vector_delete (rdf_files);
324 PluginManager::ladspa_discover (string path)
326 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
328 Glib::Module module(path);
329 const LADSPA_Descriptor *descriptor;
330 LADSPA_Descriptor_Function dfunc;
334 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
335 path, Glib::Module::get_last_error()) << endmsg;
340 if (!module.get_symbol("ladspa_descriptor", func)) {
341 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
342 error << Glib::Module::get_last_error() << endmsg;
346 dfunc = (LADSPA_Descriptor_Function)func;
348 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
350 for (uint32_t i = 0; ; ++i) {
351 if ((descriptor = dfunc (i)) == 0) {
355 if (!ladspa_plugin_whitelist.empty()) {
356 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
361 PluginInfoPtr info(new LadspaPluginInfo);
362 info->name = descriptor->Name;
363 info->category = get_ladspa_category(descriptor->UniqueID);
364 info->creator = descriptor->Maker;
367 info->n_inputs = ChanCount();
368 info->n_outputs = ChanCount();
369 info->type = ARDOUR::LADSPA;
372 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
373 info->unique_id = buf;
375 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
376 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
377 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
378 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
380 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
381 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
386 if(_ladspa_plugin_info->empty()){
387 _ladspa_plugin_info->push_back (info);
390 //Ensure that the plugin is not already in the plugin list.
394 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
395 if(0 == info->unique_id.compare((*i)->unique_id)){
401 _ladspa_plugin_info->push_back (info);
404 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
407 // GDB WILL NOT LIKE YOU IF YOU DO THIS
414 PluginManager::get_ladspa_category (uint32_t plugin_id)
418 lrdf_statement pattern;
420 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
421 pattern.subject = buf;
422 pattern.predicate = const_cast<char*>(RDF_TYPE);
424 pattern.object_type = lrdf_uri;
426 lrdf_statement* matches1 = lrdf_matches (&pattern);
432 pattern.subject = matches1->object;
433 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
435 pattern.object_type = lrdf_literal;
437 lrdf_statement* matches2 = lrdf_matches (&pattern);
438 lrdf_free_statements(matches1);
444 string label = matches2->object;
445 lrdf_free_statements(matches2);
447 /* Kludge LADSPA class names to be singular and match LV2 class names.
448 This avoids duplicate plugin menus for every class, which is necessary
449 to make the plugin category menu at all usable, but is obviously a
452 In the short term, lrdf could be updated so the labels match and a new
453 release made. To support both specs, we should probably be mapping the
454 URIs to the same category in code and perhaps tweaking that hierarchy
455 dynamically to suit the user. Personally, I (drobilla) think that time
456 is better spent replacing the little-used LRDF.
458 In the longer term, we will abandon LRDF entirely in favour of LV2 and
459 use that class hierarchy. Aside from fixing this problem properly, that
460 will also allow for translated labels. SWH plugins have been LV2 for
461 ages; TAP needs porting. I don't know of anything else with LRDF data.
463 if (label == "Utilities") {
465 } else if (label == "Pitch shifters") {
466 return "Pitch Shifter";
467 } else if (label != "Dynamics" && label != "Chorus"
468 &&label[label.length() - 1] == 's'
469 && label[label.length() - 2] != 's') {
470 return label.substr(0, label.length() - 1);
481 PluginManager::lv2_refresh ()
483 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
484 delete _lv2_plugin_info;
485 _lv2_plugin_info = LV2PluginInfo::discover();
489 #ifdef AUDIOUNIT_SUPPORT
491 PluginManager::au_refresh ()
493 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
494 delete _au_plugin_info;
495 _au_plugin_info = AUPluginInfo::discover();
500 #ifdef WINDOWS_VST_SUPPORT
503 PluginManager::windows_vst_refresh ()
505 if (_windows_vst_plugin_info) {
506 _windows_vst_plugin_info->clear ();
508 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
511 if (windows_vst_path.length() == 0) {
512 windows_vst_path = "/usr/local/lib/vst:/usr/lib/vst";
515 windows_vst_discover_from_path (windows_vst_path);
519 PluginManager::add_windows_vst_directory (string path)
521 if (windows_vst_discover_from_path (path) == 0) {
522 windows_vst_path += ':';
523 windows_vst_path += path;
529 static bool windows_vst_filter (const string& str, void *arg)
531 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
533 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
537 PluginManager::windows_vst_discover_from_path (string path)
540 vector<string *> *plugin_objects;
541 vector<string *>::iterator x;
544 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
546 plugin_objects = scanner (windows_vst_path, windows_vst_filter, 0, false, true);
548 if (plugin_objects) {
549 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
550 windows_vst_discover (**x);
553 vector_delete (plugin_objects);
560 PluginManager::windows_vst_discover (string path)
565 if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
566 warning << "Cannot get Windows VST information from " << path << endmsg;
570 if (!finfo->canProcessReplacing) {
571 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
572 finfo->name, PROGRAM_NAME)
576 PluginInfoPtr info (new WindowsVSTPluginInfo);
578 /* what a joke freeware VST is */
580 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
581 info->name = PBD::basename_nosuffix (path);
583 info->name = finfo->name;
587 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
588 info->unique_id = buf;
589 info->category = "VST";
591 info->creator = finfo->creator;
593 info->n_inputs.set_audio (finfo->numInputs);
594 info->n_outputs.set_audio (finfo->numOutputs);
595 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
596 info->type = ARDOUR::Windows_VST;
598 _windows_vst_plugin_info->push_back (info);
599 fst_free_info (finfo);
604 #endif // WINDOWS_VST_SUPPORT
609 PluginManager::lxvst_refresh ()
611 if (_lxvst_plugin_info) {
612 _lxvst_plugin_info->clear ();
614 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
617 if (lxvst_path.length() == 0) {
618 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst";
621 lxvst_discover_from_path (lxvst_path);
625 PluginManager::add_lxvst_directory (string path)
627 if (lxvst_discover_from_path (path) == 0) {
635 static bool lxvst_filter (const string& str, void *)
637 /* Not a dotfile, has a prefix before a period, suffix is "so" */
639 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
643 PluginManager::lxvst_discover_from_path (string path)
646 vector<string *> *plugin_objects;
647 vector<string *>::iterator x;
650 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
652 plugin_objects = scanner (lxvst_path, lxvst_filter, 0, false, true);
654 if (plugin_objects) {
655 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
656 lxvst_discover (**x);
659 vector_delete (plugin_objects);
666 PluginManager::lxvst_discover (string path)
671 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
673 if ((finfo = vstfx_get_info (const_cast<char *> (path.c_str()))) == 0) {
677 if (!finfo->canProcessReplacing) {
678 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
679 finfo->name, PROGRAM_NAME)
683 PluginInfoPtr info(new LXVSTPluginInfo);
685 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
686 info->name = PBD::basename_nosuffix (path);
688 info->name = finfo->name;
692 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
693 info->unique_id = buf;
694 info->category = "linuxVSTs";
696 info->creator = finfo->creator;
698 info->n_inputs.set_audio (finfo->numInputs);
699 info->n_outputs.set_audio (finfo->numOutputs);
700 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
701 info->type = ARDOUR::LXVST;
703 /* Make sure we don't find the same plugin in more than one place along
704 the LXVST_PATH We can't use a simple 'find' because the path is included
705 in the PluginInfo, and that is the one thing we can be sure MUST be
706 different if a duplicate instance is found. So we just compare the type
707 and unique ID (which for some VSTs isn't actually unique...)
710 if (!_lxvst_plugin_info->empty()) {
711 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
712 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
713 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
714 vstfx_free_info(finfo);
720 _lxvst_plugin_info->push_back (info);
721 vstfx_free_info (finfo);
726 #endif // LXVST_SUPPORT
729 PluginManager::PluginStatusType
730 PluginManager::get_status (const PluginInfoPtr& pi)
732 PluginStatus ps (pi->type, pi->unique_id);
733 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
734 if (i == statuses.end() ) {
742 PluginManager::save_statuses ()
745 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
747 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
753 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
765 ofs << "Windows-VST";
774 switch ((*i).status) {
787 ofs << (*i).unique_id;;
795 PluginManager::load_statuses ()
797 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
798 ifstream ifs (path.c_str());
808 PluginStatusType status;
825 /* rest of the line is the plugin ID */
827 ifs.getline (buf, sizeof (buf), '\n');
832 if (sstatus == "Normal") {
834 } else if (sstatus == "Favorite") {
836 } else if (sstatus == "Hidden") {
839 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
845 if (stype == "LADSPA") {
847 } else if (stype == "AudioUnit") {
849 } else if (stype == "LV2") {
851 } else if (stype == "Windows-VST") {
853 } else if (stype == "LXVST") {
856 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
862 strip_whitespace_edges (id);
863 set_status (type, id, status);
870 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
872 PluginStatus ps (t, id, status);
875 if (status == Normal) {
879 statuses.insert (ps);
882 ARDOUR::PluginInfoList&
883 PluginManager::windows_vst_plugin_info ()
885 #ifdef WINDOWS_VST_SUPPORT
886 if (!_windows_vst_plugin_info) {
887 windows_vst_refresh ();
889 return *_windows_vst_plugin_info;
891 return _empty_plugin_info;
895 ARDOUR::PluginInfoList&
896 PluginManager::lxvst_plugin_info ()
899 if (!_lxvst_plugin_info)
901 return *_lxvst_plugin_info;
903 return _empty_plugin_info;
907 ARDOUR::PluginInfoList&
908 PluginManager::ladspa_plugin_info ()
910 if (!_ladspa_plugin_info)
912 return *_ladspa_plugin_info;
915 ARDOUR::PluginInfoList&
916 PluginManager::lv2_plugin_info ()
919 if (!_lv2_plugin_info)
921 return *_lv2_plugin_info;
923 return _empty_plugin_info;
927 ARDOUR::PluginInfoList&
928 PluginManager::au_plugin_info ()
930 #ifdef AUDIOUNIT_SUPPORT
931 if (!_au_plugin_info)
933 return *_au_plugin_info;
935 return _empty_plugin_info;