Mercurial > hg > svcore
comparison plugin/FeatureExtractionPluginFactory.cpp @ 1172:59ae7e04f7e9
Merge
author | Chris Cannam |
---|---|
date | Fri, 04 Mar 2016 12:29:35 +0000 |
parents | 7c4f4701b49f |
children | 6877f4200912 |
comparison
equal
deleted
inserted
replaced
1171:fa1bec83441e | 1172:59ae7e04f7e9 |
---|---|
27 #include <QTextStream> | 27 #include <QTextStream> |
28 | 28 |
29 #include <iostream> | 29 #include <iostream> |
30 | 30 |
31 #include "base/Profiler.h" | 31 #include "base/Profiler.h" |
32 | |
33 using namespace std; | |
32 | 34 |
33 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1 | 35 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1 |
34 | 36 |
35 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper { | 37 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper { |
36 public: | 38 public: |
75 QString type, soName, label; | 77 QString type, soName, label; |
76 PluginIdentifier::parseIdentifier(identifier, type, soName, label); | 78 PluginIdentifier::parseIdentifier(identifier, type, soName, label); |
77 return instance(type); | 79 return instance(type); |
78 } | 80 } |
79 | 81 |
80 std::vector<QString> | 82 vector<QString> |
81 FeatureExtractionPluginFactory::getPluginPath() | 83 FeatureExtractionPluginFactory::getPluginPath() |
82 { | 84 { |
83 if (!m_pluginPath.empty()) return m_pluginPath; | 85 if (!m_pluginPath.empty()) return m_pluginPath; |
84 | 86 |
85 std::vector<std::string> p = Vamp::PluginHostAdapter::getPluginPath(); | 87 vector<string> p = Vamp::PluginHostAdapter::getPluginPath(); |
86 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str()); | 88 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str()); |
87 return m_pluginPath; | 89 return m_pluginPath; |
88 } | 90 } |
89 | 91 |
90 std::vector<QString> | 92 vector<QString> |
91 FeatureExtractionPluginFactory::getAllPluginIdentifiers() | 93 FeatureExtractionPluginFactory::getAllPluginIdentifiers() |
92 { | 94 { |
93 FeatureExtractionPluginFactory *factory; | 95 FeatureExtractionPluginFactory *factory; |
94 std::vector<QString> rv; | 96 vector<QString> rv; |
95 | 97 |
96 factory = instance("vamp"); | 98 factory = instance("vamp"); |
97 if (factory) { | 99 if (factory) { |
98 std::vector<QString> tmp = factory->getPluginIdentifiers(); | 100 vector<QString> tmp = factory->getPluginIdentifiers(); |
99 for (size_t i = 0; i < tmp.size(); ++i) { | 101 for (size_t i = 0; i < tmp.size(); ++i) { |
100 // cerr << "identifier: " << tmp[i] << endl; | 102 // cerr << "identifier: " << tmp[i] << endl; |
101 rv.push_back(tmp[i]); | 103 rv.push_back(tmp[i]); |
102 } | 104 } |
103 } | 105 } |
106 RestoreStartupLocale(); | 108 RestoreStartupLocale(); |
107 | 109 |
108 return rv; | 110 return rv; |
109 } | 111 } |
110 | 112 |
111 std::vector<QString> | 113 vector<QString> |
112 FeatureExtractionPluginFactory::getPluginIdentifiers() | 114 FeatureExtractionPluginFactory::getPluginCandidateFiles() |
113 { | 115 { |
114 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers"); | 116 vector<QString> path = getPluginPath(); |
115 | 117 vector<QString> candidates; |
116 std::vector<QString> rv; | 118 |
117 std::vector<QString> path = getPluginPath(); | 119 for (QString dirname : path) { |
118 | 120 |
119 for (std::vector<QString>::iterator i = path.begin(); i != path.end(); ++i) { | 121 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE |
120 | 122 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << dirname << endl; |
121 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | 123 #endif |
122 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << *i << endl; | 124 |
123 #endif | 125 QDir pluginDir(dirname, PLUGIN_GLOB, |
124 | |
125 QDir pluginDir(*i, PLUGIN_GLOB, | |
126 QDir::Name | QDir::IgnoreCase, | 126 QDir::Name | QDir::IgnoreCase, |
127 QDir::Files | QDir::Readable); | 127 QDir::Files | QDir::Readable); |
128 | 128 |
129 for (unsigned int j = 0; j < pluginDir.count(); ++j) { | 129 for (unsigned int j = 0; j < pluginDir.count(); ++j) { |
130 | |
131 QString soname = pluginDir.filePath(pluginDir[j]); | 130 QString soname = pluginDir.filePath(pluginDir[j]); |
132 | 131 candidates.push_back(soname); |
133 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | 132 } |
134 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl; | 133 } |
135 #endif | 134 |
136 | 135 return candidates; |
137 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL); | 136 } |
137 | |
138 vector<QString> | |
139 FeatureExtractionPluginFactory::winnowPluginCandidates(vector<QString> candidates, | |
140 QString &warningMessage) | |
141 { | |
142 vector<QString> good, bad; | |
143 vector<PluginLoadStatus> badStatuses; | |
144 | |
145 for (QString c: candidates) { | |
146 | |
147 PluginLoadStatus status = | |
148 TestPluginLoadability(c, "vampGetPluginDescriptor"); | |
149 | |
150 if (status == PluginLoadOK) { | |
151 good.push_back(c); | |
152 } else if (status == UnknownPluginLoadStatus) { | |
153 cerr << "WARNING: Unknown load status for plugin candidate \"" | |
154 << c << "\", continuing" << endl; | |
155 good.push_back(c); | |
156 } else { | |
157 bad.push_back(c); | |
158 badStatuses.push_back(status); | |
159 } | |
160 } | |
161 | |
162 if (!bad.empty()) { | |
163 warningMessage = | |
164 QObject::tr("<b>Failed to load plugins</b>" | |
165 "<p>Failed to load one or more plugin libraries:</p>\n"); | |
166 warningMessage += "<ul>"; | |
167 for (int i = 0; in_range_for(bad, i); ++i) { | |
168 QString m; | |
169 if (badStatuses[i] == PluginLoadFailedToLoadLibrary) { | |
170 m = QObject::tr("Failed to load library"); | |
171 } else if (badStatuses[i] == PluginLoadFailedToFindDescriptor) { | |
172 m = QObject::tr("Failed to query plugins from library after loading"); | |
173 } else if (badStatuses[i] == PluginLoadFailedElsewhere) { | |
174 m = QObject::tr("Unknown failure"); | |
175 } else { | |
176 m = QObject::tr("Success: internal error?"); | |
177 } | |
178 warningMessage += QString("<li>%1 (%2)</li>\n") | |
179 .arg(bad[i]) | |
180 .arg(m); | |
181 } | |
182 warningMessage += "</ul>"; | |
183 } | |
184 return good; | |
185 } | |
186 | |
187 vector<QString> | |
188 FeatureExtractionPluginFactory::getPluginIdentifiers() | |
189 { | |
190 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers"); | |
191 | |
192 vector<QString> rv; | |
193 vector<QString> candidates = winnowPluginCandidates(getPluginCandidateFiles(), | |
194 m_pluginScanError); | |
195 | |
196 for (QString soname : candidates) { | |
197 | |
198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | |
199 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl; | |
200 #endif | |
201 | |
202 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL); | |
138 | 203 |
139 if (!libraryHandle) { | 204 if (!libraryHandle) { |
140 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl; | 205 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl; |
141 continue; | 206 continue; |
142 } | 207 } |
143 | 208 |
144 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | 209 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE |
145 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl; | 210 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl; |
146 #endif | 211 #endif |
147 | 212 |
148 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) | 213 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) |
149 DLSYM(libraryHandle, "vampGetPluginDescriptor"); | 214 DLSYM(libraryHandle, "vampGetPluginDescriptor"); |
150 | 215 |
151 if (!fn) { | 216 if (!fn) { |
152 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl; | 217 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl; |
153 if (DLCLOSE(libraryHandle) != 0) { | |
154 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; | |
155 } | |
156 continue; | |
157 } | |
158 | |
159 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | |
160 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl; | |
161 #endif | |
162 | |
163 const VampPluginDescriptor *descriptor = 0; | |
164 int index = 0; | |
165 | |
166 std::map<std::string, int> known; | |
167 bool ok = true; | |
168 | |
169 while ((descriptor = fn(VAMP_API_VERSION, index))) { | |
170 | |
171 if (known.find(descriptor->identifier) != known.end()) { | |
172 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library " | |
173 << soname | |
174 << " returns the same plugin identifier \"" | |
175 << descriptor->identifier << "\" at indices " | |
176 << known[descriptor->identifier] << " and " | |
177 << index << endl; | |
178 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl; | |
179 ok = false; | |
180 break; | |
181 } else { | |
182 known[descriptor->identifier] = index; | |
183 } | |
184 | |
185 ++index; | |
186 } | |
187 | |
188 if (ok) { | |
189 | |
190 index = 0; | |
191 | |
192 while ((descriptor = fn(VAMP_API_VERSION, index))) { | |
193 | |
194 QString id = PluginIdentifier::createIdentifier | |
195 ("vamp", soname, descriptor->identifier); | |
196 rv.push_back(id); | |
197 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | |
198 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl; | |
199 #endif | |
200 ++index; | |
201 } | |
202 } | |
203 | |
204 if (DLCLOSE(libraryHandle) != 0) { | 218 if (DLCLOSE(libraryHandle) != 0) { |
205 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; | 219 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; |
206 } | 220 } |
207 } | 221 continue; |
222 } | |
223 | |
224 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | |
225 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl; | |
226 #endif | |
227 | |
228 const VampPluginDescriptor *descriptor = 0; | |
229 int index = 0; | |
230 | |
231 map<string, int> known; | |
232 bool ok = true; | |
233 | |
234 while ((descriptor = fn(VAMP_API_VERSION, index))) { | |
235 | |
236 if (known.find(descriptor->identifier) != known.end()) { | |
237 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library " | |
238 << soname | |
239 << " returns the same plugin identifier \"" | |
240 << descriptor->identifier << "\" at indices " | |
241 << known[descriptor->identifier] << " and " | |
242 << index << endl; | |
243 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl; | |
244 ok = false; | |
245 break; | |
246 } else { | |
247 known[descriptor->identifier] = index; | |
248 } | |
249 | |
250 ++index; | |
251 } | |
252 | |
253 if (ok) { | |
254 | |
255 index = 0; | |
256 | |
257 while ((descriptor = fn(VAMP_API_VERSION, index))) { | |
258 | |
259 QString id = PluginIdentifier::createIdentifier | |
260 ("vamp", soname, descriptor->identifier); | |
261 rv.push_back(id); | |
262 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE | |
263 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl; | |
264 #endif | |
265 ++index; | |
266 } | |
267 } | |
268 | |
269 if (DLCLOSE(libraryHandle) != 0) { | |
270 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; | |
271 } | |
208 } | 272 } |
209 | 273 |
210 generateTaxonomy(); | 274 generateTaxonomy(); |
211 | 275 |
212 return rv; | 276 return rv; |
277 if (fi.isAbsolute() && fi.absolutePath() != "") { | 341 if (fi.isAbsolute() && fi.absolutePath() != "") { |
278 file = findPluginFile(soname, fi.absolutePath()); | 342 file = findPluginFile(soname, fi.absolutePath()); |
279 if (file != "") return file; | 343 if (file != "") return file; |
280 } | 344 } |
281 | 345 |
282 std::vector<QString> path = getPluginPath(); | 346 vector<QString> path = getPluginPath(); |
283 for (std::vector<QString>::iterator i = path.begin(); | 347 for (vector<QString>::iterator i = path.begin(); |
284 i != path.end(); ++i) { | 348 i != path.end(); ++i) { |
285 if (*i != "") { | 349 if (*i != "") { |
286 file = findPluginFile(soname, *i); | 350 file = findPluginFile(soname, *i); |
287 if (file != "") return file; | 351 if (file != "") return file; |
288 } | 352 } |
310 int index = 0; | 374 int index = 0; |
311 | 375 |
312 QString type, soname, label; | 376 QString type, soname, label; |
313 PluginIdentifier::parseIdentifier(identifier, type, soname, label); | 377 PluginIdentifier::parseIdentifier(identifier, type, soname, label); |
314 if (type != "vamp") { | 378 if (type != "vamp") { |
315 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl; | 379 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE |
380 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl; | |
381 #endif | |
316 return 0; | 382 return 0; |
317 } | 383 } |
318 | 384 |
319 QString found = findPluginFile(soname); | 385 QString found = findPluginFile(soname); |
320 | 386 |
373 if (DLCLOSE(libraryHandle) != 0) { | 439 if (DLCLOSE(libraryHandle) != 0) { |
374 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl; | 440 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl; |
375 } | 441 } |
376 } | 442 } |
377 | 443 |
378 // SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl; | 444 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE |
445 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl; | |
446 #endif | |
379 | 447 |
380 return rv; | 448 return rv; |
381 } | 449 } |
382 | 450 |
383 void | 451 void |
384 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin) | 452 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin) |
385 { | 453 { |
386 void *handle = m_handleMap[plugin]; | 454 void *handle = m_handleMap[plugin]; |
387 if (handle) { | 455 if (handle) { |
388 // SVDEBUG << "unloading library " << handle << " for plugin " << plugin << endl; | 456 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE |
457 cerr << "unloading library " << handle << " for plugin " << plugin << endl; | |
458 #endif | |
389 DLCLOSE(handle); | 459 DLCLOSE(handle); |
390 } | 460 } |
391 m_handleMap.erase(plugin); | 461 m_handleMap.erase(plugin); |
392 } | 462 } |
393 | 463 |
398 } | 468 } |
399 | 469 |
400 void | 470 void |
401 FeatureExtractionPluginFactory::generateTaxonomy() | 471 FeatureExtractionPluginFactory::generateTaxonomy() |
402 { | 472 { |
403 std::vector<QString> pluginPath = getPluginPath(); | 473 vector<QString> pluginPath = getPluginPath(); |
404 std::vector<QString> path; | 474 vector<QString> path; |
405 | 475 |
406 for (size_t i = 0; i < pluginPath.size(); ++i) { | 476 for (size_t i = 0; i < pluginPath.size(); ++i) { |
407 if (pluginPath[i].contains("/lib/")) { | 477 if (pluginPath[i].contains("/lib/")) { |
408 QString p(pluginPath[i]); | 478 QString p(pluginPath[i]); |
409 path.push_back(p); | 479 path.push_back(p); |