X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fplugin_manager.cc;h=7c3eae538f9531fa9e17b20a2a796c2ebb4b3c6b;hb=70308f51747b5beeff99dec9f10490080f00b0c2;hp=8a4c36b10d31a6dad3f7fe2ceb81aaf5b3159755;hpb=2b9421fd391efcddde0be3397cb66e19b744a155;p=ardour.git diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 8a4c36b10d..7c3eae538f 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -33,17 +33,20 @@ #endif #ifdef WINDOWS_VST_SUPPORT +#include "ardour/vst_info_file.h" #include "fst.h" #include "pbd/basename.h" #include #endif // WINDOWS_VST_SUPPORT #ifdef LXVST_SUPPORT +#include "ardour/vst_info_file.h" #include "ardour/linux_vst_support.h" #include "pbd/basename.h" #include #endif //LXVST_SUPPORT +#include #include #include @@ -59,7 +62,7 @@ #include "ardour/plugin_manager.h" #include "ardour/rc_configuration.h" -#include "ardour/ladspa_search_path.h" +#include "ardour/search_paths.h" #ifdef LV2_SUPPORT #include "ardour/lv2_plugin.h" @@ -90,9 +93,10 @@ using namespace PBD; using namespace std; PluginManager* PluginManager::_instance = 0; +std::string PluginManager::scanner_bin_path = ""; PluginManager& -PluginManager::instance() +PluginManager::instance() { if (!_instance) { _instance = new PluginManager; @@ -106,10 +110,17 @@ PluginManager::PluginManager () , _ladspa_plugin_info(0) , _lv2_plugin_info(0) , _au_plugin_info(0) + , _cancel_scan(false) + , _cancel_timeout(false) { char* s; string lrdf_path; + string scan_p = Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"); + if (!PBD::find_file_in_search_path ( PBD::Searchpath(scan_p), "ardour-vst-scanner", scanner_bin_path)) { + PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << scan_p << endmsg; + } + load_statuses (); if ((s = getenv ("LADSPA_RDF_PATH"))){ @@ -140,26 +151,32 @@ PluginManager::PluginManager () windows_vst_path = s; } + if (windows_vst_path.length() == 0) { + windows_vst_path = vst_search_path (); + } + if ((s = getenv ("LXVST_PATH"))) { lxvst_path = s; } else if ((s = getenv ("LXVST_PLUGINS"))) { lxvst_path = s; } - if (_instance == 0) { - _instance = this; + if (lxvst_path.length() == 0) { + lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:" + "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:" + "/usr/lib/vst:/usr/local/lib/vst"; } - /* the plugin manager is constructed too early to use Profile */ + /* first time setup, use 'default' path */ + if (Config->get_plugin_path_lxvst() == X_("@default@")) { + Config->set_plugin_path_lxvst(get_default_lxvst_path()); + } + if (Config->get_plugin_path_vst() == X_("@default@")) { + Config->set_plugin_path_vst(get_default_windows_vst_path()); + } - 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 + if (_instance == 0) { + _instance = this; } BootMessage (_("Discovering Plugins")); @@ -170,33 +187,151 @@ PluginManager::~PluginManager() { } - void -PluginManager::refresh () +PluginManager::refresh (bool cache_only) { DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n"); + _cancel_scan = false; + BootMessage (_("Scanning LADSPA Plugins")); ladspa_refresh (); #ifdef LV2_SUPPORT + BootMessage (_("Scanning LV2 Plugins")); lv2_refresh (); #endif #ifdef WINDOWS_VST_SUPPORT if (Config->get_use_windows_vst()) { - windows_vst_refresh (); + BootMessage (_("Scanning Windows VST Plugins")); + windows_vst_refresh (cache_only); } #endif // WINDOWS_VST_SUPPORT #ifdef LXVST_SUPPORT if(Config->get_use_lxvst()) { - lxvst_refresh(); + BootMessage (_("Scanning Linux VST Plugins")); + lxvst_refresh(cache_only); } #endif //Native linuxVST SUPPORT #ifdef AUDIOUNIT_SUPPORT + BootMessage (_("Scanning AU Plugins")); au_refresh (); #endif + BootMessage (_("Plugin Scan Complete...")); PluginListChanged (); /* EMIT SIGNAL */ + PluginScanMessage(X_("closeme"), "", false); + _cancel_scan = false; +} + +void +PluginManager::cancel_plugin_scan () +{ + _cancel_scan = true; +} + +void +PluginManager::cancel_plugin_timeout () +{ + _cancel_timeout = true; +} + +void +PluginManager::clear_vst_cache () +{ + // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path() +#ifdef WINDOWS_VST_SUPPORT + { + PathScanner scanner; + vector *fsi_files; + + fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsi$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif + +#ifdef LXVST_SUPPORT + { + PathScanner scanner; + vector *fsi_files; + fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsi$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif + +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT) + { + string personal = get_personal_vst_info_cache_dir(); + PathScanner scanner; + vector *fsi_files; + fsi_files = scanner (personal, "\\.fsi$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif +} + +void +PluginManager::clear_vst_blacklist () +{ +#ifdef WINDOWS_VST_SUPPORT + { + PathScanner scanner; + vector *fsi_files; + + fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsb$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif + +#ifdef LXVST_SUPPORT + { + PathScanner scanner; + vector *fsi_files; + fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsb$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif + +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT) + { + string personal = get_personal_vst_blacklist_dir(); + + PathScanner scanner; + vector *fsi_files; + fsi_files = scanner (personal, "\\.fsb$", true, true, -1, false); + if (fsi_files) { + for (vector::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) { + ::g_unlink((*i)->c_str()); + } + } + vector_delete(fsi_files); + } +#endif } void @@ -213,7 +348,7 @@ PluginManager::ladspa_refresh () /* Only add standard locations to ladspa_path if it doesn't * already contain them. Check for trailing G_DIR_SEPARATOR too. */ - + vector ladspa_modules; DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string())); @@ -227,11 +362,12 @@ PluginManager::ladspa_refresh () 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) { + ARDOUR::PluginScanMessage(_("LADSPA"), *i, false); ladspa_discover (*i); } } @@ -286,7 +422,7 @@ PluginManager::add_presets(string domain) warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg; } } - + vector_delete (presets); } #endif @@ -496,7 +632,7 @@ PluginManager::au_refresh () #ifdef WINDOWS_VST_SUPPORT void -PluginManager::windows_vst_refresh () +PluginManager::windows_vst_refresh (bool cache_only) { if (_windows_vst_plugin_info) { _windows_vst_plugin_info->clear (); @@ -504,25 +640,10 @@ PluginManager::windows_vst_refresh () _windows_vst_plugin_info = new ARDOUR::PluginInfoList(); } - if (windows_vst_path.length() == 0) { - windows_vst_path = "/usr/local/lib/vst:/usr/lib/vst"; - } - - windows_vst_discover_from_path (windows_vst_path); + windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only); } -int -PluginManager::add_windows_vst_directory (string path) -{ - if (windows_vst_discover_from_path (path) == 0) { - windows_vst_path += ':'; - windows_vst_path += path; - return 0; - } - return -1; -} - -static bool windows_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" */ @@ -530,7 +651,7 @@ static bool windows_vst_filter (const string& str, void *arg) } int -PluginManager::windows_vst_discover_from_path (string path) +PluginManager::windows_vst_discover_from_path (string path, bool cache_only) { PathScanner scanner; vector *plugin_objects; @@ -539,11 +660,12 @@ PluginManager::windows_vst_discover_from_path (string path) DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path)); - plugin_objects = scanner (windows_vst_path, windows_vst_filter, 0, false, true); + plugin_objects = scanner (Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true); if (plugin_objects) { for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - windows_vst_discover (**x); + ARDOUR::PluginScanMessage(_("VST"), **x, !cache_only && !cancelled()); + windows_vst_discover (**x, cache_only || cancelled()); } vector_delete (plugin_objects); @@ -553,48 +675,76 @@ PluginManager::windows_vst_discover_from_path (string path) } int -PluginManager::windows_vst_discover (string path) +PluginManager::windows_vst_discover (string path, bool cache_only) { - VSTInfo* finfo; - char buf[32]; + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path)); + + _cancel_timeout = false; + vector * finfos = vstfx_get_info_fst (const_cast (path.c_str()), + cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP); - if ((finfo = fst_get_info (const_cast (path.c_str()))) == 0) { - warning << "Cannot get Windows VST information from " << path << endmsg; + if (finfos->empty()) { + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path)); return -1; } - if (!finfo->canProcessReplacing) { - 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; - } + uint32_t discovered = 0; + for (vector::iterator x = finfos->begin(); x != finfos->end(); ++x) { + VSTInfo* finfo = *x; + char buf[32]; - PluginInfoPtr info (new WindowsVSTPluginInfo); + if (!finfo->canProcessReplacing) { + 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; + continue; + } - /* what a joke freeware VST is */ + PluginInfoPtr info (new WindowsVSTPluginInfo); - if (!strcasecmp ("The Unnamed plugin", finfo->name)) { - info->name = PBD::basename_nosuffix (path); - } else { - info->name = finfo->name; - } + /* what a joke freeware VST is */ + 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 = "VST"; - 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::Windows_VST; - _windows_vst_plugin_info->push_back (info); - fst_free_info (finfo); + 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.set_audio (finfo->numInputs); + info->n_outputs.set_audio (finfo->numOutputs); + info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0); + info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0); + info->type = ARDOUR::Windows_VST; + + // TODO: check dup-IDs (lxvst AND windows vst) + bool duplicate = false; + + if (!_windows_vst_plugin_info->empty()) { + for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) { + if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) { + warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n"; + duplicate = true; + break; + } + } + } - return 0; + if (!duplicate) { + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id)); + _windows_vst_plugin_info->push_back (info); + discovered++; + } + } + + vstfx_free_info_list (finfos); + return discovered > 0 ? 0 : -1; } #endif // WINDOWS_VST_SUPPORT @@ -602,7 +752,7 @@ PluginManager::windows_vst_discover (string path) #ifdef LXVST_SUPPORT void -PluginManager::lxvst_refresh () +PluginManager::lxvst_refresh (bool cache_only) { if (_lxvst_plugin_info) { _lxvst_plugin_info->clear (); @@ -610,23 +760,7 @@ PluginManager::lxvst_refresh () _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" - "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst"; - } - - 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; + lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only); } static bool lxvst_filter (const string& str, void *) @@ -637,7 +771,7 @@ static bool lxvst_filter (const string& str, void *) } int -PluginManager::lxvst_discover_from_path (string path) +PluginManager::lxvst_discover_from_path (string path, bool cache_only) { PathScanner scanner; vector *plugin_objects; @@ -650,11 +784,12 @@ PluginManager::lxvst_discover_from_path (string path) DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path)); - plugin_objects = scanner (lxvst_path, lxvst_filter, 0, false, true); + plugin_objects = scanner (Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true); if (plugin_objects) { for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - lxvst_discover (**x); + ARDOUR::PluginScanMessage(_("LXVST"), **x, !cache_only && !cancelled()); + lxvst_discover (**x, cache_only || cancelled()); } vector_delete (plugin_objects); @@ -664,64 +799,79 @@ PluginManager::lxvst_discover_from_path (string path) } int -PluginManager::lxvst_discover (string path) +PluginManager::lxvst_discover (string path, bool cache_only) { - 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) { + _cancel_timeout = false; + vector * finfos = vstfx_get_info_lx (const_cast (path.c_str()), + cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP); + + if (finfos->empty()) { + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path)); 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; - } + uint32_t discovered = 0; + for (vector::iterator x = finfos->begin(); x != finfos->end(); ++x) { + VSTInfo* finfo = *x; + char buf[32]; - PluginInfoPtr info(new LXVSTPluginInfo); + 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; + continue; + } - 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; + 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) ? 1 : 0); + info->n_outputs.set_midi ((finfo->wantMidi&2) ? 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...) + */ + + // TODO: check dup-IDs with windowsVST, too + bool duplicate = false; + 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"; + duplicate = true; + break; + } } } + + if (!duplicate) { + _lxvst_plugin_info->push_back (info); + discovered++; + } } - - _lxvst_plugin_info->push_back (info); - vstfx_free_info (finfo); - return 0; + vstfx_free_info_list (finfos); + return discovered > 0 ? 0 : -1; } #endif // LXVST_SUPPORT @@ -897,8 +1047,7 @@ ARDOUR::PluginInfoList& PluginManager::lxvst_plugin_info () { #ifdef LXVST_SUPPORT - if (!_lxvst_plugin_info) - lxvst_refresh(); + assert(_lxvst_plugin_info); return *_lxvst_plugin_info; #else return _empty_plugin_info; @@ -908,8 +1057,7 @@ PluginManager::lxvst_plugin_info () ARDOUR::PluginInfoList& PluginManager::ladspa_plugin_info () { - if (!_ladspa_plugin_info) - ladspa_refresh(); + assert(_ladspa_plugin_info); return *_ladspa_plugin_info; } @@ -917,8 +1065,7 @@ ARDOUR::PluginInfoList& PluginManager::lv2_plugin_info () { #ifdef LV2_SUPPORT - if (!_lv2_plugin_info) - lv2_refresh(); + assert(_lv2_plugin_info); return *_lv2_plugin_info; #else return _empty_plugin_info; @@ -929,8 +1076,7 @@ ARDOUR::PluginInfoList& PluginManager::au_plugin_info () { #ifdef AUDIOUNIT_SUPPORT - if (!_au_plugin_info) - au_refresh(); + assert(_au_plugin_info); return *_au_plugin_info; #else return _empty_plugin_info;