annotate plugin/NativeVampPluginFactory.cpp @ 1776:5750b9e60818

Don't even ask to unload a library if we know about other plugins that are loaded from it. Plus debug tweaks
author Chris Cannam
date Mon, 09 Sep 2019 10:25:16 +0100
parents 70e172e6cc59
children 5f8fbbde08ff
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@1225 7 This file copyright 2006-2016 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@1225 16 #include "NativeVampPluginFactory.h"
Chris@0 17 #include "PluginIdentifier.h"
Chris@0 18
Chris@1225 19 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@1225 20 #include <vamp-hostsdk/PluginWrapper.h>
Chris@1225 21
Chris@150 22 #include "system/System.h"
Chris@66 23
Chris@1179 24 #include "PluginScan.h"
Chris@1179 25
Chris@66 26 #include <QDir>
Chris@66 27 #include <QFile>
Chris@66 28 #include <QFileInfo>
Chris@165 29 #include <QTextStream>
Chris@66 30
Chris@0 31 #include <iostream>
Chris@0 32
Chris@408 33 #include "base/Profiler.h"
Chris@408 34
Chris@1225 35 #include <QMutex>
Chris@1225 36 #include <QMutexLocker>
Chris@1223 37
Chris@1164 38 using namespace std;
Chris@1164 39
Chris@249 40 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1
Chris@249 41
Chris@1225 42 class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper {
Chris@1225 43 public:
Chris@1225 44 PluginDeletionNotifyAdapter(Vamp::Plugin *plugin,
Chris@1225 45 NativeVampPluginFactory *factory) :
Chris@1225 46 PluginWrapper(plugin), m_factory(factory) { }
Chris@1579 47 ~PluginDeletionNotifyAdapter() override;
Chris@1225 48 protected:
Chris@1225 49 NativeVampPluginFactory *m_factory;
Chris@1225 50 };
Chris@0 51
Chris@1225 52 PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
Chris@0 53 {
Chris@1225 54 // see notes in vamp-sdk/hostext/PluginLoader.cpp from which this is drawn
Chris@1225 55 Vamp::Plugin *p = m_plugin;
Chris@1776 56
Chris@1776 57 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 58 SVCERR << "PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter("
Chris@1776 59 << this << " for plugin " << p << ")" << endl;
Chris@1776 60 #endif
Chris@1776 61
Chris@1225 62 delete m_plugin;
Chris@1582 63 m_plugin = nullptr;
Chris@1225 64 // acceptable use after free here, as pluginDeleted uses p only as
Chris@1225 65 // pointer key and does not deref it
Chris@1225 66 if (m_factory) m_factory->pluginDeleted(p);
Chris@66 67 }
Chris@66 68
Chris@1164 69 vector<QString>
Chris@1225 70 NativeVampPluginFactory::getPluginPath()
Chris@0 71 {
Chris@1225 72 if (!m_pluginPath.empty()) return m_pluginPath;
Chris@1225 73
Chris@1225 74 vector<string> p = Vamp::PluginHostAdapter::getPluginPath();
Chris@1225 75 for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str());
Chris@1225 76 return m_pluginPath;
Chris@1225 77 }
Chris@1225 78
Chris@1249 79 static
Chris@1249 80 QList<PluginScan::Candidate>
Chris@1249 81 getCandidateLibraries()
Chris@1249 82 {
Chris@1249 83 #ifdef HAVE_PLUGIN_CHECKER_HELPER
Chris@1249 84 return PluginScan::getInstance()->getCandidateLibrariesFor
Chris@1249 85 (PluginScan::VampPlugin);
Chris@1249 86 #else
Chris@1249 87 auto path = Vamp::PluginHostAdapter::getPluginPath();
Chris@1249 88 QList<PluginScan::Candidate> candidates;
Chris@1249 89 for (string dirname: path) {
Chris@1249 90 SVDEBUG << "NativeVampPluginFactory: scanning directory myself: "
Chris@1249 91 << dirname << endl;
Chris@1249 92 #if defined(_WIN32)
Chris@1249 93 #define PLUGIN_GLOB "*.dll"
Chris@1249 94 #elif defined(__APPLE__)
Chris@1249 95 #define PLUGIN_GLOB "*.dylib *.so"
Chris@1249 96 #else
Chris@1249 97 #define PLUGIN_GLOB "*.so"
Chris@1249 98 #endif
Chris@1249 99 QDir dir(dirname.c_str(), PLUGIN_GLOB,
Chris@1249 100 QDir::Name | QDir::IgnoreCase,
Chris@1249 101 QDir::Files | QDir::Readable);
Chris@1249 102
Chris@1249 103 for (unsigned int i = 0; i < dir.count(); ++i) {
Chris@1464 104 QString libpath = dir.filePath(dir[i]);
Chris@1464 105 candidates.push_back({ libpath, "" });
Chris@1249 106 }
Chris@1249 107 }
Chris@1249 108
Chris@1249 109 return candidates;
Chris@1249 110 #endif
Chris@1249 111 }
Chris@1249 112
Chris@1225 113 vector<QString>
Chris@1227 114 NativeVampPluginFactory::getPluginIdentifiers(QString &)
Chris@1225 115 {
Chris@1225 116 Profiler profiler("NativeVampPluginFactory::getPluginIdentifiers");
Chris@1225 117
Chris@1225 118 QMutexLocker locker(&m_mutex);
Chris@1225 119
Chris@1225 120 if (!m_identifiers.empty()) {
Chris@1225 121 return m_identifiers;
Chris@1225 122 }
Chris@1249 123
Chris@1249 124 auto candidates = getCandidateLibraries();
Chris@0 125
Chris@1249 126 SVDEBUG << "INFO: Have " << candidates.size() << " candidate Vamp plugin libraries" << endl;
Chris@1249 127
Chris@1246 128 for (auto candidate : candidates) {
Chris@1246 129
Chris@1464 130 QString libpath = candidate.libraryPath;
Chris@1225 131
Chris@1464 132 SVDEBUG << "INFO: Considering candidate Vamp plugin library " << libpath << endl;
Chris@1249 133
Chris@1464 134 void *libraryHandle = DLOPEN(libpath, RTLD_LAZY | RTLD_LOCAL);
Chris@1225 135
Chris@1225 136 if (!libraryHandle) {
Chris@1464 137 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to load library " << libpath << ": " << DLERROR() << endl;
Chris@1225 138 continue;
Chris@1225 139 }
Chris@1225 140
Chris@1225 141 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@1225 142 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@1225 143
Chris@1225 144 if (!fn) {
Chris@1464 145 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: No descriptor function in " << libpath << endl;
Chris@1225 146 if (DLCLOSE(libraryHandle) != 0) {
Chris@1464 147 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl;
Chris@1225 148 }
Chris@1225 149 continue;
Chris@1225 150 }
Chris@1225 151
Chris@1225 152 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 153 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
Chris@1225 154 #endif
Chris@1225 155
Chris@1582 156 const VampPluginDescriptor *descriptor = nullptr;
Chris@1225 157 int index = 0;
Chris@1225 158
Chris@1225 159 map<string, int> known;
Chris@1225 160 bool ok = true;
Chris@1225 161
Chris@1225 162 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@1225 163
Chris@1225 164 if (known.find(descriptor->identifier) != known.end()) {
Chris@1247 165 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Plugin library "
Chris@1464 166 << libpath
Chris@1464 167 << " returns the same plugin identifier \""
Chris@1464 168 << descriptor->identifier << "\" at indices "
Chris@1464 169 << known[descriptor->identifier] << " and "
Chris@1464 170 << index << endl;
Chris@1464 171 SVDEBUG << "NativeVampPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl;
Chris@1225 172 ok = false;
Chris@1225 173 break;
Chris@1225 174 } else {
Chris@1225 175 known[descriptor->identifier] = index;
Chris@1225 176 }
Chris@1225 177
Chris@1225 178 ++index;
Chris@1225 179 }
Chris@1225 180
Chris@1225 181 if (ok) {
Chris@1225 182
Chris@1225 183 index = 0;
Chris@1225 184
Chris@1225 185 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@1225 186
Chris@1225 187 QString id = PluginIdentifier::createIdentifier
Chris@1464 188 ("vamp", libpath, descriptor->identifier);
Chris@1225 189 m_identifiers.push_back(id);
Chris@1464 190 m_libraries[id] = libpath;
Chris@1225 191 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 192 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
Chris@1225 193 #endif
Chris@1225 194 ++index;
Chris@1225 195 }
Chris@1225 196 }
Chris@1776 197
Chris@1776 198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 199 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: unloading library " << libraryHandle << endl;
Chris@1776 200 #endif
Chris@1776 201
Chris@1225 202 if (DLCLOSE(libraryHandle) != 0) {
Chris@1464 203 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl;
Chris@1225 204 }
Chris@0 205 }
Chris@0 206
Chris@1225 207 generateTaxonomy();
Chris@1225 208
Chris@0 209 // Plugins can change the locale, revert it to default.
Chris@608 210 RestoreStartupLocale();
Chris@608 211
Chris@1225 212 return m_identifiers;
Chris@1225 213 }
Chris@1225 214
Chris@1225 215 QString
Chris@1225 216 NativeVampPluginFactory::findPluginFile(QString soname, QString inDir)
Chris@1225 217 {
Chris@1225 218 QString file = "";
Chris@1225 219
Chris@1225 220 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 221 SVCERR << "NativeVampPluginFactory::findPluginFile(\""
Chris@1225 222 << soname << "\", \"" << inDir << "\")"
Chris@1225 223 << endl;
Chris@1225 224 #endif
Chris@1225 225
Chris@1225 226 if (inDir != "") {
Chris@1225 227
Chris@1225 228 QDir dir(inDir, PLUGIN_GLOB,
Chris@1225 229 QDir::Name | QDir::IgnoreCase,
Chris@1225 230 QDir::Files | QDir::Readable);
Chris@1225 231 if (!dir.exists()) return "";
Chris@1225 232
Chris@1225 233 file = dir.filePath(QFileInfo(soname).fileName());
Chris@1225 234
Chris@1225 235 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) {
Chris@1225 236
Chris@1225 237 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 238 SVCERR << "NativeVampPluginFactory::findPluginFile: "
Chris@1225 239 << "found trivially at " << file << endl;
Chris@1225 240 #endif
Chris@1225 241
Chris@1225 242 return file;
Chris@1225 243 }
Chris@1225 244
Chris@1429 245 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@1225 246 file = dir.filePath(dir[j]);
Chris@1225 247 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
Chris@1225 248
Chris@1225 249 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 250 SVCERR << "NativeVampPluginFactory::findPluginFile: "
Chris@1225 251 << "found \"" << soname << "\" at " << file << endl;
Chris@1225 252 #endif
Chris@1225 253
Chris@1225 254 return file;
Chris@1225 255 }
Chris@1225 256 }
Chris@1225 257
Chris@1225 258 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 259 SVCERR << "NativeVampPluginFactory::findPluginFile (with dir): "
Chris@1225 260 << "not found" << endl;
Chris@1225 261 #endif
Chris@1225 262
Chris@1225 263 return "";
Chris@1225 264
Chris@1225 265 } else {
Chris@1225 266
Chris@1225 267 QFileInfo fi(soname);
Chris@1225 268
Chris@1225 269 if (fi.isAbsolute() && fi.exists() && fi.isFile()) {
Chris@1225 270 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 271 SVCERR << "NativeVampPluginFactory::findPluginFile: "
Chris@1225 272 << "found trivially at " << soname << endl;
Chris@1225 273 #endif
Chris@1225 274 return soname;
Chris@1225 275 }
Chris@1225 276
Chris@1225 277 if (fi.isAbsolute() && fi.absolutePath() != "") {
Chris@1225 278 file = findPluginFile(soname, fi.absolutePath());
Chris@1225 279 if (file != "") return file;
Chris@1225 280 }
Chris@1225 281
Chris@1225 282 vector<QString> path = getPluginPath();
Chris@1225 283 for (vector<QString>::iterator i = path.begin();
Chris@1225 284 i != path.end(); ++i) {
Chris@1225 285 if (*i != "") {
Chris@1225 286 file = findPluginFile(soname, *i);
Chris@1225 287 if (file != "") return file;
Chris@1225 288 }
Chris@1225 289 }
Chris@1225 290
Chris@1225 291 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 292 SVCERR << "NativeVampPluginFactory::findPluginFile: "
Chris@1225 293 << "not found" << endl;
Chris@1225 294 #endif
Chris@1225 295
Chris@1225 296 return "";
Chris@1225 297 }
Chris@1225 298 }
Chris@1225 299
Chris@1225 300 Vamp::Plugin *
Chris@1225 301 NativeVampPluginFactory::instantiatePlugin(QString identifier,
Chris@1225 302 sv_samplerate_t inputSampleRate)
Chris@1225 303 {
Chris@1225 304 Profiler profiler("NativeVampPluginFactory::instantiatePlugin");
Chris@1225 305
Chris@1582 306 Vamp::Plugin *rv = nullptr;
Chris@1582 307 Vamp::PluginHostAdapter *plugin = nullptr;
Chris@1225 308
Chris@1582 309 const VampPluginDescriptor *descriptor = nullptr;
Chris@1225 310 int index = 0;
Chris@1225 311
Chris@1225 312 QString type, soname, label;
Chris@1225 313 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@1225 314 if (type != "vamp") {
Chris@1225 315 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 316 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
Chris@1225 317 #endif
Chris@1582 318 return nullptr;
Chris@1225 319 }
Chris@1225 320
Chris@1225 321 QString found = findPluginFile(soname);
Chris@1225 322
Chris@1225 323 if (found == "") {
Chris@1247 324 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
Chris@1582 325 return nullptr;
Chris@1225 326 } else if (found != soname) {
Chris@1225 327
Chris@1225 328 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 329 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl;
Chris@1776 330 SVCERR << soname << " -> " << found << endl;
Chris@1225 331 #endif
Chris@1225 332
Chris@1225 333 }
Chris@1225 334
Chris@1225 335 soname = found;
Chris@1225 336
Chris@1225 337 void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
Chris@1225 338
Chris@1225 339 if (!libraryHandle) {
Chris@1247 340 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Failed to load library " << soname << ": " << DLERROR() << endl;
Chris@1582 341 return nullptr;
Chris@1225 342 }
Chris@1225 343
Chris@1225 344 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
Chris@1225 345 DLSYM(libraryHandle, "vampGetPluginDescriptor");
Chris@1225 346
Chris@1225 347 if (!fn) {
Chris@1247 348 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl;
Chris@1225 349 goto done;
Chris@1225 350 }
Chris@1225 351
Chris@1225 352 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@1225 353 if (label == descriptor->identifier) break;
Chris@1225 354 ++index;
Chris@1225 355 }
Chris@1225 356
Chris@1225 357 if (!descriptor) {
Chris@1247 358 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Failed to find plugin \"" << label << "\" in library " << soname << endl;
Chris@1225 359 goto done;
Chris@1225 360 }
Chris@1225 361
Chris@1225 362 plugin = new Vamp::PluginHostAdapter(descriptor, float(inputSampleRate));
Chris@1225 363
Chris@1225 364 if (plugin) {
Chris@1225 365 m_handleMap[plugin] = libraryHandle;
Chris@1225 366 rv = new PluginDeletionNotifyAdapter(plugin, this);
Chris@1225 367 }
Chris@1225 368
Chris@1776 369 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 370 if (rv) {
Chris@1776 371 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
Chris@1776 372 }
Chris@1776 373 #endif
Chris@1225 374
Chris@1225 375 done:
Chris@1225 376 if (!rv) {
Chris@1776 377 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Failed to construct plugin" << endl;
Chris@1225 378 if (DLCLOSE(libraryHandle) != 0) {
Chris@1247 379 SVDEBUG << "WARNING: NativeVampPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
Chris@1225 380 }
Chris@1225 381 }
Chris@1225 382
Chris@0 383 return rv;
Chris@0 384 }
Chris@0 385
Chris@1225 386 void
Chris@1225 387 NativeVampPluginFactory::pluginDeleted(Vamp::Plugin *plugin)
Chris@0 388 {
Chris@1225 389 void *handle = m_handleMap[plugin];
Chris@1776 390 if (!handle) return;
Chris@1776 391
Chris@1776 392 m_handleMap.erase(plugin);
Chris@1776 393
Chris@1225 394 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 395 SVCERR << "NativeVampPluginFactory::pluginDeleted: Removed from handle map, which now has " << m_handleMap.size() << " entries" << endl;
Chris@1225 396 #endif
Chris@1776 397
Chris@1776 398 for (auto h: m_handleMap) {
Chris@1776 399 if (h.second == handle) {
Chris@1776 400 // still in use
Chris@1776 401 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Not unloading library " << handle << " as other plugins are still loaded from it" << endl;
Chris@1776 402 return;
Chris@1776 403 }
Chris@1225 404 }
Chris@1776 405
Chris@1776 406 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Unloading library " << handle << " after last plugin from this library " << plugin << " was deleted" << endl;
Chris@1776 407 DLCLOSE(handle);
Chris@1225 408 }
Chris@408 409
Chris@1225 410 QString
Chris@1225 411 NativeVampPluginFactory::getPluginCategory(QString identifier)
Chris@1225 412 {
Chris@1225 413 return m_taxonomy[identifier];
Chris@1225 414 }
Chris@1225 415
Chris@1464 416 QString
Chris@1464 417 NativeVampPluginFactory::getPluginLibraryPath(QString identifier)
Chris@1464 418 {
Chris@1464 419 return m_libraries[identifier];
Chris@1464 420 }
Chris@1464 421
Chris@1225 422 void
Chris@1225 423 NativeVampPluginFactory::generateTaxonomy()
Chris@1225 424 {
Chris@1225 425 vector<QString> pluginPath = getPluginPath();
Chris@1225 426 vector<QString> path;
Chris@1225 427
Chris@1225 428 for (size_t i = 0; i < pluginPath.size(); ++i) {
Chris@1429 429 if (pluginPath[i].contains("/lib/")) {
Chris@1429 430 QString p(pluginPath[i]);
Chris@1225 431 path.push_back(p);
Chris@1429 432 p.replace("/lib/", "/share/");
Chris@1429 433 path.push_back(p);
Chris@1429 434 }
Chris@1429 435 path.push_back(pluginPath[i]);
Chris@1225 436 }
Chris@1225 437
Chris@1225 438 for (size_t i = 0; i < path.size(); ++i) {
Chris@1225 439
Chris@1429 440 QDir dir(path[i], "*.cat");
Chris@1225 441
Chris@1429 442 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl;
Chris@1429 443 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@1225 444
Chris@1429 445 QFile file(path[i] + "/" + dir[j]);
Chris@1225 446
Chris@1429 447 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
Chris@1225 448
Chris@1429 449 if (file.open(QIODevice::ReadOnly)) {
Chris@1429 450 QTextStream stream(&file);
Chris@1429 451 QString line;
Chris@1225 452
Chris@1429 453 while (!stream.atEnd()) {
Chris@1429 454 line = stream.readLine();
Chris@1429 455 QString id = PluginIdentifier::canonicalise
Chris@1225 456 (line.section("::", 0, 0));
Chris@1429 457 QString cat = line.section("::", 1, 1);
Chris@1429 458 m_taxonomy[id] = cat;
Chris@1429 459 }
Chris@1429 460 }
Chris@1429 461 }
Chris@1225 462 }
Chris@1225 463 }
Chris@1225 464
Chris@1225 465 piper_vamp::PluginStaticData
Chris@1225 466 NativeVampPluginFactory::getPluginStaticData(QString identifier)
Chris@1225 467 {
Chris@1209 468 QMutexLocker locker(&m_mutex);
Chris@1209 469
Chris@1225 470 if (m_pluginData.find(identifier) != m_pluginData.end()) {
Chris@1225 471 return m_pluginData[identifier];
Chris@1209 472 }
Chris@1210 473
Chris@66 474 QString type, soname, label;
Chris@66 475 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@1210 476 std::string pluginKey = (soname + ":" + label).toStdString();
Chris@0 477
Chris@1225 478 std::vector<std::string> catlist;
Chris@1225 479 for (auto s: getPluginCategory(identifier).split(" > ")) {
Chris@1225 480 catlist.push_back(s.toStdString());
Chris@1225 481 }
Chris@1225 482
Chris@1225 483 Vamp::Plugin *p = instantiatePlugin(identifier, 44100);
Chris@1225 484 if (!p) return {};
Chris@66 485
Chris@1225 486 auto psd = piper_vamp::PluginStaticData::fromPlugin(pluginKey,
Chris@1225 487 catlist,
Chris@1225 488 p);
Chris@1225 489
Chris@1225 490 delete p;
Chris@1225 491
Chris@1225 492 m_pluginData[identifier] = psd;
Chris@1225 493 return psd;
Chris@298 494 }
Chris@298 495