changeset 1179:6b1af0f05f06 pluginscan

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.
author Chris Cannam
date Thu, 14 Apr 2016 14:03:18 +0100
parents bf05d9259dbc
children 98664afd518b
files plugin/DSSIPluginFactory.h plugin/FeatureExtractionPluginFactory.cpp plugin/FeatureExtractionPluginFactory.h plugin/LADSPAPluginFactory.cpp plugin/LADSPAPluginFactory.h plugin/PluginScan.cpp plugin/PluginScan.h system/System.cpp system/System.h transform/TransformFactory.cpp transform/TransformFactory.h
diffstat 11 files changed, 63 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- 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<QString> getPluginPath();
 
     virtual std::vector<QString> getLRDFPath(QString &baseUri);
--- 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 <QDir>
 #include <QFile>
 #include <QFileInfo>
@@ -111,87 +113,14 @@
 }
 
 vector<QString>
-FeatureExtractionPluginFactory::getPluginCandidateFiles()
-{
-    vector<QString> path = getPluginPath();
-    vector<QString> 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<QString>
-FeatureExtractionPluginFactory::winnowPluginCandidates(vector<QString> candidates,
-                                                       QString &warningMessage)
-{
-    vector<QString> good, bad;
-    vector<PluginLoadStatus> 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("<b>Failed to load plugins</b>"
-                        "<p>Failed to load one or more plugin libraries:</p>\n");
-        warningMessage += "<ul>";
-        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("<li>%1 (%2)</li>\n")
-                .arg(bad[i])
-                .arg(m);
-        }
-        warningMessage += "</ul>";
-    }
-    return good;
-}
-
-vector<QString>
 FeatureExtractionPluginFactory::getPluginIdentifiers()
 {
     Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers");
 
     vector<QString> rv;
-    vector<QString> candidates = winnowPluginCandidates(getPluginCandidateFiles(),
-                                                        m_pluginScanError);
+
+    QStringList candidates =
+        PluginScan::getInstance()->getCandidateVampLibraries();
     
     for (QString soname : candidates) {
 
--- 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<QString> getPluginPath();
 
     virtual std::vector<QString> 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<Vamp::Plugin *, void *> m_handleMap;
     
-    std::vector<QString> getPluginCandidateFiles();
-    std::vector<QString> winnowPluginCandidates(std::vector<QString> candidates,
-                                                QString &warningMessage);
-    
     void generateTaxonomy();
-
-    QString m_pluginScanError;
 };
 
 #endif
--- 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<QString>::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);
     }
 }
 
--- 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 <vector>
 #include <map>
 #include <set>
@@ -63,6 +65,10 @@
     LADSPAPluginFactory();
     friend class RealTimePluginFactory;
 
+    virtual KnownPlugins::PluginType getPluginType() const {
+        return KnownPlugins::LADSPAPlugin;
+    }
+
     virtual std::vector<QString> getPluginPath();
 
     virtual std::vector<QString> getLRDFPath(QString &baseUri);
--- 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("<b>Failed to scan for plugins</b>"
+			   "<p>Failed to scan for plugins at startup "
+			   "(application installation problem?)</p>");
+    }
+    if (!m_kp) {
+	return QObject::tr("<b>Did not scan for plugins</b>"
+			   "<p>Apparently no scan for plugins was attempted "
+			   "(internal error?)</p>");
+    }
+
     string report = m_kp->getFailureReport();
-    return report.c_str(); //!!! wrap?
+    if (report == "") {
+	return QString(report.c_str());
+    }
+
+    return QObject::tr("<b>Failed to load plugins</b>"
+		       "<p>Failed to load one or more plugin libraries:</p>")
+	+ QString(report.c_str());
 }
 
--- 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
--- 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 <unistd.h>
-#include <sys/wait.h>
-
-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
--- 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 <cmath>
 
 #ifndef M_PI
--- 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)
 {
--- 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<TransformId, TransformDescription> TransformDescriptionMap;