annotate plugin/FeatureExtractionPluginFactory.cpp @ 1160:ea636412f9fe 3.0-integration

Merge from the default branch
author Chris Cannam
date Thu, 04 Feb 2016 11:16:05 +0000
parents fc4cb3901316 c7f1300dbf64
children 6877f4200912
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "FeatureExtractionPluginFactory.h"
Chris@0 17 #include "PluginIdentifier.h"
Chris@0 18
Chris@475 19 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@475 20 #include <vamp-hostsdk/PluginWrapper.h>
Chris@66 21
Chris@150 22 #include "system/System.h"
Chris@66 23
Chris@66 24 #include <QDir>
Chris@66 25 #include <QFile>
Chris@66 26 #include <QFileInfo>
Chris@165 27 #include <QTextStream>
Chris@66 28
Chris@0 29 #include <iostream>
Chris@0 30
Chris@408 31 #include "base/Profiler.h"
Chris@408 32
Chris@1147 33 using namespace std;
Chris@1147 34
Chris@249 35 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1
Chris@249 36
Chris@298 37 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper {
Chris@298 38 public:
Chris@298 39 PluginDeletionNotifyAdapter(Vamp::Plugin *plugin,
Chris@298 40 FeatureExtractionPluginFactory *factory) :
Chris@298 41 PluginWrapper(plugin), m_factory(factory) { }
Chris@298 42 virtual ~PluginDeletionNotifyAdapter();
Chris@298 43 protected:
Chris@298 44 FeatureExtractionPluginFactory *m_factory;
Chris@298 45 };
Chris@298 46
Chris@298 47 PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
Chris@298 48 {
Chris@298 49 // see notes in vamp-sdk/hostext/PluginLoader.cpp from which this is drawn
Chris@298 50 Vamp::Plugin *p = m_plugin;
Chris@298 51 delete m_plugin;
Chris@298 52 m_plugin = 0;
Chris@973 53 // acceptable use after free here, as pluginDeleted uses p only as
Chris@973 54 // pointer key and does not deref it
Chris@298 55 if (m_factory) m_factory->pluginDeleted(p);
Chris@298 56 }
Chris@298 57
Chris@0 58 static FeatureExtractionPluginFactory *_nativeInstance = 0;
Chris@0 59
Chris@0 60 FeatureExtractionPluginFactory *
Chris@0 61 FeatureExtractionPluginFactory::instance(QString pluginType)
Chris@0 62 {
Chris@71 63 if (pluginType == "vamp") {
Chris@0 64 if (!_nativeInstance) {
Chris@690 65 // SVDEBUG << "FeatureExtractionPluginFactory::instance(" << pluginType// << "): creating new FeatureExtractionPluginFactory" << endl;
Chris@0 66 _nativeInstance = new FeatureExtractionPluginFactory();
Chris@0 67 }
Chris@0 68 return _nativeInstance;
Chris@0 69 }
Chris@0 70
Chris@0 71 else return 0;
Chris@0 72 }
Chris@0 73
Chris@0 74 FeatureExtractionPluginFactory *
Chris@0 75 FeatureExtractionPluginFactory::instanceFor(QString identifier)
Chris@0 76 {
Chris@0 77 QString type, soName, label;
Chris@0 78 PluginIdentifier::parseIdentifier(identifier, type, soName, label);
Chris@0 79 return instance(type);
Chris@0 80 }
Chris@0 81
Chris@1147 82 vector<QString>
Chris@66 83 FeatureExtractionPluginFactory::getPluginPath()
Chris@66 84 {
Chris@117 85 if (!m_pluginPath.empty()) return m_pluginPath;
Chris@117 86
Chris@1147 87 vector<string> p = Vamp::PluginHostAdapter::getPluginPath();
Chris@186 88 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str());
Chris@186 89 return m_pluginPath;
Chris@66 90 }
Chris@66 91
Chris@1147 92 vector<QString>
Chris@0 93 FeatureExtractionPluginFactory::getAllPluginIdentifiers()
Chris@0 94 {
Chris@0 95 FeatureExtractionPluginFactory *factory;
Chris@1147 96 vector<QString> rv;
Chris@0 97
Chris@66 98 factory = instance("vamp");
Chris@0 99 if (factory) {
Chris@1147 100 vector<QString> tmp = factory->getPluginIdentifiers();
Chris@0 101 for (size_t i = 0; i < tmp.size(); ++i) {
Chris@843 102 // cerr << "identifier: " << tmp[i] << endl;
Chris@0 103 rv.push_back(tmp[i]);
Chris@0 104 }
Chris@0 105 }
Chris@0 106
Chris@0 107 // Plugins can change the locale, revert it to default.
Chris@608 108 RestoreStartupLocale();
Chris@608 109
Chris@0 110 return rv;
Chris@0 111 }
Chris@0 112
Chris@1147 113 vector<QString>
Chris@1147 114 FeatureExtractionPluginFactory::getPluginCandidateFiles()
Chris@1147 115 {
Chris@1147 116 vector<QString> path = getPluginPath();
Chris@1147 117 vector<QString> candidates;
Chris@1147 118
Chris@1147 119 for (QString dirname : path) {
Chris@1147 120
Chris@1147 121 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1160 122 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << dirname << endl;
Chris@1147 123 #endif
Chris@1147 124
Chris@1147 125 QDir pluginDir(dirname, PLUGIN_GLOB,
Chris@1147 126 QDir::Name | QDir::IgnoreCase,
Chris@1147 127 QDir::Files | QDir::Readable);
Chris@1147 128
Chris@1147 129 for (unsigned int j = 0; j < pluginDir.count(); ++j) {
Chris@1147 130 QString soname = pluginDir.filePath(pluginDir[j]);
Chris@1147 131 candidates.push_back(soname);
Chris@1147 132 }
Chris@1147 133 }
Chris@1147 134
Chris@1147 135 return candidates;
Chris@1147 136 }
Chris@1147 137
Chris@1147 138 vector<QString>
Chris@1149 139 FeatureExtractionPluginFactory::winnowPluginCandidates(vector<QString> candidates,
Chris@1149 140 QString &warningMessage)
Chris@1148 141 {
Chris@1148 142 vector<QString> good, bad;
Chris@1148 143 vector<PluginLoadStatus> badStatuses;
Chris@1148 144
Chris@1148 145 for (QString c: candidates) {
Chris@1148 146
Chris@1148 147 PluginLoadStatus status =
Chris@1148 148 TestPluginLoadability(c, "vampGetPluginDescriptor");
Chris@1148 149
Chris@1148 150 if (status == PluginLoadOK) {
Chris@1148 151 good.push_back(c);
Chris@1148 152 } else if (status == UnknownPluginLoadStatus) {
Chris@1148 153 cerr << "WARNING: Unknown load status for plugin candidate \""
Chris@1148 154 << c << "\", continuing" << endl;
Chris@1148 155 good.push_back(c);
Chris@1148 156 } else {
Chris@1148 157 bad.push_back(c);
Chris@1148 158 badStatuses.push_back(status);
Chris@1148 159 }
Chris@1148 160 }
Chris@1148 161
Chris@1148 162 if (!bad.empty()) {
Chris@1149 163 warningMessage =
Chris@1149 164 QObject::tr("<b>Failed to load plugins</b>"
Chris@1149 165 "<p>Failed to load one or more plugin libraries:</p>\n");
Chris@1149 166 warningMessage += "<ul>";
Chris@1150 167 for (int i = 0; in_range_for(bad, i); ++i) {
Chris@1148 168 QString m;
Chris@1148 169 if (badStatuses[i] == PluginLoadFailedToLoadLibrary) {
Chris@1149 170 m = QObject::tr("Failed to load library");
Chris@1148 171 } else if (badStatuses[i] == PluginLoadFailedToFindDescriptor) {
Chris@1149 172 m = QObject::tr("Failed to query plugins from library after loading");
Chris@1148 173 } else if (badStatuses[i] == PluginLoadFailedElsewhere) {
Chris@1149 174 m = QObject::tr("Unknown failure");
Chris@1148 175 } else {
Chris@1149 176 m = QObject::tr("Success: internal error?");
Chris@1148 177 }
Chris@1148 178 warningMessage += QString("<li>%1 (%2)</li>\n")
Chris@1148 179 .arg(bad[i])
Chris@1148 180 .arg(m);
Chris@1148 181 }
Chris@1148 182 warningMessage += "</ul>";
Chris@1148 183 }
Chris@1148 184 return good;
Chris@1148 185 }
Chris@1148 186
Chris@1148 187 vector<QString>
Chris@0 188 FeatureExtractionPluginFactory::getPluginIdentifiers()
Chris@0 189 {
Chris@408 190 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers");
Chris@408 191
Chris@1147 192 vector<QString> rv;
Chris@1149 193 vector<QString> candidates = winnowPluginCandidates(getPluginCandidateFiles(),
Chris@1149 194 m_pluginScanError);
Chris@66 195
Chris@1147 196 for (QString soname : candidates) {
Chris@66 197
Chris@249 198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 199 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl;
Chris@249 200 #endif
Chris@249 201
Chris@1147 202 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
Chris@66 203
Chris@1147 204 if (!libraryHandle) {
Chris@1147 205 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl;
Chris@1147 206 continue;
Chris@1147 207 }
Chris@66 208
Chris@249 209 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 210 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl;
Chris@249 211 #endif
Chris@249 212
Chris@1147 213 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@1147 214 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@66 215
Chris@1147 216 if (!fn) {
Chris@1147 217 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl;
Chris@1147 218 if (DLCLOSE(libraryHandle) != 0) {
Chris@1147 219 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
Chris@66 220 }
Chris@1147 221 continue;
Chris@1147 222 }
Chris@66 223
Chris@249 224 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 225 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
Chris@249 226 #endif
Chris@249 227
Chris@1147 228 const VampPluginDescriptor *descriptor = 0;
Chris@1147 229 int index = 0;
Chris@66 230
Chris@1147 231 map<string, int> known;
Chris@1147 232 bool ok = true;
Chris@1147 233
Chris@1147 234 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@1147 235
Chris@1147 236 if (known.find(descriptor->identifier) != known.end()) {
Chris@1147 237 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library "
Chris@1147 238 << soname
Chris@1147 239 << " returns the same plugin identifier \""
Chris@1147 240 << descriptor->identifier << "\" at indices "
Chris@1147 241 << known[descriptor->identifier] << " and "
Chris@1147 242 << index << endl;
Chris@1160 243 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl;
Chris@1147 244 ok = false;
Chris@1147 245 break;
Chris@1147 246 } else {
Chris@1147 247 known[descriptor->identifier] = index;
Chris@1040 248 }
Chris@1040 249
Chris@1147 250 ++index;
Chris@1147 251 }
Chris@1040 252
Chris@1147 253 if (ok) {
Chris@1040 254
Chris@1147 255 index = 0;
Chris@251 256
Chris@239 257 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@251 258
Chris@1147 259 QString id = PluginIdentifier::createIdentifier
Chris@1147 260 ("vamp", soname, descriptor->identifier);
Chris@1147 261 rv.push_back(id);
Chris@249 262 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 263 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
Chris@249 264 #endif
Chris@1040 265 ++index;
Chris@66 266 }
Chris@1147 267 }
Chris@66 268
Chris@1147 269 if (DLCLOSE(libraryHandle) != 0) {
Chris@1147 270 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
Chris@1147 271 }
Chris@66 272 }
Chris@66 273
Chris@165 274 generateTaxonomy();
Chris@165 275
Chris@0 276 return rv;
Chris@0 277 }
Chris@0 278
Chris@66 279 QString
Chris@66 280 FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir)
Chris@66 281 {
Chris@66 282 QString file = "";
Chris@66 283
Chris@249 284 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 285 cerr << "FeatureExtractionPluginFactory::findPluginFile(\""
Chris@686 286 << soname << "\", \"" << inDir << "\")"
Chris@687 287 << endl;
Chris@249 288 #endif
Chris@249 289
Chris@66 290 if (inDir != "") {
Chris@66 291
Chris@66 292 QDir dir(inDir, PLUGIN_GLOB,
Chris@66 293 QDir::Name | QDir::IgnoreCase,
Chris@66 294 QDir::Files | QDir::Readable);
Chris@66 295 if (!dir.exists()) return "";
Chris@66 296
Chris@66 297 file = dir.filePath(QFileInfo(soname).fileName());
Chris@249 298
Chris@249 299 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) {
Chris@249 300
Chris@249 301 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 302 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
Chris@687 303 << "found trivially at " << file << endl;
Chris@249 304 #endif
Chris@249 305
Chris@66 306 return file;
Chris@66 307 }
Chris@66 308
Chris@66 309 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@66 310 file = dir.filePath(dir[j]);
Chris@66 311 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
Chris@249 312
Chris@249 313 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 314 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
Chris@687 315 << "found \"" << soname << "\" at " << file << endl;
Chris@249 316 #endif
Chris@249 317
Chris@66 318 return file;
Chris@66 319 }
Chris@66 320 }
Chris@66 321
Chris@249 322 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 323 cerr << "FeatureExtractionPluginFactory::findPluginFile (with dir): "
Chris@687 324 << "not found" << endl;
Chris@249 325 #endif
Chris@249 326
Chris@66 327 return "";
Chris@66 328
Chris@66 329 } else {
Chris@66 330
Chris@66 331 QFileInfo fi(soname);
Chris@249 332
Chris@249 333 if (fi.isAbsolute() && fi.exists() && fi.isFile()) {
Chris@249 334 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 335 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
Chris@687 336 << "found trivially at " << soname << endl;
Chris@249 337 #endif
Chris@249 338 return soname;
Chris@249 339 }
Chris@66 340
Chris@66 341 if (fi.isAbsolute() && fi.absolutePath() != "") {
Chris@66 342 file = findPluginFile(soname, fi.absolutePath());
Chris@66 343 if (file != "") return file;
Chris@66 344 }
Chris@66 345
Chris@1147 346 vector<QString> path = getPluginPath();
Chris@1147 347 for (vector<QString>::iterator i = path.begin();
Chris@66 348 i != path.end(); ++i) {
Chris@66 349 if (*i != "") {
Chris@66 350 file = findPluginFile(soname, *i);
Chris@66 351 if (file != "") return file;
Chris@66 352 }
Chris@66 353 }
Chris@66 354
Chris@249 355 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 356 cerr << "FeatureExtractionPluginFactory::findPluginFile: "
Chris@687 357 << "not found" << endl;
Chris@249 358 #endif
Chris@249 359
Chris@66 360 return "";
Chris@66 361 }
Chris@66 362 }
Chris@66 363
Chris@66 364 Vamp::Plugin *
Chris@0 365 FeatureExtractionPluginFactory::instantiatePlugin(QString identifier,
Chris@1040 366 sv_samplerate_t inputSampleRate)
Chris@0 367 {
Chris@408 368 Profiler profiler("FeatureExtractionPluginFactory::instantiatePlugin");
Chris@408 369
Chris@66 370 Vamp::Plugin *rv = 0;
Chris@298 371 Vamp::PluginHostAdapter *plugin = 0;
Chris@66 372
Chris@66 373 const VampPluginDescriptor *descriptor = 0;
Chris@66 374 int index = 0;
Chris@66 375
Chris@66 376 QString type, soname, label;
Chris@66 377 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@71 378 if (type != "vamp") {
Chris@1150 379 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1150 380 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
Chris@1150 381 #endif
Chris@0 382 return 0;
Chris@0 383 }
Chris@0 384
Chris@66 385 QString found = findPluginFile(soname);
Chris@66 386
Chris@66 387 if (found == "") {
Chris@843 388 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
Chris@117 389 return 0;
Chris@66 390 } else if (found != soname) {
Chris@249 391
Chris@249 392 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 393 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl;
Chris@843 394 cerr << soname << " -> " << found << endl;
Chris@249 395 #endif
Chris@249 396
Chris@249 397 }
Chris@0 398
Chris@66 399 soname = found;
Chris@66 400
Chris@435 401 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
Chris@66 402
Chris@66 403 if (!libraryHandle) {
Chris@843 404 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname << ": " << DLERROR() << endl;
Chris@66 405 return 0;
Chris@19 406 }
Chris@19 407
Chris@66 408 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@66 409 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@66 410
Chris@66 411 if (!fn) {
Chris@1140 412 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl;
Chris@66 413 goto done;
Chris@0 414 }
Chris@0 415
Chris@239 416 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@238 417 if (label == descriptor->identifier) break;
Chris@66 418 ++index;
Chris@47 419 }
Chris@47 420
Chris@66 421 if (!descriptor) {
Chris@843 422 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label << "\" in library " << soname << endl;
Chris@66 423 goto done;
Martin@37 424 }
Martin@37 425
Chris@1040 426 plugin = new Vamp::PluginHostAdapter(descriptor, float(inputSampleRate));
Chris@298 427
Chris@298 428 if (plugin) {
Chris@298 429 m_handleMap[plugin] = libraryHandle;
Chris@298 430 rv = new PluginDeletionNotifyAdapter(plugin, this);
Chris@298 431 }
Chris@66 432
Chris@690 433 // SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Constructed Vamp plugin, rv is " << rv << endl;
Chris@79 434
Chris@66 435 //!!! need to dlclose() when plugins from a given library are unloaded
Chris@66 436
Chris@66 437 done:
Chris@66 438 if (!rv) {
Chris@66 439 if (DLCLOSE(libraryHandle) != 0) {
Chris@843 440 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
Chris@66 441 }
Chris@66 442 }
Chris@73 443
Chris@1150 444 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1150 445 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
Chris@1150 446 #endif
Chris@73 447
Chris@66 448 return rv;
Chris@0 449 }
Chris@0 450
Chris@298 451 void
Chris@298 452 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin)
Chris@298 453 {
Chris@298 454 void *handle = m_handleMap[plugin];
Chris@298 455 if (handle) {
Chris@1150 456 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1150 457 cerr << "unloading library " << handle << " for plugin " << plugin << endl;
Chris@1150 458 #endif
Chris@298 459 DLCLOSE(handle);
Chris@298 460 }
Chris@298 461 m_handleMap.erase(plugin);
Chris@298 462 }
Chris@298 463
Chris@165 464 QString
Chris@165 465 FeatureExtractionPluginFactory::getPluginCategory(QString identifier)
Chris@165 466 {
Chris@165 467 return m_taxonomy[identifier];
Chris@165 468 }
Chris@165 469
Chris@165 470 void
Chris@165 471 FeatureExtractionPluginFactory::generateTaxonomy()
Chris@165 472 {
Chris@1147 473 vector<QString> pluginPath = getPluginPath();
Chris@1147 474 vector<QString> path;
Chris@165 475
Chris@165 476 for (size_t i = 0; i < pluginPath.size(); ++i) {
Chris@165 477 if (pluginPath[i].contains("/lib/")) {
Chris@165 478 QString p(pluginPath[i]);
Chris@165 479 path.push_back(p);
Chris@165 480 p.replace("/lib/", "/share/");
Chris@165 481 path.push_back(p);
Chris@165 482 }
Chris@165 483 path.push_back(pluginPath[i]);
Chris@165 484 }
Chris@165 485
Chris@165 486 for (size_t i = 0; i < path.size(); ++i) {
Chris@165 487
Chris@165 488 QDir dir(path[i], "*.cat");
Chris@165 489
Chris@690 490 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl;
Chris@165 491 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@165 492
Chris@165 493 QFile file(path[i] + "/" + dir[j]);
Chris@165 494
Chris@690 495 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
Chris@165 496
Chris@165 497 if (file.open(QIODevice::ReadOnly)) {
Chris@843 498 // cerr << "...opened" << endl;
Chris@165 499 QTextStream stream(&file);
Chris@165 500 QString line;
Chris@165 501
Chris@165 502 while (!stream.atEnd()) {
Chris@165 503 line = stream.readLine();
Chris@843 504 // cerr << "line is: \"" << line << "\"" << endl;
Chris@165 505 QString id = PluginIdentifier::canonicalise
Chris@165 506 (line.section("::", 0, 0));
Chris@165 507 QString cat = line.section("::", 1, 1);
Chris@165 508 m_taxonomy[id] = cat;
Chris@843 509 // cerr << "FeatureExtractionPluginFactory: set id \"" << id << "\" to cat \"" << cat << "\"" << endl;
Chris@165 510 }
Chris@165 511 }
Chris@165 512 }
Chris@165 513 }
Chris@165 514 }