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>
33 #ifdef WINDOWS_VST_SUPPORT
35 #include "pbd/basename.h"
37 #endif // WINDOWS_VST_SUPPORT
40 #include "ardour/linux_vst_support.h"
41 #include "pbd/basename.h"
43 #endif //LXVST_SUPPORT
45 #include <glibmm/miscutils.h>
47 #include "pbd/pathscanner.h"
48 #include "pbd/whitespace.h"
50 #include "ardour/debug.h"
51 #include "ardour/filesystem_paths.h"
52 #include "ardour/ladspa.h"
53 #include "ardour/ladspa_plugin.h"
54 #include "ardour/plugin.h"
55 #include "ardour/plugin_manager.h"
56 #include "ardour/rc_configuration.h"
59 #include "ardour/lv2_plugin.h"
62 #ifdef WINDOWS_VST_SUPPORT
63 #include "ardour/windows_vst_plugin.h"
67 #include "ardour/lxvst_plugin.h"
70 #ifdef AUDIOUNIT_SUPPORT
71 #include "ardour/audio_unit.h"
72 #include <Carbon/Carbon.h>
75 #include "pbd/error.h"
76 #include "pbd/stl_delete.h"
80 using namespace ARDOUR;
84 PluginManager* PluginManager::_instance = 0;
87 PluginManager::instance()
90 _instance = new PluginManager;
95 PluginManager::PluginManager ()
96 : _windows_vst_plugin_info(0)
97 , _lxvst_plugin_info(0)
98 , _ladspa_plugin_info(0)
107 if ((s = getenv ("LADSPA_RDF_PATH"))){
111 if (lrdf_path.length() == 0) {
112 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
115 add_lrdf_data(lrdf_path);
116 add_ladspa_presets();
117 #ifdef WINDOWS_VST_SUPPORT
118 if (Config->get_use_windows_vst ()) {
119 add_windows_vst_presets ();
121 #endif /* WINDOWS_VST_SUPPORT */
124 if (Config->get_use_lxvst()) {
127 #endif /* Native LinuxVST support*/
129 if ((s = getenv ("LADSPA_PATH"))) {
133 if ((s = getenv ("VST_PATH"))) {
134 windows_vst_path = s;
135 } else if ((s = getenv ("VST_PLUGINS"))) {
136 windows_vst_path = s;
139 if ((s = getenv ("LXVST_PATH"))) {
141 } else if ((s = getenv ("LXVST_PLUGINS"))) {
145 if (_instance == 0) {
149 /* the plugin manager is constructed too early to use Profile */
151 if (getenv ("ARDOUR_SAE")) {
152 ladspa_plugin_whitelist.push_back (1203); // single band parametric
153 ladspa_plugin_whitelist.push_back (1772); // caps compressor
154 ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter
155 ladspa_plugin_whitelist.push_back (1075); // simple RMS expander
156 ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s)
157 ladspa_plugin_whitelist.push_back (1216); // gverb
158 ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
161 BootMessage (_("Discovering Plugins"));
165 PluginManager::~PluginManager()
171 PluginManager::refresh ()
173 DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
179 #ifdef WINDOWS_VST_SUPPORT
180 if (Config->get_use_windows_vst()) {
181 windows_vst_refresh ();
183 #endif // WINDOWS_VST_SUPPORT
186 if(Config->get_use_lxvst()) {
189 #endif //Native linuxVST SUPPORT
191 #ifdef AUDIOUNIT_SUPPORT
195 PluginListChanged (); /* EMIT SIGNAL */
199 PluginManager::ladspa_refresh ()
201 if (_ladspa_plugin_info)
202 _ladspa_plugin_info->clear ();
204 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
206 static const char *standard_paths[] = {
207 "/usr/local/lib64/ladspa",
208 "/usr/local/lib/ladspa",
211 "/Library/Audio/Plug-Ins/LADSPA",
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.
222 for (i = 0; standard_paths[i][0]; i++) {
223 size_t found = ladspa_path.find(standard_paths[i]);
224 if (found != ladspa_path.npos) {
225 switch (ladspa_path[found + strlen(standard_paths[i])]) {
229 case G_DIR_SEPARATOR :
230 if (ladspa_path[found + strlen(standard_paths[i]) + 1] == ':' ||
231 ladspa_path[found + strlen(standard_paths[i]) + 1] == '\0') {
236 if (!ladspa_path.empty())
239 ladspa_path += standard_paths[i];
243 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_path));
245 ladspa_discover_from_path (ladspa_path);
250 PluginManager::add_ladspa_directory (string path)
252 if (ladspa_discover_from_path (path) == 0) {
260 static bool ladspa_filter (const string& str, void */*arg*/)
262 /* Not a dotfile, has a prefix before a period, suffix is "so" */
264 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
268 PluginManager::ladspa_discover_from_path (string /*path*/)
271 vector<string *> *plugin_objects;
272 vector<string *>::iterator x;
275 plugin_objects = scanner (ladspa_path, ladspa_filter, 0, false, true);
277 if (plugin_objects) {
278 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
279 ladspa_discover (**x);
283 vector_delete (plugin_objects);
287 static bool rdf_filter (const string &str, void* /*arg*/)
289 return str[0] != '.' &&
290 ((str.find(".rdf") == (str.length() - 4)) ||
291 (str.find(".rdfs") == (str.length() - 5)) ||
292 (str.find(".n3") == (str.length() - 3)) ||
293 (str.find(".ttl") == (str.length() - 4)));
297 PluginManager::add_ladspa_presets()
299 add_presets ("ladspa");
303 PluginManager::add_windows_vst_presets()
305 add_presets ("windows-vst");
309 PluginManager::add_lxvst_presets()
311 add_presets ("lxvst");
315 PluginManager::add_presets(string domain)
319 vector<string *> *presets;
320 vector<string *>::iterator x;
323 if ((envvar = getenv ("HOME")) == 0) {
327 string path = string_compose("%1/.%2/rdf", envvar, domain);
328 presets = scanner (path, rdf_filter, 0, false, true);
331 for (x = presets->begin(); x != presets->end (); ++x) {
332 string file = "file:" + **x;
333 if (lrdf_read_file(file.c_str())) {
334 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
339 vector_delete (presets);
343 PluginManager::add_lrdf_data (const string &path)
346 vector<string *>* rdf_files;
347 vector<string *>::iterator x;
349 rdf_files = scanner (path, rdf_filter, 0, false, true);
352 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
353 const string uri(string("file://") + **x);
355 if (lrdf_read_file(uri.c_str())) {
356 warning << "Could not parse rdf file: " << uri << endmsg;
361 vector_delete (rdf_files);
365 PluginManager::ladspa_discover (string path)
368 const LADSPA_Descriptor *descriptor;
369 LADSPA_Descriptor_Function dfunc;
372 if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
373 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
377 dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor");
379 if ((errstr = dlerror()) != 0) {
380 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
381 error << errstr << endmsg;
386 for (uint32_t i = 0; ; ++i) {
387 if ((descriptor = dfunc (i)) == 0) {
391 if (!ladspa_plugin_whitelist.empty()) {
392 if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
397 PluginInfoPtr info(new LadspaPluginInfo);
398 info->name = descriptor->Name;
399 info->category = get_ladspa_category(descriptor->UniqueID);
400 info->creator = descriptor->Maker;
403 info->n_inputs = ChanCount();
404 info->n_outputs = ChanCount();
405 info->type = ARDOUR::LADSPA;
408 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
409 info->unique_id = buf;
411 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
412 if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
413 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
414 info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
416 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
417 info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
422 if(_ladspa_plugin_info->empty()){
423 _ladspa_plugin_info->push_back (info);
426 //Ensure that the plugin is not already in the plugin list.
430 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
431 if(0 == info->unique_id.compare((*i)->unique_id)){
437 _ladspa_plugin_info->push_back (info);
441 // GDB WILL NOT LIKE YOU IF YOU DO THIS
448 PluginManager::get_ladspa_category (uint32_t plugin_id)
451 lrdf_statement pattern;
453 snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
454 pattern.subject = buf;
455 pattern.predicate = const_cast<char*>(RDF_TYPE);
457 pattern.object_type = lrdf_uri;
459 lrdf_statement* matches1 = lrdf_matches (&pattern);
465 pattern.subject = matches1->object;
466 pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
468 pattern.object_type = lrdf_literal;
470 lrdf_statement* matches2 = lrdf_matches (&pattern);
471 lrdf_free_statements(matches1);
477 string label = matches2->object;
478 lrdf_free_statements(matches2);
480 /* Kludge LADSPA class names to be singular and match LV2 class names.
481 This avoids duplicate plugin menus for every class, which is necessary
482 to make the plugin category menu at all usable, but is obviously a
485 In the short term, lrdf could be updated so the labels match and a new
486 release made. To support both specs, we should probably be mapping the
487 URIs to the same category in code and perhaps tweaking that hierarchy
488 dynamically to suit the user. Personally, I (drobilla) think that time
489 is better spent replacing the little-used LRDF.
491 In the longer term, we will abandon LRDF entirely in favour of LV2 and
492 use that class hierarchy. Aside from fixing this problem properly, that
493 will also allow for translated labels. SWH plugins have been LV2 for
494 ages; TAP needs porting. I don't know of anything else with LRDF data.
496 if (label == "Utilities") {
498 } else if (label == "Pitch shifters") {
499 return "Pitch Shifter";
500 } else if (label != "Dynamics" && label != "Chorus"
501 &&label[label.length() - 1] == 's'
502 && label[label.length() - 2] != 's') {
503 return label.substr(0, label.length() - 1);
511 PluginManager::lv2_refresh ()
513 DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
514 delete _lv2_plugin_info;
515 _lv2_plugin_info = LV2PluginInfo::discover();
519 #ifdef AUDIOUNIT_SUPPORT
521 PluginManager::au_refresh ()
523 DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
524 delete _au_plugin_info;
525 _au_plugin_info = AUPluginInfo::discover();
530 #ifdef WINDOWS_VST_SUPPORT
533 PluginManager::windows_vst_refresh ()
535 if (_windows_vst_plugin_info) {
536 _windows_vst_plugin_info->clear ();
538 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
541 if (windows_vst_path.length() == 0) {
542 windows_vst_path = "/usr/local/lib/vst:/usr/lib/vst";
545 windows_vst_discover_from_path (windows_vst_path);
549 PluginManager::add_windows_vst_directory (string path)
551 if (windows_vst_discover_from_path (path) == 0) {
552 windows_vst_path += ':';
553 windows_vst_path += path;
559 static bool windows_vst_filter (const string& str, void *arg)
561 /* Not a dotfile, has a prefix before a period, suffix is "dll" */
563 return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
567 PluginManager::windows_vst_discover_from_path (string path)
570 vector<string *> *plugin_objects;
571 vector<string *>::iterator x;
574 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
576 plugin_objects = scanner (windows_vst_path, windows_vst_filter, 0, false, true);
578 if (plugin_objects) {
579 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
580 windows_vst_discover (**x);
584 vector_delete (plugin_objects);
589 PluginManager::windows_vst_discover (string path)
594 if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
595 warning << "Cannot get Windows VST information from " << path << endmsg;
599 if (!finfo->canProcessReplacing) {
600 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
601 finfo->name, PROGRAM_NAME)
605 PluginInfoPtr info (new WindowsVSTPluginInfo);
607 /* what a joke freeware VST is */
609 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
610 info->name = PBD::basename_nosuffix (path);
612 info->name = finfo->name;
616 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
617 info->unique_id = buf;
618 info->category = "VST";
620 info->creator = finfo->creator;
622 info->n_inputs.set_audio (finfo->numInputs);
623 info->n_outputs.set_audio (finfo->numOutputs);
624 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
625 info->type = ARDOUR::Windows_VST;
627 _windows_vst_plugin_info->push_back (info);
628 fst_free_info (finfo);
633 #endif // WINDOWS_VST_SUPPORT
638 PluginManager::lxvst_refresh ()
640 if (_lxvst_plugin_info) {
641 _lxvst_plugin_info->clear ();
643 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
646 if (lxvst_path.length() == 0) {
647 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst";
650 lxvst_discover_from_path (lxvst_path);
654 PluginManager::add_lxvst_directory (string path)
656 if (lxvst_discover_from_path (path) == 0) {
664 static bool lxvst_filter (const string& str, void *)
666 /* Not a dotfile, has a prefix before a period, suffix is "so" */
668 return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
672 PluginManager::lxvst_discover_from_path (string path)
675 vector<string *> *plugin_objects;
676 vector<string *>::iterator x;
679 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
681 plugin_objects = scanner (lxvst_path, lxvst_filter, 0, false, true);
683 if (plugin_objects) {
684 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
685 lxvst_discover (**x);
689 vector_delete (plugin_objects);
694 PluginManager::lxvst_discover (string path)
699 if ((finfo = vstfx_get_info (const_cast<char *> (path.c_str()))) == 0) {
703 if (!finfo->canProcessReplacing) {
704 warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
705 finfo->name, PROGRAM_NAME)
709 PluginInfoPtr info(new LXVSTPluginInfo);
711 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
712 info->name = PBD::basename_nosuffix (path);
714 info->name = finfo->name;
718 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
719 info->unique_id = buf;
720 info->category = "linuxVSTs";
722 info->creator = finfo->creator;
724 info->n_inputs.set_audio (finfo->numInputs);
725 info->n_outputs.set_audio (finfo->numOutputs);
726 info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
727 info->type = ARDOUR::LXVST;
729 /* Make sure we don't find the same plugin in more than one place along
730 the LXVST_PATH We can't use a simple 'find' because the path is included
731 in the PluginInfo, and that is the one thing we can be sure MUST be
732 different if a duplicate instance is found. So we just compare the type
733 and unique ID (which for some VSTs isn't actually unique...)
736 if (!_lxvst_plugin_info->empty()) {
737 for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
738 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
739 warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
740 vstfx_free_info(finfo);
746 _lxvst_plugin_info->push_back (info);
747 vstfx_free_info (finfo);
752 #endif // LXVST_SUPPORT
755 PluginManager::PluginStatusType
756 PluginManager::get_status (const PluginInfoPtr& pi)
758 PluginStatus ps (pi->type, pi->unique_id);
759 PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
760 if (i == statuses.end() ) {
768 PluginManager::save_statuses ()
771 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
773 ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
779 for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
791 ofs << "Windows-VST";
800 switch ((*i).status) {
813 ofs << (*i).unique_id;;
821 PluginManager::load_statuses ()
823 std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
824 ifstream ifs (path.c_str());
834 PluginStatusType status;
851 /* rest of the line is the plugin ID */
853 ifs.getline (buf, sizeof (buf), '\n');
858 if (sstatus == "Normal") {
860 } else if (sstatus == "Favorite") {
862 } else if (sstatus == "Hidden") {
865 error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
871 if (stype == "LADSPA") {
873 } else if (stype == "AudioUnit") {
875 } else if (stype == "LV2") {
877 } else if (stype == "Windows-VST") {
879 } else if (stype == "LXVST") {
882 error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
888 strip_whitespace_edges (id);
889 set_status (type, id, status);
896 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
898 PluginStatus ps (t, id, status);
901 if (status == Normal) {
905 statuses.insert (ps);
908 ARDOUR::PluginInfoList&
909 PluginManager::windows_vst_plugin_info ()
911 #ifdef WINDOWS_VST_SUPPORT
912 if (!_windows_vst_plugin_info) {
913 windows_vst_refresh ();
915 return *_windows_vst_plugin_info;
917 return _empty_plugin_info;
921 ARDOUR::PluginInfoList&
922 PluginManager::lxvst_plugin_info ()
925 if (!_lxvst_plugin_info)
927 return *_lxvst_plugin_info;
929 return _empty_plugin_info;
933 ARDOUR::PluginInfoList&
934 PluginManager::ladspa_plugin_info ()
936 if (!_ladspa_plugin_info)
938 return *_ladspa_plugin_info;
941 ARDOUR::PluginInfoList&
942 PluginManager::lv2_plugin_info ()
945 if (!_lv2_plugin_info)
947 return *_lv2_plugin_info;
949 return _empty_plugin_info;
953 ARDOUR::PluginInfoList&
954 PluginManager::au_plugin_info ()
956 #ifdef AUDIOUNIT_SUPPORT
957 if (!_au_plugin_info)
959 return *_au_plugin_info;
961 return _empty_plugin_info;