X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fplugin_manager.cc;h=8d4e6258767617cc3b427bf74fb042c3f2bad457;hb=9cbe231b920d92a2e44e08962a3ed6870b962f34;hp=02cba7dd9413b70f36477407d740b18899553ed8;hpb=8ae580427987b4eefc102f3e801c1b76fdc74d48;p=ardour.git diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 02cba7dd94..8d4e625876 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2006 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,47 +17,105 @@ */ -#define __STDC_FORMAT_MACROS 1 +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + #include #include #include +#include +#include + +#ifdef HAVE_LRDF #include -#include +#endif -#ifdef VST_SUPPORT -#include -#include -#include -#endif // VST_SUPPORT +#ifdef WINDOWS_VST_SUPPORT +#include "fst.h" +#include "pbd/basename.h" +#include +#endif // WINDOWS_VST_SUPPORT + +#ifdef LXVST_SUPPORT +#include "ardour/linux_vst_support.h" +#include "pbd/basename.h" +#include +#endif //LXVST_SUPPORT + +#include +#include + +#include "pbd/pathscanner.h" +#include "pbd/whitespace.h" +#include "pbd/file_utils.h" + +#include "ardour/debug.h" +#include "ardour/filesystem_paths.h" +#include "ardour/ladspa.h" +#include "ardour/ladspa_plugin.h" +#include "ardour/plugin.h" +#include "ardour/plugin_manager.h" +#include "ardour/rc_configuration.h" + +#ifdef SearchPath +#undef SearchPath +#endif -#include +#include "ardour/ladspa_search_path.h" + +#ifdef LV2_SUPPORT +#include "ardour/lv2_plugin.h" +#endif + +#ifdef WINDOWS_VST_SUPPORT +#include "ardour/windows_vst_plugin.h" +#endif -#include -#include -#include -#include -#include +#ifdef LXVST_SUPPORT +#include "ardour/lxvst_plugin.h" +#endif -#ifdef VST_SUPPORT -#include +#ifdef AUDIOUNIT_SUPPORT +#include "ardour/audio_unit.h" +#include #endif -#include -#include +#include "pbd/error.h" +#include "pbd/stl_delete.h" #include "i18n.h" +#include "ardour/debug.h" + using namespace ARDOUR; using namespace PBD; +using namespace std; -PluginManager* PluginManager::_manager = 0; +PluginManager* PluginManager::_instance = 0; + +PluginManager& +PluginManager::instance() +{ + if (!_instance) { + _instance = new PluginManager; + } + return *_instance; +} PluginManager::PluginManager () + : _windows_vst_plugin_info(0) + , _lxvst_plugin_info(0) + , _ladspa_plugin_info(0) + , _lv2_plugin_info(0) + , _au_plugin_info(0) { char* s; string lrdf_path; + load_statuses (); + if ((s = getenv ("LADSPA_RDF_PATH"))){ lrdf_path = s; } @@ -68,95 +126,127 @@ PluginManager::PluginManager () add_lrdf_data(lrdf_path); add_ladspa_presets(); -#ifdef VST_SUPPORT - if (Config->get_use_vst()) { - add_vst_presets(); +#ifdef WINDOWS_VST_SUPPORT + if (Config->get_use_windows_vst ()) { + add_windows_vst_presets (); } -#endif /* VST_SUPPORT */ +#endif /* WINDOWS_VST_SUPPORT */ - if ((s = getenv ("LADSPA_PATH"))) { - ladspa_path = s; +#ifdef LXVST_SUPPORT + if (Config->get_use_lxvst()) { + add_lxvst_presets(); } +#endif /* Native LinuxVST support*/ if ((s = getenv ("VST_PATH"))) { - vst_path = s; + windows_vst_path = s; } else if ((s = getenv ("VST_PLUGINS"))) { - vst_path = s; + windows_vst_path = s; + } + + if ((s = getenv ("LXVST_PATH"))) { + lxvst_path = s; + } else if ((s = getenv ("LXVST_PLUGINS"))) { + lxvst_path = s; } - refresh (); - if (_manager == 0) { - _manager = this; + if (_instance == 0) { + _instance = this; } + + /* the plugin manager is constructed too early to use Profile */ + + if (getenv ("ARDOUR_SAE")) { + ladspa_plugin_whitelist.push_back (1203); // single band parametric + ladspa_plugin_whitelist.push_back (1772); // caps compressor + ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter + ladspa_plugin_whitelist.push_back (1075); // simple RMS expander + ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s) + ladspa_plugin_whitelist.push_back (1216); // gverb + ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter + } + + BootMessage (_("Discovering Plugins")); } + +PluginManager::~PluginManager() +{ +} + + void PluginManager::refresh () { + DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n"); + ladspa_refresh (); -#ifdef VST_SUPPORT - if (Config->get_use_vst()) { - vst_refresh (); +#ifdef LV2_SUPPORT + lv2_refresh (); +#endif +#ifdef WINDOWS_VST_SUPPORT + if (Config->get_use_windows_vst()) { + windows_vst_refresh (); + } +#endif // WINDOWS_VST_SUPPORT + +#ifdef LXVST_SUPPORT + if(Config->get_use_lxvst()) { + lxvst_refresh(); } -#endif // VST_SUPPORT +#endif //Native linuxVST SUPPORT + +#ifdef AUDIOUNIT_SUPPORT + au_refresh (); +#endif + + PluginListChanged (); /* EMIT SIGNAL */ } void PluginManager::ladspa_refresh () { - _ladspa_plugin_info.clear (); - - if (ladspa_path.length() == 0) { - ladspa_path = "/usr/local/lib64/ladspa:/usr/local/lib/ladspa:/usr/lib64/ladspa:/usr/lib/ladspa:/Library/Audio/Plug-Ins/LADSPA"; + if (_ladspa_plugin_info) { + _ladspa_plugin_info->clear (); + } else { + _ladspa_plugin_info = new ARDOUR::PluginInfoList (); } - ladspa_discover_from_path (ladspa_path); -} + /* allow LADSPA_PATH to augment, not override standard locations */ -int -PluginManager::add_ladspa_directory (string path) -{ - if (ladspa_discover_from_path (path) == 0) { - ladspa_path += ':'; - ladspa_path += path; - return 0; - } - return -1; -} - -static bool ladspa_filter (const string& str, void *arg) -{ - /* Not a dotfile, has a prefix before a period, suffix is "so" */ + /* Only add standard locations to ladspa_path if it doesn't + * already contain them. Check for trailing G_DIR_SEPARATOR too. + */ - return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3)); -} + vector ladspa_modules; -int -PluginManager::ladspa_discover_from_path (string path) -{ - PathScanner scanner; - vector *plugin_objects; - vector::iterator x; - int ret = 0; + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string())); - plugin_objects = scanner (ladspa_path, ladspa_filter, 0, true, true); + Glib::PatternSpec so_extension_pattern("*.so"); + Glib::PatternSpec dylib_extension_pattern("*.dylib"); + Glib::PatternSpec dll_extension_pattern("*.dll"); - if (plugin_objects) { - for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - ladspa_discover (**x); - } - } + find_matching_files_in_search_path (ladspa_search_path (), + so_extension_pattern, ladspa_modules); - vector_delete (plugin_objects); - return ret; + find_matching_files_in_search_path (ladspa_search_path (), + dylib_extension_pattern, ladspa_modules); + + find_matching_files_in_search_path (ladspa_search_path (), + dll_extension_pattern, ladspa_modules); + + for (vector::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) { + ladspa_discover (*i); + } } -static bool rdf_filter (const string &str, void *arg) +static bool rdf_filter (const string &str, void* /*arg*/) { - return str[0] != '.' && + return str[0] != '.' && ((str.find(".rdf") == (str.length() - 4)) || (str.find(".rdfs") == (str.length() - 5)) || - (str.find(".n3") == (str.length() - 3))); + (str.find(".n3") == (str.length() - 3)) || + (str.find(".ttl") == (str.length() - 4))); } void @@ -166,14 +256,21 @@ PluginManager::add_ladspa_presets() } void -PluginManager::add_vst_presets() +PluginManager::add_windows_vst_presets() { - add_presets ("vst"); + add_presets ("windows-vst"); } + void -PluginManager::add_presets(string domain) +PluginManager::add_lxvst_presets() { + add_presets ("lxvst"); +} +void +PluginManager::add_presets(string domain) +{ +#ifdef HAVE_LRDF PathScanner scanner; vector *presets; vector::iterator x; @@ -184,7 +281,7 @@ PluginManager::add_presets(string domain) } string path = string_compose("%1/.%2/rdf", envvar, domain); - presets = scanner (path, rdf_filter, 0, true, true); + presets = scanner (path, rdf_filter, 0, false, true); if (presets) { for (x = presets->begin(); x != presets->end (); ++x) { @@ -193,71 +290,88 @@ PluginManager::add_presets(string domain) warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg; } } + + vector_delete (presets); } - - vector_delete (presets); +#endif } void PluginManager::add_lrdf_data (const string &path) { +#ifdef HAVE_LRDF PathScanner scanner; vector* rdf_files; vector::iterator x; - string uri; - rdf_files = scanner (path, rdf_filter, 0, true, true); + rdf_files = scanner (path, rdf_filter, 0, false, true); if (rdf_files) { for (x = rdf_files->begin(); x != rdf_files->end (); ++x) { - uri = "file://" + **x; + const string uri(string("file://") + **x); if (lrdf_read_file(uri.c_str())) { warning << "Could not parse rdf file: " << uri << endmsg; } } - } - vector_delete (rdf_files); + vector_delete (rdf_files); + } +#endif } -int +int PluginManager::ladspa_discover (string path) { - void *module; + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path)); + + Glib::Module module(path); const LADSPA_Descriptor *descriptor; LADSPA_Descriptor_Function dfunc; - const char *errstr; + void* func = 0; - if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg; + if (!module) { + error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), + path, Glib::Module::get_last_error()) << endmsg; return -1; } - dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor"); - if ((errstr = dlerror()) != 0) { + if (!module.get_symbol("ladspa_descriptor", func)) { error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg; - error << errstr << endmsg; - dlclose (module); + error << Glib::Module::get_last_error() << endmsg; return -1; } + dfunc = (LADSPA_Descriptor_Function)func; + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path)); + for (uint32_t i = 0; ; ++i) { if ((descriptor = dfunc (i)) == 0) { break; } + if (!ladspa_plugin_whitelist.empty()) { + if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) { + continue; + } + } + PluginInfoPtr info(new LadspaPluginInfo); info->name = descriptor->Name; info->category = get_ladspa_category(descriptor->UniqueID); + info->creator = descriptor->Maker; info->path = path; info->index = i; info->n_inputs = ChanCount(); info->n_outputs = ChanCount(); info->type = ARDOUR::LADSPA; - info->unique_id = descriptor->UniqueID; - + + char buf[32]; + snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID); + info->unique_id = buf; + for (uint32_t n=0; n < descriptor->PortCount; ++n) { if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) { if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) { @@ -269,7 +383,25 @@ PluginManager::ladspa_discover (string path) } } - _ladspa_plugin_info.push_back (info); + if(_ladspa_plugin_info->empty()){ + _ladspa_plugin_info->push_back (info); + } + + //Ensure that the plugin is not already in the plugin list. + + bool found = false; + + for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) { + if(0 == info->unique_id.compare((*i)->unique_id)){ + found = true; + } + } + + if(!found){ + _ladspa_plugin_info->push_back (info); + } + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs)); } // GDB WILL NOT LIKE YOU IF YOU DO THIS @@ -281,23 +413,24 @@ PluginManager::ladspa_discover (string path) string PluginManager::get_ladspa_category (uint32_t plugin_id) { +#ifdef HAVE_LRDF char buf[256]; lrdf_statement pattern; snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id); pattern.subject = buf; - pattern.predicate = RDF_TYPE; + pattern.predicate = const_cast(RDF_TYPE); pattern.object = 0; pattern.object_type = lrdf_uri; lrdf_statement* matches1 = lrdf_matches (&pattern); if (!matches1) { - return _("Unknown"); + return "Unknown"; } pattern.subject = matches1->object; - pattern.predicate = LADSPA_BASE "hasLabel"; + pattern.predicate = const_cast(LADSPA_BASE "hasLabel"); pattern.object = 0; pattern.object_type = lrdf_literal; @@ -305,41 +438,95 @@ PluginManager::get_ladspa_category (uint32_t plugin_id) lrdf_free_statements(matches1); if (!matches2) { - return _("Unknown"); + return ("Unknown"); } string label = matches2->object; lrdf_free_statements(matches2); - return label; + /* Kludge LADSPA class names to be singular and match LV2 class names. + This avoids duplicate plugin menus for every class, which is necessary + to make the plugin category menu at all usable, but is obviously a + filthy kludge. + + In the short term, lrdf could be updated so the labels match and a new + release made. To support both specs, we should probably be mapping the + URIs to the same category in code and perhaps tweaking that hierarchy + dynamically to suit the user. Personally, I (drobilla) think that time + is better spent replacing the little-used LRDF. + + In the longer term, we will abandon LRDF entirely in favour of LV2 and + use that class hierarchy. Aside from fixing this problem properly, that + will also allow for translated labels. SWH plugins have been LV2 for + ages; TAP needs porting. I don't know of anything else with LRDF data. + */ + if (label == "Utilities") { + return "Utility"; + } else if (label == "Pitch shifters") { + return "Pitch Shifter"; + } else if (label != "Dynamics" && label != "Chorus" + &&label[label.length() - 1] == 's' + && label[label.length() - 2] != 's') { + return label.substr(0, label.length() - 1); + } else { + return label; + } +#else + return ("Unknown"); +#endif +} + +#ifdef LV2_SUPPORT +void +PluginManager::lv2_refresh () +{ + DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n"); + delete _lv2_plugin_info; + _lv2_plugin_info = LV2PluginInfo::discover(); +} +#endif + +#ifdef AUDIOUNIT_SUPPORT +void +PluginManager::au_refresh () +{ + DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n"); + delete _au_plugin_info; + _au_plugin_info = AUPluginInfo::discover(); } -#ifdef VST_SUPPORT +#endif + +#ifdef WINDOWS_VST_SUPPORT void -PluginManager::vst_refresh () +PluginManager::windows_vst_refresh () { - _vst_plugin_info.clear (); + if (_windows_vst_plugin_info) { + _windows_vst_plugin_info->clear (); + } else { + _windows_vst_plugin_info = new ARDOUR::PluginInfoList(); + } - if (vst_path.length() == 0) { - vst_path = "/usr/local/lib/vst:/usr/lib/vst"; + if (windows_vst_path.length() == 0) { + windows_vst_path = "/usr/local/lib/vst:/usr/lib/vst"; } - vst_discover_from_path (vst_path); + windows_vst_discover_from_path (windows_vst_path); } int -PluginManager::add_vst_directory (string path) +PluginManager::add_windows_vst_directory (string path) { - if (vst_discover_from_path (path) == 0) { - vst_path += ':'; - vst_path += path; + if (windows_vst_discover_from_path (path) == 0) { + windows_vst_path += ':'; + windows_vst_path += path; return 0; - } + } return -1; } -static bool vst_filter (const string& str, void *arg) +static bool windows_vst_filter (const string& str, void *arg) { /* Not a dotfile, has a prefix before a period, suffix is "dll" */ @@ -347,46 +534,48 @@ static bool vst_filter (const string& str, void *arg) } int -PluginManager::vst_discover_from_path (string path) +PluginManager::windows_vst_discover_from_path (string path) { PathScanner scanner; vector *plugin_objects; vector::iterator x; int ret = 0; - info << "detecting VST plugins along " << path << endmsg; + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path)); - plugin_objects = scanner (vst_path, vst_filter, 0, true, true); + plugin_objects = scanner (windows_vst_path, windows_vst_filter, 0, false, true); if (plugin_objects) { for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - vst_discover (**x); + windows_vst_discover (**x); } + + vector_delete (plugin_objects); } - vector_delete (plugin_objects); return ret; } int -PluginManager::vst_discover (string path) +PluginManager::windows_vst_discover (string path) { - FSTInfo* finfo; + VSTInfo* finfo; + char buf[32]; if ((finfo = fst_get_info (const_cast (path.c_str()))) == 0) { - warning << "Cannot get VST information from " << path << endmsg; + warning << "Cannot get Windows VST information from " << path << endmsg; return -1; } if (!finfo->canProcessReplacing) { - warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in ardour at this time"), - finfo->name) + warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"), + finfo->name, PROGRAM_NAME) << endl; } - - PluginInfoPtr info(new VSTPluginInfo); - /* what a goddam joke freeware VST is */ + PluginInfoPtr info (new WindowsVSTPluginInfo); + + /* what a joke freeware VST is */ if (!strcasecmp ("The Unnamed plugin", finfo->name)) { info->name = PBD::basename_nosuffix (path); @@ -394,17 +583,355 @@ PluginManager::vst_discover (string path) info->name = finfo->name; } + + snprintf (buf, sizeof (buf), "%d", finfo->UniqueID); + info->unique_id = buf; info->category = "VST"; info->path = path; + info->creator = finfo->creator; info->index = 0; - info->n_inputs = finfo->numInputs; - info->n_outputs = finfo->numOutputs; - info->type = ARDOUR::VST; - - _vst_plugin_info.push_back (info); + info->n_inputs.set_audio (finfo->numInputs); + info->n_outputs.set_audio (finfo->numOutputs); + info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0); + info->type = ARDOUR::Windows_VST; + + _windows_vst_plugin_info->push_back (info); fst_free_info (finfo); return 0; } -#endif // VST_SUPPORT +#endif // WINDOWS_VST_SUPPORT + +#ifdef LXVST_SUPPORT + +void +PluginManager::lxvst_refresh () +{ + if (_lxvst_plugin_info) { + _lxvst_plugin_info->clear (); + } else { + _lxvst_plugin_info = new ARDOUR::PluginInfoList(); + } + + if (lxvst_path.length() == 0) { + lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst"; + } + + lxvst_discover_from_path (lxvst_path); +} + +int +PluginManager::add_lxvst_directory (string path) +{ + if (lxvst_discover_from_path (path) == 0) { + lxvst_path += ':'; + lxvst_path += path; + return 0; + } + return -1; +} + +static bool lxvst_filter (const string& str, void *) +{ + /* Not a dotfile, has a prefix before a period, suffix is "so" */ + + return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3)); +} + +int +PluginManager::lxvst_discover_from_path (string path) +{ + PathScanner scanner; + vector *plugin_objects; + vector::iterator x; + int ret = 0; + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path)); + + plugin_objects = scanner (lxvst_path, lxvst_filter, 0, false, true); + + if (plugin_objects) { + for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { + lxvst_discover (**x); + } + + vector_delete (plugin_objects); + } + + return ret; +} + +int +PluginManager::lxvst_discover (string path) +{ + VSTInfo* finfo; + char buf[32]; + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path)); + + if ((finfo = vstfx_get_info (const_cast (path.c_str()))) == 0) { + return -1; + } + + if (!finfo->canProcessReplacing) { + warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"), + finfo->name, PROGRAM_NAME) + << endl; + } + + PluginInfoPtr info(new LXVSTPluginInfo); + + if (!strcasecmp ("The Unnamed plugin", finfo->name)) { + info->name = PBD::basename_nosuffix (path); + } else { + info->name = finfo->name; + } + + + snprintf (buf, sizeof (buf), "%d", finfo->UniqueID); + info->unique_id = buf; + info->category = "linuxVSTs"; + info->path = path; + info->creator = finfo->creator; + info->index = 0; + info->n_inputs.set_audio (finfo->numInputs); + info->n_outputs.set_audio (finfo->numOutputs); + info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0); + info->type = ARDOUR::LXVST; + + /* Make sure we don't find the same plugin in more than one place along + the LXVST_PATH We can't use a simple 'find' because the path is included + in the PluginInfo, and that is the one thing we can be sure MUST be + different if a duplicate instance is found. So we just compare the type + and unique ID (which for some VSTs isn't actually unique...) + */ + + if (!_lxvst_plugin_info->empty()) { + for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) { + if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) { + warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n"; + vstfx_free_info(finfo); + return 0; + } + } + } + + _lxvst_plugin_info->push_back (info); + vstfx_free_info (finfo); + + return 0; +} + +#endif // LXVST_SUPPORT + + +PluginManager::PluginStatusType +PluginManager::get_status (const PluginInfoPtr& pi) +{ + PluginStatus ps (pi->type, pi->unique_id); + PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps); + if (i == statuses.end() ) { + return Normal; + } else { + return i->status; + } +} + +void +PluginManager::save_statuses () +{ + ofstream ofs; + std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses"); + + ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc)); + + if (!ofs) { + return; + } + + for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) { + switch ((*i).type) { + case LADSPA: + ofs << "LADSPA"; + break; + case AudioUnit: + ofs << "AudioUnit"; + break; + case LV2: + ofs << "LV2"; + break; + case Windows_VST: + ofs << "Windows-VST"; + break; + case LXVST: + ofs << "LXVST"; + break; + } + + ofs << ' '; + + switch ((*i).status) { + case Normal: + ofs << "Normal"; + break; + case Favorite: + ofs << "Favorite"; + break; + case Hidden: + ofs << "Hidden"; + break; + } + + ofs << ' '; + ofs << (*i).unique_id;; + ofs << endl; + } + + ofs.close (); +} + +void +PluginManager::load_statuses () +{ + std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses"); + ifstream ifs (path.c_str()); + + if (!ifs) { + return; + } + + std::string stype; + std::string sstatus; + std::string id; + PluginType type; + PluginStatusType status; + char buf[1024]; + + while (ifs) { + + ifs >> stype; + if (!ifs) { + break; + + } + + ifs >> sstatus; + if (!ifs) { + break; + + } + + /* rest of the line is the plugin ID */ + + ifs.getline (buf, sizeof (buf), '\n'); + if (!ifs) { + break; + } + + if (sstatus == "Normal") { + status = Normal; + } else if (sstatus == "Favorite") { + status = Favorite; + } else if (sstatus == "Hidden") { + status = Hidden; + } else { + error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus) + << endmsg; + statuses.clear (); + break; + } + + if (stype == "LADSPA") { + type = LADSPA; + } else if (stype == "AudioUnit") { + type = AudioUnit; + } else if (stype == "LV2") { + type = LV2; + } else if (stype == "Windows-VST") { + type = Windows_VST; + } else if (stype == "LXVST") { + type = LXVST; + } else { + error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype) + << endmsg; + continue; + } + + id = buf; + strip_whitespace_edges (id); + set_status (type, id, status); + } + + ifs.close (); +} + +void +PluginManager::set_status (PluginType t, string id, PluginStatusType status) +{ + PluginStatus ps (t, id, status); + statuses.erase (ps); + + if (status == Normal) { + return; + } + + statuses.insert (ps); +} + +ARDOUR::PluginInfoList& +PluginManager::windows_vst_plugin_info () +{ +#ifdef WINDOWS_VST_SUPPORT + if (!_windows_vst_plugin_info) { + windows_vst_refresh (); + } + return *_windows_vst_plugin_info; +#else + return _empty_plugin_info; +#endif +} + +ARDOUR::PluginInfoList& +PluginManager::lxvst_plugin_info () +{ +#ifdef LXVST_SUPPORT + if (!_lxvst_plugin_info) + lxvst_refresh(); + return *_lxvst_plugin_info; +#else + return _empty_plugin_info; +#endif +} + +ARDOUR::PluginInfoList& +PluginManager::ladspa_plugin_info () +{ + if (!_ladspa_plugin_info) + ladspa_refresh(); + return *_ladspa_plugin_info; +} + +ARDOUR::PluginInfoList& +PluginManager::lv2_plugin_info () +{ +#ifdef LV2_SUPPORT + if (!_lv2_plugin_info) + lv2_refresh(); + return *_lv2_plugin_info; +#else + return _empty_plugin_info; +#endif +} + +ARDOUR::PluginInfoList& +PluginManager::au_plugin_info () +{ +#ifdef AUDIOUNIT_SUPPORT + if (!_au_plugin_info) + au_refresh(); + return *_au_plugin_info; +#else + return _empty_plugin_info; +#endif +}