annotate plugin/PluginScan.cpp @ 1412:b7a9edee85e0 scale-ticks

Change loop to something that feels more correct, though it makes no difference to the tests here. More tests, one failing.
author Chris Cannam
date Thu, 04 May 2017 08:32:41 +0100
parents 0bbf91b05164
children 48e9f538e6e9
rev   line source
Chris@1178 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1178 2
Chris@1178 3 /*
Chris@1178 4 Sonic Visualiser
Chris@1178 5 An audio file viewer and annotation editor.
Chris@1178 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1178 7
Chris@1178 8 This program is free software; you can redistribute it and/or
Chris@1178 9 modify it under the terms of the GNU General Public License as
Chris@1178 10 published by the Free Software Foundation; either version 2 of the
Chris@1178 11 License, or (at your option) any later version. See the file
Chris@1178 12 COPYING included with this distribution for more information.
Chris@1178 13 */
Chris@1178 14
Chris@1178 15 #include "PluginScan.h"
Chris@1178 16
Chris@1178 17 #include "base/Debug.h"
Chris@1246 18 #include "base/Preferences.h"
Chris@1241 19 #include "base/HelperExecPath.h"
Chris@1178 20
Chris@1249 21 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1180 22 #include "checker/knownplugins.h"
Chris@1249 23 #else
Chris@1249 24 class KnownPlugins {};
Chris@1249 25 #endif
Chris@1180 26
Chris@1178 27 #include <QMutex>
Chris@1181 28 #include <QCoreApplication>
Chris@1178 29
Chris@1178 30 using std::string;
Chris@1178 31
Chris@1249 32 class PluginScan::Logger
Chris@1249 33 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 34 : public PluginCandidates::LogCallback
Chris@1249 35 #endif
Chris@1180 36 {
Chris@1180 37 protected:
Chris@1180 38 void log(std::string message) {
Chris@1264 39 SVDEBUG << "PluginScan: " << message << endl;
Chris@1180 40 }
Chris@1180 41 };
Chris@1180 42
Chris@1180 43 PluginScan *PluginScan::getInstance()
Chris@1180 44 {
Chris@1178 45 static QMutex mutex;
Chris@1178 46 static PluginScan *m_instance = 0;
Chris@1178 47 mutex.lock();
Chris@1178 48 if (!m_instance) m_instance = new PluginScan();
Chris@1178 49 mutex.unlock();
Chris@1178 50 return m_instance;
Chris@1178 51 }
Chris@1178 52
Chris@1246 53 PluginScan::PluginScan() : m_succeeded(false), m_logger(new Logger) {
Chris@1178 54 }
Chris@1178 55
Chris@1178 56 PluginScan::~PluginScan() {
Chris@1246 57 QMutexLocker locker(&m_mutex);
Chris@1241 58 clear();
Chris@1180 59 delete m_logger;
Chris@1396 60 SVDEBUG << "PluginScan::~PluginScan completed" << endl;
Chris@1178 61 }
Chris@1178 62
Chris@1178 63 void
Chris@1241 64 PluginScan::scan()
Chris@1178 65 {
Chris@1249 66 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 67
Chris@1246 68 QMutexLocker locker(&m_mutex);
Chris@1246 69
Chris@1246 70 bool inProcess = Preferences::getInstance()->getRunPluginsInProcess();
Chris@1246 71
Chris@1246 72 HelperExecPath hep(inProcess ?
Chris@1246 73 HelperExecPath::NativeArchitectureOnly :
Chris@1246 74 HelperExecPath::AllInstalled);
Chris@1246 75
Chris@1352 76 QString helperName("vamp-plugin-load-checker");
Chris@1246 77 auto helpers = hep.getHelperExecutables(helperName);
Chris@1241 78
Chris@1241 79 clear();
Chris@1241 80
Chris@1246 81 for (auto p: helpers) {
Chris@1247 82 SVDEBUG << "NOTE: PluginScan: Found helper: " << p.executable << endl;
Chris@1246 83 }
Chris@1246 84
Chris@1246 85 if (helpers.empty()) {
Chris@1247 86 SVDEBUG << "NOTE: No plugin checker helpers found in installation;"
Chris@1246 87 << " found none of the following:" << endl;
Chris@1246 88 for (auto d: hep.getHelperCandidatePaths(helperName)) {
Chris@1247 89 SVDEBUG << "NOTE: " << d << endl;
Chris@1246 90 }
Chris@1246 91 }
Chris@1246 92
Chris@1246 93 for (auto p: helpers) {
Chris@1241 94 try {
Chris@1246 95 KnownPlugins *kp = new KnownPlugins
Chris@1246 96 (p.executable.toStdString(), m_logger);
Chris@1246 97 if (m_kp.find(p.tag) != m_kp.end()) {
Chris@1247 98 SVDEBUG << "WARNING: PluginScan::scan: Duplicate tag " << p.tag
Chris@1246 99 << " for helpers" << endl;
Chris@1246 100 continue;
Chris@1246 101 }
Chris@1246 102 m_kp[p.tag] = kp;
Chris@1241 103 m_succeeded = true;
Chris@1241 104 } catch (const std::exception &e) {
Chris@1247 105 SVDEBUG << "ERROR: PluginScan::scan: " << e.what()
Chris@1246 106 << " (with helper path = " << p.executable << ")" << endl;
Chris@1241 107 }
Chris@1241 108 }
Chris@1249 109
Chris@1396 110 SVDEBUG << "PluginScan::scan complete" << endl;
Chris@1249 111 #endif
Chris@1241 112 }
Chris@1241 113
Chris@1246 114 bool
Chris@1246 115 PluginScan::scanSucceeded() const
Chris@1246 116 {
Chris@1246 117 QMutexLocker locker(&m_mutex);
Chris@1246 118 return m_succeeded;
Chris@1246 119 }
Chris@1246 120
Chris@1241 121 void
Chris@1241 122 PluginScan::clear()
Chris@1241 123 {
Chris@1246 124 for (auto &p: m_kp) {
Chris@1246 125 delete p.second;
Chris@1246 126 }
Chris@1241 127 m_kp.clear();
Chris@1179 128 m_succeeded = false;
Chris@1179 129 }
Chris@1179 130
Chris@1246 131 QList<PluginScan::Candidate>
Chris@1278 132 PluginScan::getCandidateLibrariesFor(PluginType
Chris@1278 133 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1278 134 type
Chris@1278 135 #endif
Chris@1278 136 ) const
Chris@1179 137 {
Chris@1249 138 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 139
Chris@1246 140 QMutexLocker locker(&m_mutex);
Chris@1246 141
Chris@1180 142 KnownPlugins::PluginType kpt;
Chris@1180 143 switch (type) {
Chris@1180 144 case VampPlugin: kpt = KnownPlugins::VampPlugin; break;
Chris@1180 145 case LADSPAPlugin: kpt = KnownPlugins::LADSPAPlugin; break;
Chris@1180 146 case DSSIPlugin: kpt = KnownPlugins::DSSIPlugin; break;
Chris@1180 147 default: throw std::logic_error("Inconsistency in plugin type enums");
Chris@1180 148 }
Chris@1180 149
Chris@1246 150 QList<Candidate> candidates;
Chris@1245 151
Chris@1246 152 for (auto rec: m_kp) {
Chris@1245 153
Chris@1246 154 KnownPlugins *kp = rec.second;
Chris@1246 155
Chris@1241 156 auto c = kp->getCandidateLibrariesFor(kpt);
Chris@1245 157
Chris@1247 158 SVDEBUG << "PluginScan: helper \"" << kp->getHelperExecutableName()
Chris@1247 159 << "\" likes " << c.size() << " libraries of type "
Chris@1247 160 << kp->getTagFor(kpt) << endl;
Chris@1245 161
Chris@1246 162 for (auto s: c) {
Chris@1246 163 candidates.push_back({ s.c_str(), rec.first });
Chris@1246 164 }
Chris@1245 165
Chris@1245 166 if (type != VampPlugin) {
Chris@1245 167 // We are only interested in querying multiple helpers
Chris@1245 168 // when dealing with Vamp plugins, for which we can use
Chris@1245 169 // external servers and so in some cases can support
Chris@1245 170 // additional architectures. Other plugin formats are
Chris@1245 171 // loaded directly and so must match the host, which is
Chris@1245 172 // what the first helper is supposed to handle -- so
Chris@1245 173 // break after the first one if not querying Vamp
Chris@1245 174 break;
Chris@1245 175 }
Chris@1241 176 }
Chris@1245 177
Chris@1179 178 return candidates;
Chris@1249 179
Chris@1249 180 #else
Chris@1249 181 return {};
Chris@1249 182 #endif
Chris@1178 183 }
Chris@1178 184
Chris@1178 185 QString
Chris@1178 186 PluginScan::getStartupFailureReport() const
Chris@1178 187 {
Chris@1249 188 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 189
Chris@1246 190 QMutexLocker locker(&m_mutex);
Chris@1246 191
Chris@1179 192 if (!m_succeeded) {
Chris@1179 193 return QObject::tr("<b>Failed to scan for plugins</b>"
Chris@1181 194 "<p>Failed to scan for plugins at startup. Possibly "
Chris@1352 195 "the plugin checker program was not correctly "
Chris@1181 196 "installed alongside %1?</p>")
Chris@1181 197 .arg(QCoreApplication::applicationName());
Chris@1179 198 }
Chris@1241 199 if (m_kp.empty()) {
Chris@1179 200 return QObject::tr("<b>Did not scan for plugins</b>"
Chris@1179 201 "<p>Apparently no scan for plugins was attempted "
Chris@1179 202 "(internal error?)</p>");
Chris@1179 203 }
Chris@1179 204
Chris@1241 205 QString report;
Chris@1241 206 for (auto kp: m_kp) {
Chris@1246 207 report += QString::fromStdString(kp.second->getFailureReport());
Chris@1241 208 }
Chris@1179 209 if (report == "") {
Chris@1241 210 return report;
Chris@1179 211 }
Chris@1179 212
Chris@1179 213 return QObject::tr("<b>Failed to load plugins</b>"
Chris@1179 214 "<p>Failed to load one or more plugin libraries:</p>")
Chris@1241 215 + report
Chris@1181 216 + QObject::tr("<p>These plugins may be incompatible with the system, "
Chris@1181 217 "and will be ignored during this run of %1.</p>")
Chris@1181 218 .arg(QCoreApplication::applicationName());
Chris@1249 219
Chris@1249 220 #else
Chris@1249 221 return "";
Chris@1249 222 #endif
Chris@1178 223 }
Chris@1178 224