annotate plugin/NativeVampPluginFactory.cpp @ 1879:652c5360e682

Ensure transforms are populated before instantiateDefaultPluginFor runs - otherwise if we have prior knowledge of a transform id, we can find ourselves trying to instantiate it before the plugin factory has heard of it and e.g. knows which server to use
author Chris Cannam
date Thu, 25 Jun 2020 12:20:06 +0100
parents 5f8fbbde08ff
children
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@1830 300 std::shared_ptr<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@1830 306 std::shared_ptr<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@1830 366 rv = std::shared_ptr<Vamp::Plugin>
Chris@1830 367 (new PluginDeletionNotifyAdapter(plugin, this));
Chris@1225 368 }
Chris@1225 369
Chris@1776 370 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 371 if (rv) {
Chris@1776 372 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
Chris@1776 373 }
Chris@1776 374 #endif
Chris@1225 375
Chris@1225 376 done:
Chris@1225 377 if (!rv) {
Chris@1776 378 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Failed to construct plugin" << endl;
Chris@1225 379 if (DLCLOSE(libraryHandle) != 0) {
Chris@1247 380 SVDEBUG << "WARNING: NativeVampPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
Chris@1225 381 }
Chris@1225 382 }
Chris@1225 383
Chris@0 384 return rv;
Chris@0 385 }
Chris@0 386
Chris@1225 387 void
Chris@1830 388 NativeVampPluginFactory::pluginDeleted(Vamp::Plugin* plugin)
Chris@0 389 {
Chris@1225 390 void *handle = m_handleMap[plugin];
Chris@1776 391 if (!handle) return;
Chris@1776 392
Chris@1776 393 m_handleMap.erase(plugin);
Chris@1776 394
Chris@1225 395 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
Chris@1776 396 SVCERR << "NativeVampPluginFactory::pluginDeleted: Removed from handle map, which now has " << m_handleMap.size() << " entries" << endl;
Chris@1225 397 #endif
Chris@1776 398
Chris@1776 399 for (auto h: m_handleMap) {
Chris@1776 400 if (h.second == handle) {
Chris@1776 401 // still in use
Chris@1776 402 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Not unloading library " << handle << " as other plugins are still loaded from it" << endl;
Chris@1776 403 return;
Chris@1776 404 }
Chris@1225 405 }
Chris@1776 406
Chris@1776 407 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Unloading library " << handle << " after last plugin from this library " << plugin << " was deleted" << endl;
Chris@1776 408 DLCLOSE(handle);
Chris@1225 409 }
Chris@408 410
Chris@1225 411 QString
Chris@1225 412 NativeVampPluginFactory::getPluginCategory(QString identifier)
Chris@1225 413 {
Chris@1225 414 return m_taxonomy[identifier];
Chris@1225 415 }
Chris@1225 416
Chris@1464 417 QString
Chris@1464 418 NativeVampPluginFactory::getPluginLibraryPath(QString identifier)
Chris@1464 419 {
Chris@1464 420 return m_libraries[identifier];
Chris@1464 421 }
Chris@1464 422
Chris@1225 423 void
Chris@1225 424 NativeVampPluginFactory::generateTaxonomy()
Chris@1225 425 {
Chris@1225 426 vector<QString> pluginPath = getPluginPath();
Chris@1225 427 vector<QString> path;
Chris@1225 428
Chris@1225 429 for (size_t i = 0; i < pluginPath.size(); ++i) {
Chris@1429 430 if (pluginPath[i].contains("/lib/")) {
Chris@1429 431 QString p(pluginPath[i]);
Chris@1225 432 path.push_back(p);
Chris@1429 433 p.replace("/lib/", "/share/");
Chris@1429 434 path.push_back(p);
Chris@1429 435 }
Chris@1429 436 path.push_back(pluginPath[i]);
Chris@1225 437 }
Chris@1225 438
Chris@1225 439 for (size_t i = 0; i < path.size(); ++i) {
Chris@1225 440
Chris@1429 441 QDir dir(path[i], "*.cat");
Chris@1225 442
Chris@1429 443 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl;
Chris@1429 444 for (unsigned int j = 0; j < dir.count(); ++j) {
Chris@1225 445
Chris@1429 446 QFile file(path[i] + "/" + dir[j]);
Chris@1225 447
Chris@1429 448 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
Chris@1225 449
Chris@1429 450 if (file.open(QIODevice::ReadOnly)) {
Chris@1429 451 QTextStream stream(&file);
Chris@1429 452 QString line;
Chris@1225 453
Chris@1429 454 while (!stream.atEnd()) {
Chris@1429 455 line = stream.readLine();
Chris@1429 456 QString id = PluginIdentifier::canonicalise
Chris@1225 457 (line.section("::", 0, 0));
Chris@1429 458 QString cat = line.section("::", 1, 1);
Chris@1429 459 m_taxonomy[id] = cat;
Chris@1429 460 }
Chris@1429 461 }
Chris@1429 462 }
Chris@1225 463 }
Chris@1225 464 }
Chris@1225 465
Chris@1225 466 piper_vamp::PluginStaticData
Chris@1225 467 NativeVampPluginFactory::getPluginStaticData(QString identifier)
Chris@1225 468 {
Chris@1209 469 QMutexLocker locker(&m_mutex);
Chris@1209 470
Chris@1225 471 if (m_pluginData.find(identifier) != m_pluginData.end()) {
Chris@1225 472 return m_pluginData[identifier];
Chris@1209 473 }
Chris@1210 474
Chris@66 475 QString type, soname, label;
Chris@66 476 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@1210 477 std::string pluginKey = (soname + ":" + label).toStdString();
Chris@0 478
Chris@1225 479 std::vector<std::string> catlist;
Chris@1225 480 for (auto s: getPluginCategory(identifier).split(" > ")) {
Chris@1225 481 catlist.push_back(s.toStdString());
Chris@1225 482 }
Chris@1225 483
Chris@1830 484 std::shared_ptr<Vamp::Plugin> p = instantiatePlugin(identifier, 44100);
Chris@1225 485 if (!p) return {};
Chris@66 486
Chris@1225 487 auto psd = piper_vamp::PluginStaticData::fromPlugin(pluginKey,
Chris@1225 488 catlist,
Chris@1830 489 p.get());
Chris@1225 490
Chris@1225 491 m_pluginData[identifier] = psd;
Chris@1225 492 return psd;
Chris@298 493 }
Chris@298 494