annotate plugin/FeatureExtractionPluginFactory.cpp @ 1166:4607603c46d0

Show warning to the user when plugin population has problems
author Chris Cannam
date Tue, 19 Jan 2016 12:32:30 +0000
parents d57f9344db19
children 7c4f4701b49f
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@1164 33 using namespace std;
Chris@1164 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@1164 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@1164 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@1164 92 vector<QString>
Chris@0 93 FeatureExtractionPluginFactory::getAllPluginIdentifiers()
Chris@0 94 {
Chris@0 95 FeatureExtractionPluginFactory *factory;
Chris@1164 96 vector<QString> rv;
Chris@0 97
Chris@66 98 factory = instance("vamp");
Chris@0 99 if (factory) {
Chris@1164 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@1164 113 vector<QString>
Chris@1164 114 FeatureExtractionPluginFactory::getPluginCandidateFiles()
Chris@1164 115 {
Chris@1164 116 vector<QString> path = getPluginPath();
Chris@1164 117 vector<QString> candidates;
Chris@1164 118
Chris@1164 119 for (QString dirname : path) {
Chris@1164 120
Chris@1164 121 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1164 122 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << dirname << endl;
Chris@1164 123 #endif
Chris@1164 124
Chris@1164 125 QDir pluginDir(dirname, PLUGIN_GLOB,
Chris@1164 126 QDir::Name | QDir::IgnoreCase,
Chris@1164 127 QDir::Files | QDir::Readable);
Chris@1164 128
Chris@1164 129 for (unsigned int j = 0; j < pluginDir.count(); ++j) {
Chris@1164 130 QString soname = pluginDir.filePath(pluginDir[j]);
Chris@1164 131 candidates.push_back(soname);
Chris@1164 132 }
Chris@1164 133 }
Chris@1164 134
Chris@1164 135 return candidates;
Chris@1164 136 }
Chris@1164 137
Chris@1164 138 vector<QString>
Chris@1166 139 FeatureExtractionPluginFactory::winnowPluginCandidates(vector<QString> candidates,
Chris@1166 140 QString &warningMessage)
Chris@1165 141 {
Chris@1165 142 vector<QString> good, bad;
Chris@1165 143 vector<PluginLoadStatus> badStatuses;
Chris@1165 144
Chris@1165 145 for (QString c: candidates) {
Chris@1165 146
Chris@1165 147 PluginLoadStatus status =
Chris@1165 148 TestPluginLoadability(c, "vampGetPluginDescriptor");
Chris@1165 149
Chris@1165 150 if (status == PluginLoadOK) {
Chris@1165 151 good.push_back(c);
Chris@1165 152 } else if (status == UnknownPluginLoadStatus) {
Chris@1165 153 cerr << "WARNING: Unknown load status for plugin candidate \""
Chris@1165 154 << c << "\", continuing" << endl;
Chris@1165 155 good.push_back(c);
Chris@1165 156 } else {
Chris@1165 157 bad.push_back(c);
Chris@1165 158 badStatuses.push_back(status);
Chris@1165 159 }
Chris@1165 160 }
Chris@1165 161
Chris@1165 162 if (!bad.empty()) {
Chris@1166 163 warningMessage =
Chris@1166 164 QObject::tr("<b>Failed to load plugins</b>"
Chris@1166 165 "<p>Failed to load one or more plugin libraries:</p>\n");
Chris@1166 166 warningMessage += "<ul>";
Chris@1165 167 for (int i = 0; i < bad.size(); ++i) {
Chris@1165 168 QString m;
Chris@1165 169 if (badStatuses[i] == PluginLoadFailedToLoadLibrary) {
Chris@1166 170 m = QObject::tr("Failed to load library");
Chris@1165 171 } else if (badStatuses[i] == PluginLoadFailedToFindDescriptor) {
Chris@1166 172 m = QObject::tr("Failed to query plugins from library after loading");
Chris@1165 173 } else if (badStatuses[i] == PluginLoadFailedElsewhere) {
Chris@1166 174 m = QObject::tr("Unknown failure");
Chris@1165 175 } else {
Chris@1166 176 m = QObject::tr("Success: internal error?");
Chris@1165 177 }
Chris@1165 178 warningMessage += QString("<li>%1 (%2)</li>\n")
Chris@1165 179 .arg(bad[i])
Chris@1165 180 .arg(m);
Chris@1165 181 }
Chris@1165 182 warningMessage += "</ul>";
Chris@1165 183 }
Chris@1165 184 return good;
Chris@1165 185 }
Chris@1165 186
Chris@1165 187 vector<QString>
Chris@0 188 FeatureExtractionPluginFactory::getPluginIdentifiers()
Chris@0 189 {
Chris@408 190 Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers");
Chris@408 191
Chris@1164 192 vector<QString> rv;
Chris@1166 193 vector<QString> candidates = winnowPluginCandidates(getPluginCandidateFiles(),
Chris@1166 194 m_pluginScanError);
Chris@1165 195
Chris@1164 196 for (QString soname : candidates) {
Chris@66 197
Chris@249 198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1164 199 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl;
Chris@249 200 #endif
Chris@66 201
Chris@1164 202 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
Chris@1164 203
Chris@1164 204 if (!libraryHandle) {
Chris@1164 205 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl;
Chris@1164 206 continue;
Chris@1164 207 }
Chris@66 208
Chris@249 209 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1164 210 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl;
Chris@249 211 #endif
Chris@249 212
Chris@1164 213 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@1164 214 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@1164 215
Chris@1164 216 if (!fn) {
Chris@1164 217 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl;
Chris@1164 218 if (DLCLOSE(libraryHandle) != 0) {
Chris@1164 219 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
Chris@1164 220 }
Chris@1164 221 continue;
Chris@1164 222 }
Chris@1164 223
Chris@1164 224 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1164 225 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
Chris@1164 226 #endif
Chris@1164 227
Chris@1164 228 const VampPluginDescriptor *descriptor = 0;
Chris@1164 229 int index = 0;
Chris@1164 230
Chris@1164 231 map<string, int> known;
Chris@1164 232 bool ok = true;
Chris@1164 233
Chris@1164 234 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@1164 235
Chris@1164 236 if (known.find(descriptor->identifier) != known.end()) {
Chris@1164 237 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library "
Chris@1164 238 << soname
Chris@1164 239 << " returns the same plugin identifier \""
Chris@1164 240 << descriptor->identifier << "\" at indices "
Chris@1164 241 << known[descriptor->identifier] << " and "
Chris@1164 242 << index << endl;
Chris@1166 243 cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl;
Chris@1164 244 ok = false;
Chris@1164 245 break;
Chris@1164 246 } else {
Chris@1164 247 known[descriptor->identifier] = index;
Chris@66 248 }
Chris@66 249
Chris@1164 250 ++index;
Chris@1164 251 }
Chris@249 252
Chris@1164 253 if (ok) {
Chris@66 254
Chris@1164 255 index = 0;
Chris@251 256
Chris@239 257 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@251 258
Chris@1164 259 QString id = PluginIdentifier::createIdentifier
Chris@1164 260 ("vamp", soname, descriptor->identifier);
Chris@1164 261 rv.push_back(id);
Chris@1164 262 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1164 263 SVDEBUG << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
Chris@1164 264 #endif
Chris@251 265 ++index;
Chris@251 266 }
Chris@1164 267 }
Chris@66 268
Chris@1164 269 if (DLCLOSE(libraryHandle) != 0) {
Chris@1164 270 cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl;
Chris@1164 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@1164 346 vector<QString> path = getPluginPath();
Chris@1164 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@1140 379 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
Chris@0 380 return 0;
Chris@0 381 }
Chris@0 382
Chris@66 383 QString found = findPluginFile(soname);
Chris@66 384
Chris@66 385 if (found == "") {
Chris@843 386 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
Chris@117 387 return 0;
Chris@66 388 } else if (found != soname) {
Chris@249 389
Chris@249 390 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1140 391 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl;
Chris@843 392 cerr << soname << " -> " << found << endl;
Chris@249 393 #endif
Chris@249 394
Chris@249 395 }
Chris@0 396
Chris@66 397 soname = found;
Chris@66 398
Chris@435 399 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
Chris@66 400
Chris@66 401 if (!libraryHandle) {
Chris@843 402 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname << ": " << DLERROR() << endl;
Chris@66 403 return 0;
Chris@19 404 }
Chris@19 405
Chris@66 406 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@66 407 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@66 408
Chris@66 409 if (!fn) {
Chris@1140 410 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl;
Chris@66 411 goto done;
Chris@0 412 }
Chris@0 413
Chris@239 414 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@238 415 if (label == descriptor->identifier) break;
Chris@66 416 ++index;
Chris@47 417 }
Chris@47 418
Chris@66 419 if (!descriptor) {
Chris@843 420 cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label << "\" in library " << soname << endl;
Chris@66 421 goto done;
Martin@37 422 }
Martin@37 423
Chris@1040 424 plugin = new Vamp::PluginHostAdapter(descriptor, float(inputSampleRate));
Chris@298 425
Chris@298 426 if (plugin) {
Chris@298 427 m_handleMap[plugin] = libraryHandle;
Chris@298 428 rv = new PluginDeletionNotifyAdapter(plugin, this);
Chris@298 429 }
Chris@66 430
Chris@690 431 // SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Constructed Vamp plugin, rv is " << rv << endl;
Chris@79 432
Chris@66 433 //!!! need to dlclose() when plugins from a given library are unloaded
Chris@66 434
Chris@66 435 done:
Chris@66 436 if (!rv) {
Chris@66 437 if (DLCLOSE(libraryHandle) != 0) {
Chris@843 438 cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
Chris@66 439 }
Chris@66 440 }
Chris@73 441
Chris@690 442 // SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
Chris@73 443
Chris@66 444 return rv;
Chris@0 445 }
Chris@0 446
Chris@298 447 void
Chris@298 448 FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin)
Chris@298 449 {
Chris@298 450 void *handle = m_handleMap[plugin];
Chris@298 451 if (handle) {
Chris@690 452 // SVDEBUG << "unloading library " << handle << " for plugin " << plugin << endl;
Chris@298 453 DLCLOSE(handle);
Chris@298 454 }
Chris@298 455 m_handleMap.erase(plugin);
Chris@298 456 }
Chris@298 457
Chris@165 458 QString
Chris@165 459 FeatureExtractionPluginFactory::getPluginCategory(QString identifier)
Chris@165 460 {
Chris@165 461 return m_taxonomy[identifier];
Chris@165 462 }
Chris@165 463
Chris@165 464 void
Chris@165 465 FeatureExtractionPluginFactory::generateTaxonomy()
Chris@165 466 {
Chris@1164 467 vector<QString> pluginPath = getPluginPath();
Chris@1164 468 vector<QString> path;
Chris@165 469
Chris@165 470 for (size_t i = 0; i < pluginPath.size(); ++i) {
Chris@165 471 if (pluginPath[i].contains("/lib/")) {
Chris@165 472 QString p(pluginPath[i]);
Chris@165 473 path.push_back(p);
Chris@165 474 p.replace("/lib/", "/share/");
Chris@165 475 path.push_back(p);
Chris@165 476 }
Chris@165 477 path.push_back(pluginPath[i]);
Chris@165 478 }
Chris@165 479
Chris@165 480 for (size_t i = 0; i < path.size(); ++i) {
Chris@165 481
Chris@165 482 QDir dir(path[i], "*.cat");
Chris@165 483
Chris@690 484 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl;
Chris@165 485 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@165 486
Chris@165 487 QFile file(path[i] + "/" + dir[j]);
Chris@165 488
Chris@690 489 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
Chris@165 490
Chris@165 491 if (file.open(QIODevice::ReadOnly)) {
Chris@843 492 // cerr << "...opened" << endl;
Chris@165 493 QTextStream stream(&file);
Chris@165 494 QString line;
Chris@165 495
Chris@165 496 while (!stream.atEnd()) {
Chris@165 497 line = stream.readLine();
Chris@843 498 // cerr << "line is: \"" << line << "\"" << endl;
Chris@165 499 QString id = PluginIdentifier::canonicalise
Chris@165 500 (line.section("::", 0, 0));
Chris@165 501 QString cat = line.section("::", 1, 1);
Chris@165 502 m_taxonomy[id] = cat;
Chris@843 503 // cerr << "FeatureExtractionPluginFactory: set id \"" << id << "\" to cat \"" << cat << "\"" << endl;
Chris@165 504 }
Chris@165 505 }
Chris@165 506 }
Chris@165 507 }
Chris@165 508 }