PM: add support for interactive and partial plugin scan

This commit is contained in:
Robin Gareus 2021-06-13 17:02:00 +02:00
parent 349a41a448
commit 8014b9409e
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 314 additions and 3 deletions

View File

@ -100,6 +100,13 @@ public:
void scan_log (std::vector<boost::shared_ptr<PluginScanLogEntry> >&) const;
void clear_stale_log ();
bool whitelist (ARDOUR::PluginType, std::string const&, bool force);
void blacklist (ARDOUR::PluginType, std::string const&);
static std::string cache_file (ARDOUR::PluginType, std::string const&);
bool rescan_plugin (ARDOUR::PluginType, std::string const&, bool batch = false);
void rescan_faulty ();
/* always return LXVST for any VST subtype */
static PluginType to_generic_vst (const PluginType);
@ -124,7 +131,7 @@ public:
std::string user_plugin_metadata_dir () const;
void save_statuses ();
void set_status (ARDOUR::PluginType type, std::string unique_id, PluginStatusType status);
void set_status (ARDOUR::PluginType type, std::string const& unique_id, PluginStatusType status);
PluginStatusType get_status (const PluginInfoPtr&) const;
void save_tags ();
@ -283,6 +290,8 @@ private:
void detect_name_ambiguities (ARDOUR::PluginInfoList*);
void detect_type_ambiguities (ARDOUR::PluginInfoList&);
void detect_ambiguities ();
void conceal_duplicates (ARDOUR::PluginInfoList*, ARDOUR::PluginInfoList*);
void load_statuses ();

View File

@ -592,7 +592,12 @@ PluginManager::refresh (bool cache_only)
PluginScanMessage(X_("closeme"), "", false);
BootMessage (_("Indexing Plugins..."));
detect_ambiguities ();
}
void
PluginManager::detect_ambiguities ()
{
detect_name_ambiguities (_windows_vst_plugin_info);
detect_name_ambiguities (_lxvst_plugin_info);
detect_name_ambiguities (_mac_vst_plugin_info);
@ -1151,6 +1156,10 @@ PluginManager::auv2_plugin (CAComponentDescription const& desc, AUv2Info const&
int
PluginManager::auv2_discover (AUv2DescStr const& d, bool cache_only)
{
if (!d.valid ()) {
return -1;
}
std::string dstr = d.to_s ();
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking AU plugin at %1\n", dstr));
@ -2292,7 +2301,7 @@ PluginManager::load_statuses ()
}
void
PluginManager::set_status (PluginType t, string id, PluginStatusType status)
PluginManager::set_status (PluginType t, string const& id, PluginStatusType status)
{
PluginStatus ps (t, id, status);
statuses.erase (ps);
@ -2869,6 +2878,293 @@ PluginManager::lua_plugin_info ()
/* ****************************************************************************/
void
PluginManager::blacklist (ARDOUR::PluginType type, std::string const& path_uid)
{
PluginInfoList* pil = 0;
switch (type) {
case AudioUnit:
#ifdef AUDIOUNIT_SUPPORT
auv2_blacklist (path_uid);
pil = _au_plugin_info;
#endif
break;
case Windows_VST:
#ifdef WINDOWS_VST_SUPPORT
vst2_blacklist (path_uid);
pil = _windows_vst_plugin_info;
#endif
break;
case LXVST:
#ifdef LXVST_SUPPORT
vst2_blacklist (path_uid);
pil = _lxvst_plugin_info;
#endif
break;
case MacVST:
#ifdef MACVST_SUPPORT
vst2_blacklist (path_uid);
pil = _mac_vst_plugin_info;
#endif
break;
case VST3:
#ifdef VST3_SUPPORT
vst3_blacklist (path_uid);
pil = _vst3_plugin_info;
#endif
break;
default:
return;
}
PSLEPtr psle (scan_log_entry (type, path_uid));
psle->msg (PluginScanLogEntry::Blacklisted);
save_scanlog ();
if (!pil) {
return;
}
/* remove existing info */
PluginScanLog::iterator i = _plugin_scan_log.find (PSLEPtr (new PluginScanLogEntry (type, path_uid)));
if (i != _plugin_scan_log.end ()) {
PluginInfoList const& plugs ((*i)->nfo ());
for (PluginInfoList::const_iterator j = plugs.begin(); j != plugs.end(); ++j) {
PluginInfoList::const_iterator k = std::find (pil->begin(), pil->end(), *j);
if (k != pil->end()) {
pil->erase (k);
}
}
}
PluginListChanged (); /* EMIT SIGNAL */
}
bool
PluginManager::whitelist (ARDOUR::PluginType type, std::string const& path_uid, bool force)
{
if (!force) {
PluginScanLog::iterator i = _plugin_scan_log.find (PSLEPtr (new PluginScanLogEntry (type, path_uid)));
if (i == _plugin_scan_log.end ()) {
/* plugin was not found */
return false;
}
/* only allow manually blacklisted (no error) */
if ((*i)->result () != PluginScanLogEntry::Blacklisted) {
return false;
}
}
switch (type) {
case AudioUnit:
#ifdef AUDIOUNIT_SUPPORT
auv2_whitelist (path_uid);
return true;
#endif
break;
case Windows_VST:
case LXVST:
case MacVST:
#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
vst2_whitelist (path_uid);
return true;
#endif
break;
case VST3:
#ifdef VST3_SUPPORT
vst3_whitelist (path_uid);
return true;
#endif
break;
default:
break;
}
return false;
}
std::string
PluginManager::cache_file (ARDOUR::PluginType type, std::string const& path_uid)
{
std::string fn;
switch (type) {
case AudioUnit:
#ifdef AUDIOUNIT_SUPPORT
{
AUv2DescStr aud (path_uid);
fn = auv2_cache_file (aud.desc ());
}
#endif
break;
case Windows_VST:
case LXVST:
case MacVST:
#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
fn = ARDOUR::vst2_cache_file (path_uid);
#endif
break;
case VST3:
#ifdef VST3_SUPPORT
fn = ARDOUR::vst3_cache_file (path_uid);
#endif
break;
default:
break;
}
if (!fn.empty () && !Glib::file_test (fn, Glib::FileTest (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR))) {
return "";
}
return fn;
}
bool
PluginManager::rescan_plugin (ARDOUR::PluginType type, std::string const& path_uid, bool batch)
{
PluginInfoList* pil = 0;
switch (type) {
case AudioUnit:
pil = _au_plugin_info;
break;
case Windows_VST:
pil = _windows_vst_plugin_info;
break;
case LXVST:
pil = _lxvst_plugin_info;
break;
case MacVST:
pil = _mac_vst_plugin_info;
break;
case VST3:
pil = _vst3_plugin_info;
// XXX resolve VST module to bundle
// string module_path = module_path_vst3 (uid);
break;
case LADSPA:
pil = _ladspa_plugin_info;
break;
default:
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Invalid plugin type for rescan: %1\n", type));
return false;
}
if (!pil) {
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Rescan of '%1' without initial scan\n", type));
return false;
}
bool erased = false;
/* remove existing info */
PluginScanLog::iterator i = _plugin_scan_log.find (PSLEPtr (new PluginScanLogEntry (type, path_uid)));
if (i != _plugin_scan_log.end ()) {
PluginInfoList const& plugs ((*i)->nfo ());
for (PluginInfoList::const_iterator j = plugs.begin(); j != plugs.end(); ++j) {
PluginInfoList::const_iterator k = std::find (pil->begin(), pil->end(), *j);
if (k != pil->end()) {
pil->erase (k);
}
erased = true;
}
}
if (!batch) {
_cancel_scan = false;
_cancel_all_scan_timeout = false;
}
whitelist (type, path_uid, true);
_cancel_scan_timeout = false;
/* force re-scan, remove cache file */
std::string fn = cache_file ((*i)->type (), (*i)->path ());
if (!fn.empty ()) {
::g_unlink (fn.c_str ());
}
int rv = -1;
switch (type) {
case AudioUnit:
#ifdef AUDIOUNIT_SUPPORT
{
AUv2DescStr aud (path_uid);
ARDOUR::PluginScanMessage(_("AUv2"), aud.to_s(), !cancelled());
rv = auv2_discover (aud, false);
}
#endif
break;
case Windows_VST:
case LXVST:
case MacVST:
#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
ARDOUR::PluginScanMessage(_("VST2"), path_uid, !cancelled());
rv = vst2_discover (path_uid, type, false);
#endif
break;
case VST3:
#ifdef VST3_SUPPORT
ARDOUR::PluginScanMessage(_("VST3"), path_uid, !cancelled());
rv = vst3_discover (path_uid, false);
#endif
break;
case LADSPA:
ARDOUR::PluginScanMessage(_("LADSPA"), path_uid, !cancelled());
rv = ladspa_discover (path_uid);
break;
default:
return false;
}
if (batch) {
return (rv >= 0 || erased);
}
_cancel_scan = false;
if (rv < 0) {
save_scanlog ();
if (erased) {
PluginListChanged (); /* EMIT SIGNAL */
}
PluginScanMessage(X_("closeme"), "", false);
return false;
}
PluginScanMessage(X_("closeme"), "", false);
detect_ambiguities ();
return true;
}
void
PluginManager::rescan_faulty ()
{
bool changed = false;
/* rescan can change _plugin_scan_log, so we need to make a copy first */
PluginScanLog psl;
for (PluginScanLog::const_iterator i = _plugin_scan_log.begin(); i != _plugin_scan_log.end(); ++i) {
if (!(*i)->recent() || ((*i)->result() & PluginScanLogEntry::Faulty) != PluginScanLogEntry::OK) {
psl.insert (*i);
}
}
_cancel_scan = false;
_cancel_all_scan_timeout = false;
for (PluginScanLog::const_iterator i = psl.begin(); i != psl.end(); ++i) {
changed |= rescan_plugin ((*i)->type (), (*i)->path (), true);
if (cancelled ()) {
break;
}
}
_cancel_scan = false;
PluginScanMessage(X_("closeme"), "", false);
if (changed) {
detect_ambiguities ();
} else {
save_scanlog ();
}
}
/* ****************************************************************************/
void
PluginManager::scan_log (std::vector<boost::shared_ptr<PluginScanLogEntry> >& l) const
{
@ -2882,12 +3178,18 @@ PluginManager::clear_stale_log ()
{
for (PluginScanLog::const_iterator i = _plugin_scan_log.begin(); i != _plugin_scan_log.end();) {
if (!(*i)->recent()) {
whitelist ((*i)->type (), (*i)->path (), true);
std::string fn = cache_file ((*i)->type (), (*i)->path ());
if (!fn.empty ()) {
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("unlink stale cache: %1\n", fn));
::g_unlink (fn.c_str ());
}
i = _plugin_scan_log.erase (i);
// TODO also remove cache file (and blacklist entry)
} else {
++i;
}
}
save_scanlog ();
}
void