annotate plugin/PluginScan.cpp @ 1346:75ad55315db4 3.0-integration

More work on getting tests (especially file encoding ones) running on Windows. Various problems here to do with interaction with test filenames in Hg repos
author Chris Cannam
date Fri, 06 Jan 2017 15:44:55 +0000
parents 0be27c989c1d
children f98fde50570b
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@1178 60 }
Chris@1178 61
Chris@1178 62 void
Chris@1241 63 PluginScan::scan()
Chris@1178 64 {
Chris@1249 65 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 66
Chris@1246 67 QMutexLocker locker(&m_mutex);
Chris@1246 68
Chris@1246 69 bool inProcess = Preferences::getInstance()->getRunPluginsInProcess();
Chris@1246 70
Chris@1246 71 HelperExecPath hep(inProcess ?
Chris@1246 72 HelperExecPath::NativeArchitectureOnly :
Chris@1246 73 HelperExecPath::AllInstalled);
Chris@1246 74
Chris@1246 75 QString helperName("plugin-checker-helper");
Chris@1246 76 auto helpers = hep.getHelperExecutables(helperName);
Chris@1241 77
Chris@1241 78 clear();
Chris@1241 79
Chris@1246 80 for (auto p: helpers) {
Chris@1247 81 SVDEBUG << "NOTE: PluginScan: Found helper: " << p.executable << endl;
Chris@1246 82 }
Chris@1246 83
Chris@1246 84 if (helpers.empty()) {
Chris@1247 85 SVDEBUG << "NOTE: No plugin checker helpers found in installation;"
Chris@1246 86 << " found none of the following:" << endl;
Chris@1246 87 for (auto d: hep.getHelperCandidatePaths(helperName)) {
Chris@1247 88 SVDEBUG << "NOTE: " << d << endl;
Chris@1246 89 }
Chris@1246 90 }
Chris@1246 91
Chris@1246 92 for (auto p: helpers) {
Chris@1241 93 try {
Chris@1246 94 KnownPlugins *kp = new KnownPlugins
Chris@1246 95 (p.executable.toStdString(), m_logger);
Chris@1246 96 if (m_kp.find(p.tag) != m_kp.end()) {
Chris@1247 97 SVDEBUG << "WARNING: PluginScan::scan: Duplicate tag " << p.tag
Chris@1246 98 << " for helpers" << endl;
Chris@1246 99 continue;
Chris@1246 100 }
Chris@1246 101 m_kp[p.tag] = kp;
Chris@1241 102 m_succeeded = true;
Chris@1241 103 } catch (const std::exception &e) {
Chris@1247 104 SVDEBUG << "ERROR: PluginScan::scan: " << e.what()
Chris@1246 105 << " (with helper path = " << p.executable << ")" << endl;
Chris@1241 106 }
Chris@1241 107 }
Chris@1249 108
Chris@1249 109 #endif
Chris@1241 110 }
Chris@1241 111
Chris@1246 112 bool
Chris@1246 113 PluginScan::scanSucceeded() const
Chris@1246 114 {
Chris@1246 115 QMutexLocker locker(&m_mutex);
Chris@1246 116 return m_succeeded;
Chris@1246 117 }
Chris@1246 118
Chris@1241 119 void
Chris@1241 120 PluginScan::clear()
Chris@1241 121 {
Chris@1246 122 for (auto &p: m_kp) {
Chris@1246 123 delete p.second;
Chris@1246 124 }
Chris@1241 125 m_kp.clear();
Chris@1179 126 m_succeeded = false;
Chris@1179 127 }
Chris@1179 128
Chris@1246 129 QList<PluginScan::Candidate>
Chris@1278 130 PluginScan::getCandidateLibrariesFor(PluginType
Chris@1278 131 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1278 132 type
Chris@1278 133 #endif
Chris@1278 134 ) const
Chris@1179 135 {
Chris@1249 136 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 137
Chris@1246 138 QMutexLocker locker(&m_mutex);
Chris@1246 139
Chris@1180 140 KnownPlugins::PluginType kpt;
Chris@1180 141 switch (type) {
Chris@1180 142 case VampPlugin: kpt = KnownPlugins::VampPlugin; break;
Chris@1180 143 case LADSPAPlugin: kpt = KnownPlugins::LADSPAPlugin; break;
Chris@1180 144 case DSSIPlugin: kpt = KnownPlugins::DSSIPlugin; break;
Chris@1180 145 default: throw std::logic_error("Inconsistency in plugin type enums");
Chris@1180 146 }
Chris@1180 147
Chris@1246 148 QList<Candidate> candidates;
Chris@1245 149
Chris@1246 150 for (auto rec: m_kp) {
Chris@1245 151
Chris@1246 152 KnownPlugins *kp = rec.second;
Chris@1246 153
Chris@1241 154 auto c = kp->getCandidateLibrariesFor(kpt);
Chris@1245 155
Chris@1247 156 SVDEBUG << "PluginScan: helper \"" << kp->getHelperExecutableName()
Chris@1247 157 << "\" likes " << c.size() << " libraries of type "
Chris@1247 158 << kp->getTagFor(kpt) << endl;
Chris@1245 159
Chris@1246 160 for (auto s: c) {
Chris@1246 161 candidates.push_back({ s.c_str(), rec.first });
Chris@1246 162 }
Chris@1245 163
Chris@1245 164 if (type != VampPlugin) {
Chris@1245 165 // We are only interested in querying multiple helpers
Chris@1245 166 // when dealing with Vamp plugins, for which we can use
Chris@1245 167 // external servers and so in some cases can support
Chris@1245 168 // additional architectures. Other plugin formats are
Chris@1245 169 // loaded directly and so must match the host, which is
Chris@1245 170 // what the first helper is supposed to handle -- so
Chris@1245 171 // break after the first one if not querying Vamp
Chris@1245 172 break;
Chris@1245 173 }
Chris@1241 174 }
Chris@1245 175
Chris@1179 176 return candidates;
Chris@1249 177
Chris@1249 178 #else
Chris@1249 179 return {};
Chris@1249 180 #endif
Chris@1178 181 }
Chris@1178 182
Chris@1178 183 QString
Chris@1178 184 PluginScan::getStartupFailureReport() const
Chris@1178 185 {
Chris@1249 186 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 187
Chris@1246 188 QMutexLocker locker(&m_mutex);
Chris@1246 189
Chris@1179 190 if (!m_succeeded) {
Chris@1179 191 return QObject::tr("<b>Failed to scan for plugins</b>"
Chris@1181 192 "<p>Failed to scan for plugins at startup. Possibly "
Chris@1181 193 "the plugin checker helper program was not correctly "
Chris@1181 194 "installed alongside %1?</p>")
Chris@1181 195 .arg(QCoreApplication::applicationName());
Chris@1179 196 }
Chris@1241 197 if (m_kp.empty()) {
Chris@1179 198 return QObject::tr("<b>Did not scan for plugins</b>"
Chris@1179 199 "<p>Apparently no scan for plugins was attempted "
Chris@1179 200 "(internal error?)</p>");
Chris@1179 201 }
Chris@1179 202
Chris@1241 203 QString report;
Chris@1241 204 for (auto kp: m_kp) {
Chris@1246 205 report += QString::fromStdString(kp.second->getFailureReport());
Chris@1241 206 }
Chris@1179 207 if (report == "") {
Chris@1241 208 return report;
Chris@1179 209 }
Chris@1179 210
Chris@1179 211 return QObject::tr("<b>Failed to load plugins</b>"
Chris@1179 212 "<p>Failed to load one or more plugin libraries:</p>")
Chris@1241 213 + report
Chris@1181 214 + QObject::tr("<p>These plugins may be incompatible with the system, "
Chris@1181 215 "and will be ignored during this run of %1.</p>")
Chris@1181 216 .arg(QCoreApplication::applicationName());
Chris@1249 217
Chris@1249 218 #else
Chris@1249 219 return "";
Chris@1249 220 #endif
Chris@1178 221 }
Chris@1178 222