comparison plugin/PluginScan.cpp @ 1251:67aee57e32c8 3.0-integration

Merge from branch piper
author Chris Cannam
date Fri, 04 Nov 2016 14:57:03 +0000
parents d45a16c232bd
children a99641535e02
comparison
equal deleted inserted replaced
1241:c6bdf247016a 1251:67aee57e32c8
13 */ 13 */
14 14
15 #include "PluginScan.h" 15 #include "PluginScan.h"
16 16
17 #include "base/Debug.h" 17 #include "base/Debug.h"
18 #include "base/Preferences.h"
18 #include "base/HelperExecPath.h" 19 #include "base/HelperExecPath.h"
19 20
21 #ifdef HAVE_PLUGIN_CHECKER_HELPER
20 #include "checker/knownplugins.h" 22 #include "checker/knownplugins.h"
23 #else
24 class KnownPlugins {};
25 #endif
21 26
22 #include <QMutex> 27 #include <QMutex>
23 #include <QCoreApplication> 28 #include <QCoreApplication>
24 29
25 using std::string; 30 using std::string;
26 31
27 //#define DEBUG_PLUGIN_SCAN 1 32 class PluginScan::Logger
28 33 #ifdef HAVE_PLUGIN_CHECKER_HELPER
29 class PluginScan::Logger : public PluginCandidates::LogCallback 34 : public PluginCandidates::LogCallback
35 #endif
30 { 36 {
31 protected: 37 protected:
32 void log(std::string message) { 38 void log(std::string message) {
33 #ifdef DEBUG_PLUGIN_SCAN
34 cerr << "PluginScan: " << message;
35 #endif
36 SVDEBUG << "PluginScan: " << message; 39 SVDEBUG << "PluginScan: " << message;
37 } 40 }
38 }; 41 };
39 42
40 PluginScan *PluginScan::getInstance() 43 PluginScan *PluginScan::getInstance()
45 if (!m_instance) m_instance = new PluginScan(); 48 if (!m_instance) m_instance = new PluginScan();
46 mutex.unlock(); 49 mutex.unlock();
47 return m_instance; 50 return m_instance;
48 } 51 }
49 52
50 PluginScan::PluginScan() : m_kp(0), m_succeeded(false), m_logger(new Logger) { 53 PluginScan::PluginScan() : m_succeeded(false), m_logger(new Logger) {
51 } 54 }
52 55
53 PluginScan::~PluginScan() { 56 PluginScan::~PluginScan() {
57 QMutexLocker locker(&m_mutex);
54 clear(); 58 clear();
55 delete m_logger; 59 delete m_logger;
56 } 60 }
57 61
58 void 62 void
59 PluginScan::scan() 63 PluginScan::scan()
60 { 64 {
61 QStringList helperPaths = 65 #ifdef HAVE_PLUGIN_CHECKER_HELPER
62 HelperExecPath::getHelperExecutables("plugin-checker-helper"); 66
67 QMutexLocker locker(&m_mutex);
68
69 bool inProcess = Preferences::getInstance()->getRunPluginsInProcess();
70
71 HelperExecPath hep(inProcess ?
72 HelperExecPath::NativeArchitectureOnly :
73 HelperExecPath::AllInstalled);
74
75 QString helperName("plugin-checker-helper");
76 auto helpers = hep.getHelperExecutables(helperName);
63 77
64 clear(); 78 clear();
65 79
66 for (auto p: helperPaths) { 80 for (auto p: helpers) {
81 SVDEBUG << "NOTE: PluginScan: Found helper: " << p.executable << endl;
82 }
83
84 if (helpers.empty()) {
85 SVDEBUG << "NOTE: No plugin checker helpers found in installation;"
86 << " found none of the following:" << endl;
87 for (auto d: hep.getHelperCandidatePaths(helperName)) {
88 SVDEBUG << "NOTE: " << d << endl;
89 }
90 }
91
92 for (auto p: helpers) {
67 try { 93 try {
68 KnownPlugins *kp = new KnownPlugins(p.toStdString(), m_logger); 94 KnownPlugins *kp = new KnownPlugins
69 m_kp.push_back(kp); 95 (p.executable.toStdString(), m_logger);
96 if (m_kp.find(p.tag) != m_kp.end()) {
97 SVDEBUG << "WARNING: PluginScan::scan: Duplicate tag " << p.tag
98 << " for helpers" << endl;
99 continue;
100 }
101 m_kp[p.tag] = kp;
70 m_succeeded = true; 102 m_succeeded = true;
71 } catch (const std::exception &e) { 103 } catch (const std::exception &e) {
72 cerr << "ERROR: PluginScan::scan: " << e.what() 104 SVDEBUG << "ERROR: PluginScan::scan: " << e.what()
73 << " (with helper path = " << p << ")" << endl; 105 << " (with helper path = " << p.executable << ")" << endl;
74 } 106 }
75 } 107 }
108
109 #endif
110 }
111
112 bool
113 PluginScan::scanSucceeded() const
114 {
115 QMutexLocker locker(&m_mutex);
116 return m_succeeded;
76 } 117 }
77 118
78 void 119 void
79 PluginScan::clear() 120 PluginScan::clear()
80 { 121 {
81 for (auto &p: m_kp) delete p; 122 for (auto &p: m_kp) {
123 delete p.second;
124 }
82 m_kp.clear(); 125 m_kp.clear();
83 m_succeeded = false; 126 m_succeeded = false;
84 } 127 }
85 128
86 QStringList 129 QList<PluginScan::Candidate>
87 PluginScan::getCandidateLibrariesFor(PluginType type) const 130 PluginScan::getCandidateLibrariesFor(PluginType type) const
88 { 131 {
132 #ifdef HAVE_PLUGIN_CHECKER_HELPER
133
134 QMutexLocker locker(&m_mutex);
135
89 KnownPlugins::PluginType kpt; 136 KnownPlugins::PluginType kpt;
90 switch (type) { 137 switch (type) {
91 case VampPlugin: kpt = KnownPlugins::VampPlugin; break; 138 case VampPlugin: kpt = KnownPlugins::VampPlugin; break;
92 case LADSPAPlugin: kpt = KnownPlugins::LADSPAPlugin; break; 139 case LADSPAPlugin: kpt = KnownPlugins::LADSPAPlugin; break;
93 case DSSIPlugin: kpt = KnownPlugins::DSSIPlugin; break; 140 case DSSIPlugin: kpt = KnownPlugins::DSSIPlugin; break;
94 default: throw std::logic_error("Inconsistency in plugin type enums"); 141 default: throw std::logic_error("Inconsistency in plugin type enums");
95 } 142 }
96 143
97 QStringList candidates; 144 QList<Candidate> candidates;
98 for (auto kp: m_kp) { 145
146 for (auto rec: m_kp) {
147
148 KnownPlugins *kp = rec.second;
149
99 auto c = kp->getCandidateLibrariesFor(kpt); 150 auto c = kp->getCandidateLibrariesFor(kpt);
100 for (auto s: c) candidates.push_back(s.c_str()); 151
101 } 152 SVDEBUG << "PluginScan: helper \"" << kp->getHelperExecutableName()
153 << "\" likes " << c.size() << " libraries of type "
154 << kp->getTagFor(kpt) << endl;
155
156 for (auto s: c) {
157 candidates.push_back({ s.c_str(), rec.first });
158 }
159
160 if (type != VampPlugin) {
161 // We are only interested in querying multiple helpers
162 // when dealing with Vamp plugins, for which we can use
163 // external servers and so in some cases can support
164 // additional architectures. Other plugin formats are
165 // loaded directly and so must match the host, which is
166 // what the first helper is supposed to handle -- so
167 // break after the first one if not querying Vamp
168 break;
169 }
170 }
171
102 return candidates; 172 return candidates;
173
174 #else
175 return {};
176 #endif
103 } 177 }
104 178
105 QString 179 QString
106 PluginScan::getStartupFailureReport() const 180 PluginScan::getStartupFailureReport() const
107 { 181 {
182 #ifdef HAVE_PLUGIN_CHECKER_HELPER
183
184 QMutexLocker locker(&m_mutex);
185
108 if (!m_succeeded) { 186 if (!m_succeeded) {
109 return QObject::tr("<b>Failed to scan for plugins</b>" 187 return QObject::tr("<b>Failed to scan for plugins</b>"
110 "<p>Failed to scan for plugins at startup. Possibly " 188 "<p>Failed to scan for plugins at startup. Possibly "
111 "the plugin checker helper program was not correctly " 189 "the plugin checker helper program was not correctly "
112 "installed alongside %1?</p>") 190 "installed alongside %1?</p>")
118 "(internal error?)</p>"); 196 "(internal error?)</p>");
119 } 197 }
120 198
121 QString report; 199 QString report;
122 for (auto kp: m_kp) { 200 for (auto kp: m_kp) {
123 report += QString::fromStdString(kp->getFailureReport()); 201 report += QString::fromStdString(kp.second->getFailureReport());
124 } 202 }
125 if (report == "") { 203 if (report == "") {
126 return report; 204 return report;
127 } 205 }
128 206
130 "<p>Failed to load one or more plugin libraries:</p>") 208 "<p>Failed to load one or more plugin libraries:</p>")
131 + report 209 + report
132 + QObject::tr("<p>These plugins may be incompatible with the system, " 210 + QObject::tr("<p>These plugins may be incompatible with the system, "
133 "and will be ignored during this run of %1.</p>") 211 "and will be ignored during this run of %1.</p>")
134 .arg(QCoreApplication::applicationName()); 212 .arg(QCoreApplication::applicationName());
135 } 213
136 214 #else
215 return "";
216 #endif
217 }
218