# HG changeset patch # User Chris Cannam # Date 1460638998 -3600 # Node ID 6b1af0f05f067846d30baf8ced184da38a9c36ca # Parent bf05d9259dbce1ebf451f6a527fa0c9484bfc926 Make use of, and warn for, the plugin checker for all types of plugin. Haven't yet resolved the question of how to install and find it. diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/DSSIPluginFactory.h --- a/plugin/DSSIPluginFactory.h Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/DSSIPluginFactory.h Thu Apr 14 14:03:18 2016 +0100 @@ -48,6 +48,10 @@ DSSIPluginFactory(); friend class RealTimePluginFactory; + virtual KnownPlugins::PluginType getPluginType() const { + return KnownPlugins::DSSIPlugin; + } + virtual std::vector getPluginPath(); virtual std::vector getLRDFPath(QString &baseUri); diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/FeatureExtractionPluginFactory.cpp --- a/plugin/FeatureExtractionPluginFactory.cpp Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/FeatureExtractionPluginFactory.cpp Thu Apr 14 14:03:18 2016 +0100 @@ -21,6 +21,8 @@ #include "system/System.h" +#include "PluginScan.h" + #include #include #include @@ -111,87 +113,14 @@ } vector -FeatureExtractionPluginFactory::getPluginCandidateFiles() -{ - vector path = getPluginPath(); - vector candidates; - - for (QString dirname : path) { - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::getPluginCandidateFiles: scanning directory " << dirname << endl; -#endif - - QDir pluginDir(dirname, PLUGIN_GLOB, - QDir::Name | QDir::IgnoreCase, - QDir::Files | QDir::Readable); - - for (unsigned int j = 0; j < pluginDir.count(); ++j) { - QString soname = pluginDir.filePath(pluginDir[j]); - candidates.push_back(soname); - } - } - - return candidates; -} - -vector -FeatureExtractionPluginFactory::winnowPluginCandidates(vector candidates, - QString &warningMessage) -{ - vector good, bad; - vector badStatuses; - - for (QString c: candidates) { - - PluginLoadStatus status = - TestPluginLoadability(c, "vampGetPluginDescriptor"); - - if (status == PluginLoadOK) { - good.push_back(c); - } else if (status == UnknownPluginLoadStatus) { - cerr << "WARNING: Unknown load status for plugin candidate \"" - << c << "\", continuing" << endl; - good.push_back(c); - } else { - bad.push_back(c); - badStatuses.push_back(status); - } - } - - if (!bad.empty()) { - warningMessage = - QObject::tr("Failed to load plugins" - "

Failed to load one or more plugin libraries:

\n"); - warningMessage += "
    "; - for (int i = 0; in_range_for(bad, i); ++i) { - QString m; - if (badStatuses[i] == PluginLoadFailedToLoadLibrary) { - m = QObject::tr("Failed to load library"); - } else if (badStatuses[i] == PluginLoadFailedToFindDescriptor) { - m = QObject::tr("Failed to query plugins from library after loading"); - } else if (badStatuses[i] == PluginLoadFailedElsewhere) { - m = QObject::tr("Unknown failure"); - } else { - m = QObject::tr("Success: internal error?"); - } - warningMessage += QString("
  • %1 (%2)
  • \n") - .arg(bad[i]) - .arg(m); - } - warningMessage += "
"; - } - return good; -} - -vector FeatureExtractionPluginFactory::getPluginIdentifiers() { Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers"); vector rv; - vector candidates = winnowPluginCandidates(getPluginCandidateFiles(), - m_pluginScanError); + + QStringList candidates = + PluginScan::getInstance()->getCandidateVampLibraries(); for (QString soname : candidates) { diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/FeatureExtractionPluginFactory.h --- a/plugin/FeatureExtractionPluginFactory.h Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/FeatureExtractionPluginFactory.h Thu Apr 14 14:03:18 2016 +0100 @@ -37,14 +37,6 @@ virtual std::vector getPluginPath(); virtual std::vector getPluginIdentifiers(); - - /** - * Return any error message arising from the initial plugin - * scan. The return value will either be an empty string (nothing - * to report) or an HTML string suitable for dropping into a - * dialog and showing the user. - */ - virtual QString getPluginPopulationWarning() { return m_pluginScanError; } virtual QString findPluginFile(QString soname, QString inDir = ""); @@ -66,13 +58,7 @@ void pluginDeleted(Vamp::Plugin *); std::map m_handleMap; - std::vector getPluginCandidateFiles(); - std::vector winnowPluginCandidates(std::vector candidates, - QString &warningMessage); - void generateTaxonomy(); - - QString m_pluginScanError; }; #endif diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/LADSPAPluginFactory.cpp --- a/plugin/LADSPAPluginFactory.cpp Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/LADSPAPluginFactory.cpp Thu Apr 14 14:03:18 2016 +0100 @@ -668,14 +668,11 @@ generateFallbackCategories(); - for (std::vector::iterator i = pathList.begin(); - i != pathList.end(); ++i) { + QStringList candidates = + PluginScan::getInstance()->getCandidateLibrariesFor(getPluginType()); - QDir pluginDir(*i, PLUGIN_GLOB); - - for (unsigned int j = 0; j < pluginDir.count(); ++j) { - discoverPluginsFrom(QString("%1/%2").arg(*i).arg(pluginDir[j])); - } + for (QString c: candidates) { + discoverPluginsFrom(c); } } diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/LADSPAPluginFactory.h --- a/plugin/LADSPAPluginFactory.h Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/LADSPAPluginFactory.h Thu Apr 14 14:03:18 2016 +0100 @@ -24,6 +24,8 @@ #include "RealTimePluginFactory.h" #include "api/ladspa.h" +#include "PluginScan.h" + #include #include #include @@ -63,6 +65,10 @@ LADSPAPluginFactory(); friend class RealTimePluginFactory; + virtual KnownPlugins::PluginType getPluginType() const { + return KnownPlugins::LADSPAPlugin; + } + virtual std::vector getPluginPath(); virtual std::vector getLRDFPath(QString &baseUri); diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/PluginScan.cpp --- a/plugin/PluginScan.cpp Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/PluginScan.cpp Thu Apr 14 14:03:18 2016 +0100 @@ -29,7 +29,7 @@ return m_instance; } -PluginScan::PluginScan() : m_kp(0) { +PluginScan::PluginScan() : m_kp(0), m_succeeded(false) { } PluginScan::~PluginScan() { @@ -46,44 +46,65 @@ PluginScan::scan() { delete m_kp; - m_kp = new KnownPlugins("./helper", this); //!!! + m_succeeded = false; + try { + m_kp = new KnownPlugins("./helper", this); //!!! + m_succeeded = true; + } catch (const std::exception &e) { + cerr << "ERROR: PluginScan::scan: " << e.what() << endl; + m_kp = 0; + } +} + +QStringList +PluginScan::getCandidateLibrariesFor(KnownPlugins::PluginType type) const +{ + QStringList candidates; + if (!m_kp) return candidates; + auto c = m_kp->getCandidateLibrariesFor(type); + for (auto s: c) candidates.push_back(s.c_str()); + return candidates; } QStringList PluginScan::getCandidateVampLibraries() const { - QStringList candidates; - if (!m_kp) return candidates; - auto c = m_kp->getCandidateLibrariesFor(KnownPlugins::VampPlugin); - for (auto s: c) candidates.push_back(s.c_str()); - return candidates; + return getCandidateLibrariesFor(KnownPlugins::VampPlugin); } QStringList PluginScan::getCandidateLADSPALibraries() const { - QStringList candidates; - if (!m_kp) return candidates; - auto c = m_kp->getCandidateLibrariesFor(KnownPlugins::LADSPAPlugin); - for (auto s: c) candidates.push_back(s.c_str()); - return candidates; + return getCandidateLibrariesFor(KnownPlugins::LADSPAPlugin); } QStringList PluginScan::getCandidateDSSILibraries() const { - QStringList candidates; - if (!m_kp) return candidates; - auto c = m_kp->getCandidateLibrariesFor(KnownPlugins::DSSIPlugin); - for (auto s: c) candidates.push_back(s.c_str()); - return candidates; + return getCandidateLibrariesFor(KnownPlugins::DSSIPlugin); } QString PluginScan::getStartupFailureReport() const { - if (!m_kp) return ""; //!!!??? + if (!m_succeeded) { + return QObject::tr("Failed to scan for plugins" + "

Failed to scan for plugins at startup " + "(application installation problem?)

"); + } + if (!m_kp) { + return QObject::tr("Did not scan for plugins" + "

Apparently no scan for plugins was attempted " + "(internal error?)

"); + } + string report = m_kp->getFailureReport(); - return report.c_str(); //!!! wrap? + if (report == "") { + return QString(report.c_str()); + } + + return QObject::tr("Failed to load plugins" + "

Failed to load one or more plugin libraries:

") + + QString(report.c_str()); } diff -r bf05d9259dbc -r 6b1af0f05f06 plugin/PluginScan.h --- a/plugin/PluginScan.h Thu Apr 14 12:12:04 2016 +0100 +++ b/plugin/PluginScan.h Thu Apr 14 14:03:18 2016 +0100 @@ -25,10 +25,13 @@ static PluginScan *getInstance(); void scan(); + + bool scanSucceeded() const; QStringList getCandidateVampLibraries() const; QStringList getCandidateLADSPALibraries() const; QStringList getCandidateDSSILibraries() const; + QStringList getCandidateLibrariesFor(KnownPlugins::PluginType) const; QString getStartupFailureReport() const; @@ -39,6 +42,7 @@ PluginScan(); ~PluginScan(); KnownPlugins *m_kp; + bool m_succeeded; }; #endif diff -r bf05d9259dbc -r 6b1af0f05f06 system/System.cpp --- a/system/System.cpp Thu Apr 14 12:12:04 2016 +0100 +++ b/system/System.cpp Thu Apr 14 14:03:18 2016 +0100 @@ -325,77 +325,3 @@ double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; } float princargf(float a) { return float(princarg(a)); } -#ifndef _WIN32 - -#include -#include - -PluginLoadStatus -TestPluginLoadability(QString soname, QString descriptorFn) -{ - //!!! This is POSIX only, no equivalent on Windows, where we'll - //!!! have to do something completely different - - //!!! update -- this is a bad idea on POSIX systems as well, I - //!!! fear, because fork() generally doesn't mix with - //!!! multithreaded processes (it forks only one thread but any - //!!! locked mutexes from the other threads remain locked). - - pid_t pid = fork(); - - if (pid < 0) { - return UnknownPluginLoadStatus; // fork failed - } - - if (pid == 0) { // the child process - - cerr << "isPluginLibraryLoadable: About to try library \"" << soname << "\"" << endl; - - void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL); - if (!handle) { - cerr << "isPluginLibraryLoadable: Failed to open plugin library \"" - << soname << "\": " << dlerror() << "\n"; - cerr << "exiting with status 1" << endl; - exit(1); - } - - void *fn = DLSYM(handle, descriptorFn.toLocal8Bit().data()); - if (!fn) { - cerr << "isPluginLibraryLoadable: Failed to find plugin descriptor function \"" << descriptorFn << "\" in library \"" << soname << "\": " << dlerror() << "\n"; - exit(2); - } - - cerr << "isPluginLibraryLoadable: Successfully loaded library \"" << soname << "\" and retrieved descriptor function" << endl; - - exit(0); - - } else { // the parent process - - int status = 0; - - do { - cerr << "waiting for subprocess with pid " << pid << "..." << endl; - waitpid(pid, &status, 0); - cerr << "waited" << endl; - } while (WIFSTOPPED(status)); - - cerr << "and finished" << endl; - - if (WIFEXITED(status)) { - switch (WEXITSTATUS(status)) { - case 0: return PluginLoadOK; // success - case 1: return PluginLoadFailedToLoadLibrary; - case 2: return PluginLoadFailedToFindDescriptor; - default: return PluginLoadFailedElsewhere; - } - } - - if (WIFSIGNALED(status)) { - return PluginLoadFailedElsewhere; - } - - return UnknownPluginLoadStatus; - } -} - -#endif diff -r bf05d9259dbc -r 6b1af0f05f06 system/System.h --- a/system/System.h Thu Apr 14 12:12:04 2016 +0100 +++ b/system/System.h Thu Apr 14 14:03:18 2016 +0100 @@ -154,21 +154,6 @@ extern void StoreStartupLocale(); extern void RestoreStartupLocale(); -enum PluginLoadStatus { - UnknownPluginLoadStatus, - PluginLoadOK, - PluginLoadFailedToLoadLibrary, - PluginLoadFailedToFindDescriptor, - PluginLoadFailedElsewhere -}; - -// Check whether a plugin library is loadable without crashing (may -// need to spawn an external process to do it). Descriptor fn is the -// name of a LADSPA/DSSI/Vamp-style descriptor function to try -// calling; may be an empty string if the plugin doesn't follow that -// convention. -PluginLoadStatus TestPluginLoadability(QString soname, QString descriptorFn); - #include #ifndef M_PI diff -r bf05d9259dbc -r 6b1af0f05f06 transform/TransformFactory.cpp --- a/transform/TransformFactory.cpp Thu Apr 14 12:12:04 2016 +0100 +++ b/transform/TransformFactory.cpp Thu Apr 14 14:03:18 2016 +0100 @@ -399,18 +399,6 @@ m_transformsPopulated = true; } -QString -TransformFactory::getPluginPopulationWarning() -{ - FeatureExtractionPluginFactory *vfactory = - FeatureExtractionPluginFactory::instance("vamp"); - QString warningMessage; - if (vfactory) { - warningMessage = vfactory->getPluginPopulationWarning(); - } - return warningMessage; -} - void TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms) { diff -r bf05d9259dbc -r 6b1af0f05f06 transform/TransformFactory.h --- a/transform/TransformFactory.h Thu Apr 14 12:12:04 2016 +0100 +++ b/transform/TransformFactory.h Thu Apr 14 14:03:18 2016 +0100 @@ -195,14 +195,6 @@ */ void setParametersFromPluginConfigurationXml(Transform &transform, QString xml); - - /** - * Return any error message arising from the initial plugin - * scan. The return value will either be an empty string (nothing - * to report) or an HTML string suitable for dropping into a - * dialog and showing the user. - */ - QString getPluginPopulationWarning(); protected: typedef std::map TransformDescriptionMap;