comparison plugin/FeatureExtractionPluginFactory.cpp @ 1206:659372323b45 tony-2.0-integration

Merge latest SV 3.0 branch code
author Chris Cannam
date Fri, 19 Aug 2016 15:58:57 +0100
parents 98664afd518b
children 385deb828b4a
comparison
equal deleted inserted replaced
1136:e94719f941ba 1206:659372323b45
19 #include <vamp-hostsdk/PluginHostAdapter.h> 19 #include <vamp-hostsdk/PluginHostAdapter.h>
20 #include <vamp-hostsdk/PluginWrapper.h> 20 #include <vamp-hostsdk/PluginWrapper.h>
21 21
22 #include "system/System.h" 22 #include "system/System.h"
23 23
24 #include "PluginScan.h"
25
24 #include <QDir> 26 #include <QDir>
25 #include <QFile> 27 #include <QFile>
26 #include <QFileInfo> 28 #include <QFileInfo>
27 #include <QTextStream> 29 #include <QTextStream>
28 30
29 #include <iostream> 31 #include <iostream>
30 32
31 #include "base/Profiler.h" 33 #include "base/Profiler.h"
34
35 using namespace std;
32 36
33 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1 37 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1
34 38
35 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper { 39 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper {
36 public: 40 public:
75 QString type, soName, label; 79 QString type, soName, label;
76 PluginIdentifier::parseIdentifier(identifier, type, soName, label); 80 PluginIdentifier::parseIdentifier(identifier, type, soName, label);
77 return instance(type); 81 return instance(type);
78 } 82 }
79 83
80 std::vector<QString> 84 vector<QString>
81 FeatureExtractionPluginFactory::getPluginPath() 85 FeatureExtractionPluginFactory::getPluginPath()
82 { 86 {
83 if (!m_pluginPath.empty()) return m_pluginPath; 87 if (!m_pluginPath.empty()) return m_pluginPath;
84 88
85 std::vector<std::string> p = Vamp::PluginHostAdapter::getPluginPath(); 89 vector<string> p = Vamp::PluginHostAdapter::getPluginPath();
86 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str()); 90 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str());
87 return m_pluginPath; 91 return m_pluginPath;
88 } 92 }
89 93
90 std::vector<QString> 94 vector<QString>
91 FeatureExtractionPluginFactory::getAllPluginIdentifiers() 95 FeatureExtractionPluginFactory::getAllPluginIdentifiers()
92 { 96 {
93 FeatureExtractionPluginFactory *factory; 97 FeatureExtractionPluginFactory *factory;
94 std::vector<QString> rv; 98 vector<QString> rv;
95 99
96 factory = instance("vamp"); 100 factory = instance("vamp");
97 if (factory) { 101 if (factory) {
98 std::vector<QString> tmp = factory->getPluginIdentifiers(); 102 vector<QString> tmp = factory->getPluginIdentifiers();
99 for (size_t i = 0; i < tmp.size(); ++i) { 103 for (size_t i = 0; i < tmp.size(); ++i) {
100 // cerr << "identifier: " << tmp[i] << endl; 104 // cerr << "identifier: " << tmp[i] << endl;
101 rv.push_back(tmp[i]); 105 rv.push_back(tmp[i]);
102 } 106 }
103 } 107 }
106 RestoreStartupLocale(); 110 RestoreStartupLocale();
107 111
108 return rv; 112 return rv;
109 } 113 }
110 114
111 std::vector<QString> 115 vector<QString>
112 FeatureExtractionPluginFactory::getPluginIdentifiers() 116 FeatureExtractionPluginFactory::getPluginIdentifiers()
113 { 117 {
114 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers"); 118 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers");
115 119
116 std::vector<QString> rv; 120 vector<QString> rv;
117 std::vector<QString> path = getPluginPath(); 121
122 QStringList candidates = PluginScan::getInstance()->getCandidateLibrariesFor
123 (PluginScan::VampPlugin);
118 124
119 for (std::vector<QString>::iterator i = path.begin(); i != path.end(); ++i) { 125 for (QString soname : candidates) {
120 126
121 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 127 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
122 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << i-<< endl;
123 #endif
124
125 QDir pluginDir(*i, PLUGIN_GLOB,
126 QDir::Name | QDir::IgnoreCase,
127 QDir::Files | QDir::Readable);
128
129 for (unsigned int j = 0; j < pluginDir.count(); ++j) {
130
131 QString soname = pluginDir.filePath(pluginDir[j]);
132
133 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
134 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl;
135 #endif
136
137 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
138 128
139 if (!libraryHandle) { 129 if (!libraryHandle) {
140 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl; 130 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl;
141 continue; 131 continue;
142 } 132 }
143 133
144 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 134 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
145 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl; 135 DLSYM(libraryHandle, "vampGetPluginDescriptor");
146 #endif 136
147 137 if (!fn) {
148 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) 138 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl;
149 DLSYM(libraryHandle, "vampGetPluginDescriptor");
150
151 if (!fn) {
152 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 SVDEBUG << "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 SVDEBUG << "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 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
199 #endif
200 ++index;
201 }
202 }
203
204 if (DLCLOSE(libraryHandle) != 0) { 139 if (DLCLOSE(libraryHandle) != 0) {
205 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; 140 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
206 } 141 }
207 } 142 continue;
143 }
144
145 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
146 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
147 #endif
148
149 const VampPluginDescriptor *descriptor = 0;
150 int index = 0;
151
152 map<string, int> known;
153 bool ok = true;
154
155 while ((descriptor = fn(VAMP_API_VERSION, index))) {
156
157 if (known.find(descriptor->identifier) != known.end()) {
158 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library "
159 << soname
160 << " returns the same plugin identifier \""
161 << descriptor->identifier << "\" at indices "
162 << known[descriptor->identifier] << " and "
163 << index << endl;
164 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl;
165 ok = false;
166 break;
167 } else {
168 known[descriptor->identifier] = index;
169 }
170
171 ++index;
172 }
173
174 if (ok) {
175
176 index = 0;
177
178 while ((descriptor = fn(VAMP_API_VERSION, index))) {
179
180 QString id = PluginIdentifier::createIdentifier
181 ("vamp", soname, descriptor->identifier);
182 rv.push_back(id);
183 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
184 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
185 #endif
186 ++index;
187 }
188 }
189
190 if (DLCLOSE(libraryHandle) != 0) {
191 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
192 }
208 } 193 }
209 194
210 generateTaxonomy(); 195 generateTaxonomy();
211 196
212 return rv; 197 return rv;
216 FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir) 201 FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir)
217 { 202 {
218 QString file = ""; 203 QString file = "";
219 204
220 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 205 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
221 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile(\"" 206 cerr << "FeatureExtractionPluginFactory::findPluginFile(\""
222 << soname << "\", \"" << inDir << "\")" 207 << soname << "\", \"" << inDir << "\")"
223 << endl; 208 << endl;
224 #endif 209 #endif
225 210
226 if (inDir != "") { 211 if (inDir != "") {
233 file = dir.filePath(QFileInfo(soname).fileName()); 218 file = dir.filePath(QFileInfo(soname).fileName());
234 219
235 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) { 220 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) {
236 221
237 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 222 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
238 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile: " 223 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
239 << "found trivially at " << file << endl; 224 << "found trivially at " << file << endl;
240 #endif 225 #endif
241 226
242 return file; 227 return file;
243 } 228 }
245 for (unsigned int j = 0; j < dir.count(); ++j) { 230 for (unsigned int j = 0; j < dir.count(); ++j) {
246 file = dir.filePath(dir[j]); 231 file = dir.filePath(dir[j]);
247 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) { 232 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
248 233
249 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 234 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
250 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile: " 235 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
251 << "found \"" << soname << "\" at " << file << endl; 236 << "found \"" << soname << "\" at " << file << endl;
252 #endif 237 #endif
253 238
254 return file; 239 return file;
255 } 240 }
256 } 241 }
257 242
258 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 243 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
259 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile (with dir): " 244 cerr << "FeatureExtractionPluginFactory::findPluginFile (with dir): "
260 << "not found" << endl; 245 << "not found" << endl;
261 #endif 246 #endif
262 247
263 return ""; 248 return "";
264 249
266 251
267 QFileInfo fi(soname); 252 QFileInfo fi(soname);
268 253
269 if (fi.isAbsolute() && fi.exists() && fi.isFile()) { 254 if (fi.isAbsolute() && fi.exists() && fi.isFile()) {
270 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 255 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
271 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile: " 256 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
272 << "found trivially at " << soname << endl; 257 << "found trivially at " << soname << endl;
273 #endif 258 #endif
274 return soname; 259 return soname;
275 } 260 }
276 261
277 if (fi.isAbsolute() && fi.absolutePath() != "") { 262 if (fi.isAbsolute() && fi.absolutePath() != "") {
278 file = findPluginFile(soname, fi.absolutePath()); 263 file = findPluginFile(soname, fi.absolutePath());
279 if (file != "") return file; 264 if (file != "") return file;
280 } 265 }
281 266
282 std::vector<QString> path = getPluginPath(); 267 vector<QString> path = getPluginPath();
283 for (std::vector<QString>::iterator i = path.begin(); 268 for (vector<QString>::iterator i = path.begin();
284 i != path.end(); ++i) { 269 i != path.end(); ++i) {
285 if (*i != "") { 270 if (*i != "") {
286 file = findPluginFile(soname, *i); 271 file = findPluginFile(soname, *i);
287 if (file != "") return file; 272 if (file != "") return file;
288 } 273 }
289 } 274 }
290 275
291 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 276 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
292 SVDEBUG << "FeatureExtractionPluginFactory::findPluginFile: " 277 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
293 << "not found" << endl; 278 << "not found" << endl;
294 #endif 279 #endif
295 280
296 return ""; 281 return "";
297 } 282 }
310 int index = 0; 295 int index = 0;
311 296
312 QString type, soname, label; 297 QString type, soname, label;
313 PluginIdentifier::parseIdentifier(identifier, type, soname, label); 298 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
314 if (type != "vamp") { 299 if (type != "vamp") {
315 SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl; 300 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
301 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
302 #endif
316 return 0; 303 return 0;
317 } 304 }
318 305
319 QString found = findPluginFile(soname); 306 QString found = findPluginFile(soname);
320 307
322 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl; 309 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
323 return 0; 310 return 0;
324 } else if (found != soname) { 311 } else if (found != soname) {
325 312
326 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 313 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
327 SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl; 314 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl;
328 cerr << soname << " -> " << found << endl; 315 cerr << soname << " -> " << found << endl;
329 #endif 316 #endif
330 317
331 } 318 }
332 319
341 328
342 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) 329 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
343 DLSYM(libraryHandle, "vampGetPluginDescriptor"); 330 DLSYM(libraryHandle, "vampGetPluginDescriptor");
344 331
345 if (!fn) { 332 if (!fn) {
346 SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl; 333 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl;
347 goto done; 334 goto done;
348 } 335 }
349 336
350 while ((descriptor = fn(VAMP_API_VERSION, index))) { 337 while ((descriptor = fn(VAMP_API_VERSION, index))) {
351 if (label == descriptor->identifier) break; 338 if (label == descriptor->identifier) break;
373 if (DLCLOSE(libraryHandle) != 0) { 360 if (DLCLOSE(libraryHandle) != 0) {
374 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl; 361 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
375 } 362 }
376 } 363 }
377 364
378 // SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl; 365 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
366 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
367 #endif
379 368
380 return rv; 369 return rv;
381 } 370 }
382 371
383 void 372 void
384 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin) 373 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin)
385 { 374 {
386 void *handle = m_handleMap[plugin]; 375 void *handle = m_handleMap[plugin];
387 if (handle) { 376 if (handle) {
388 // SVDEBUG << "unloading library " << handle << " for plugin " << plugin << endl; 377 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
378 cerr << "unloading library " << handle << " for plugin " << plugin << endl;
379 #endif
389 DLCLOSE(handle); 380 DLCLOSE(handle);
390 } 381 }
391 m_handleMap.erase(plugin); 382 m_handleMap.erase(plugin);
392 } 383 }
393 384
398 } 389 }
399 390
400 void 391 void
401 FeatureExtractionPluginFactory::generateTaxonomy() 392 FeatureExtractionPluginFactory::generateTaxonomy()
402 { 393 {
403 std::vector<QString> pluginPath = getPluginPath(); 394 vector<QString> pluginPath = getPluginPath();
404 std::vector<QString> path; 395 vector<QString> path;
405 396
406 for (size_t i = 0; i < pluginPath.size(); ++i) { 397 for (size_t i = 0; i < pluginPath.size(); ++i) {
407 if (pluginPath[i].contains("/lib/")) { 398 if (pluginPath[i].contains("/lib/")) {
408 QString p(pluginPath[i]); 399 QString p(pluginPath[i]);
409 path.push_back(p); 400 path.push_back(p);