annotate transform/TransformFactory.cpp @ 1773:fadd9f8aaa27

This output is too annoying, in the perfectly innocuous case of reading from an aggregate model whose components are different lengths
author Chris Cannam
date Wed, 14 Aug 2019 13:54:23 +0100
parents 70e172e6cc59
children 5f8fbbde08ff
rev   line source
Chris@330 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@330 2
Chris@330 3 /*
Chris@330 4 Sonic Visualiser
Chris@330 5 An audio file viewer and annotation editor.
Chris@330 6 Centre for Digital Music, Queen Mary, University of London.
Chris@330 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@330 8
Chris@330 9 This program is free software; you can redistribute it and/or
Chris@330 10 modify it under the terms of the GNU General Public License as
Chris@330 11 published by the Free Software Foundation; either version 2 of the
Chris@330 12 License, or (at your option) any later version. See the file
Chris@330 13 COPYING included with this distribution for more information.
Chris@330 14 */
Chris@330 15
Chris@330 16 #include "TransformFactory.h"
Chris@330 17
Chris@330 18 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@1225 19
Chris@330 20 #include "plugin/RealTimePluginFactory.h"
Chris@332 21 #include "plugin/RealTimePluginInstance.h"
Chris@330 22 #include "plugin/PluginXml.h"
Chris@330 23
Chris@475 24 #include <vamp-hostsdk/Plugin.h>
Chris@475 25 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@475 26 #include <vamp-hostsdk/PluginWrapper.h>
Chris@330 27
Chris@457 28 #include "rdf/PluginRDFIndexer.h"
Chris@457 29 #include "rdf/PluginRDFDescription.h"
Chris@457 30
Chris@446 31 #include "base/XmlExportable.h"
Chris@446 32
Chris@330 33 #include <iostream>
Chris@330 34 #include <set>
Chris@1546 35 #include <functional>
Chris@330 36
Chris@330 37 #include <QRegExp>
Chris@350 38 #include <QTextStream>
Chris@330 39
Chris@460 40 #include "base/Thread.h"
Chris@460 41
Chris@810 42 //#define DEBUG_TRANSFORM_FACTORY 1
Chris@810 43
Chris@330 44 TransformFactory *
Chris@330 45 TransformFactory::m_instance = new TransformFactory;
Chris@330 46
Chris@330 47 TransformFactory *
Chris@330 48 TransformFactory::getInstance()
Chris@330 49 {
Chris@330 50 return m_instance;
Chris@330 51 }
Chris@330 52
Chris@574 53 void
Chris@574 54 TransformFactory::deleteInstance()
Chris@574 55 {
Chris@690 56 SVDEBUG << "TransformFactory::deleteInstance called" << endl;
Chris@574 57 delete m_instance;
Chris@1582 58 m_instance = nullptr;
Chris@574 59 }
Chris@574 60
Chris@457 61 TransformFactory::TransformFactory() :
Chris@457 62 m_transformsPopulated(false),
Chris@477 63 m_uninstalledTransformsPopulated(false),
Chris@1582 64 m_thread(nullptr),
Chris@976 65 m_exiting(false),
Chris@976 66 m_populatingSlowly(false)
Chris@457 67 {
Chris@457 68 }
Chris@457 69
Chris@330 70 TransformFactory::~TransformFactory()
Chris@330 71 {
Chris@574 72 m_exiting = true;
Chris@574 73 if (m_thread) {
Chris@600 74 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@690 75 SVDEBUG << "TransformFactory::~TransformFactory: waiting on thread" << endl;
Chris@600 76 #endif
Chris@574 77 m_thread->wait();
Chris@574 78 delete m_thread;
Chris@600 79 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@690 80 SVDEBUG << "TransformFactory::~TransformFactory: waited and done" << endl;
Chris@600 81 #endif
Chris@574 82 }
Chris@330 83 }
Chris@330 84
Chris@477 85 void
Chris@477 86 TransformFactory::startPopulationThread()
Chris@477 87 {
Chris@482 88 m_uninstalledTransformsMutex.lock();
Chris@477 89
Chris@482 90 if (m_thread) {
Chris@482 91 m_uninstalledTransformsMutex.unlock();
Chris@482 92 return;
Chris@482 93 }
Chris@482 94 m_thread = new UninstalledTransformsPopulateThread(this);
Chris@477 95
Chris@482 96 m_uninstalledTransformsMutex.unlock();
Chris@482 97
Chris@477 98 m_thread->start();
Chris@477 99 }
Chris@477 100
Chris@481 101 void
Chris@481 102 TransformFactory::UninstalledTransformsPopulateThread::run()
Chris@481 103 {
Chris@481 104 m_factory->m_populatingSlowly = true;
Chris@481 105 sleep(1);
Chris@481 106 m_factory->populateUninstalledTransforms();
Chris@481 107 }
Chris@481 108
Chris@330 109 TransformList
Chris@350 110 TransformFactory::getAllTransformDescriptions()
Chris@330 111 {
Chris@460 112 populateTransforms();
Chris@330 113
Chris@330 114 std::set<TransformDescription> dset;
Chris@1546 115 for (auto i = m_transforms.begin(); i != m_transforms.end(); ++i) {
Chris@600 116 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@1546 117 cerr << "inserting transform into set: id = " << i->second.identifier << " (" << i->second.name << ")" << endl;
Chris@600 118 #endif
Chris@1429 119 dset.insert(i->second);
Chris@330 120 }
Chris@330 121
Chris@330 122 TransformList list;
Chris@1546 123 for (auto i = dset.begin(); i != dset.end(); ++i) {
Chris@600 124 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@1546 125 cerr << "inserting transform into list: id = " << i->identifier << " (" << i->name << ")" << endl;
Chris@600 126 #endif
Chris@1429 127 list.push_back(*i);
Chris@330 128 }
Chris@330 129
Chris@330 130 return list;
Chris@330 131 }
Chris@330 132
Chris@350 133 TransformDescription
Chris@350 134 TransformFactory::getTransformDescription(TransformId id)
Chris@350 135 {
Chris@460 136 populateTransforms();
Chris@350 137
Chris@350 138 if (m_transforms.find(id) == m_transforms.end()) {
Chris@350 139 return TransformDescription();
Chris@350 140 }
Chris@350 141
Chris@350 142 return m_transforms[id];
Chris@350 143 }
Chris@350 144
Chris@485 145 bool
Chris@485 146 TransformFactory::haveInstalledTransforms()
Chris@485 147 {
Chris@485 148 populateTransforms();
Chris@485 149 return !m_transforms.empty();
Chris@485 150 }
Chris@485 151
Chris@457 152 TransformList
Chris@457 153 TransformFactory::getUninstalledTransformDescriptions()
Chris@457 154 {
Chris@479 155 m_populatingSlowly = false;
Chris@460 156 populateUninstalledTransforms();
Chris@457 157
Chris@457 158 std::set<TransformDescription> dset;
Chris@1546 159 for (auto i = m_uninstalledTransforms.begin();
Chris@1429 160 i != m_uninstalledTransforms.end(); ++i) {
Chris@600 161 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 162 cerr << "inserting transform into set: id = " << i->second.identifier << endl;
Chris@600 163 #endif
Chris@1429 164 dset.insert(i->second);
Chris@457 165 }
Chris@457 166
Chris@457 167 TransformList list;
Chris@1546 168 for (auto i = dset.begin(); i != dset.end(); ++i) {
Chris@600 169 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 170 cerr << "inserting transform into uninstalled list: id = " << i->identifier << endl;
Chris@600 171 #endif
Chris@1429 172 list.push_back(*i);
Chris@457 173 }
Chris@457 174
Chris@457 175 return list;
Chris@457 176 }
Chris@457 177
Chris@457 178 TransformDescription
Chris@457 179 TransformFactory::getUninstalledTransformDescription(TransformId id)
Chris@457 180 {
Chris@479 181 m_populatingSlowly = false;
Chris@460 182 populateUninstalledTransforms();
Chris@457 183
Chris@457 184 if (m_uninstalledTransforms.find(id) == m_uninstalledTransforms.end()) {
Chris@457 185 return TransformDescription();
Chris@457 186 }
Chris@457 187
Chris@457 188 return m_uninstalledTransforms[id];
Chris@457 189 }
Chris@457 190
Chris@485 191 bool
Chris@485 192 TransformFactory::haveUninstalledTransforms(bool waitForCheckToComplete)
Chris@485 193 {
Chris@485 194 if (waitForCheckToComplete) {
Chris@485 195 populateUninstalledTransforms();
Chris@485 196 } else {
Chris@485 197 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@485 198 return false;
Chris@485 199 }
Chris@485 200 if (!m_uninstalledTransformsPopulated) {
Chris@485 201 m_uninstalledTransformsMutex.unlock();
Chris@485 202 return false;
Chris@485 203 }
Chris@485 204 m_uninstalledTransformsMutex.unlock();
Chris@485 205 }
Chris@485 206
Chris@485 207 return !m_uninstalledTransforms.empty();
Chris@485 208 }
Chris@485 209
Chris@457 210 TransformFactory::TransformInstallStatus
Chris@457 211 TransformFactory::getTransformInstallStatus(TransformId id)
Chris@457 212 {
Chris@460 213 populateTransforms();
Chris@457 214
Chris@457 215 if (m_transforms.find(id) != m_transforms.end()) {
Chris@457 216 return TransformInstalled;
Chris@457 217 }
Chris@473 218
Chris@473 219 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@473 220 // uninstalled transforms are being populated; this may take some time,
Chris@473 221 // and they aren't critical
Chris@473 222 return TransformUnknown;
Chris@473 223 }
Chris@473 224
Chris@473 225 if (!m_uninstalledTransformsPopulated) {
Chris@473 226 m_uninstalledTransformsMutex.unlock();
Chris@479 227 m_populatingSlowly = false;
Chris@473 228 populateUninstalledTransforms();
Chris@473 229 m_uninstalledTransformsMutex.lock();
Chris@473 230 }
Chris@473 231
Chris@457 232 if (m_uninstalledTransforms.find(id) != m_uninstalledTransforms.end()) {
Chris@482 233 m_uninstalledTransformsMutex.unlock();
Chris@457 234 return TransformNotInstalled;
Chris@457 235 }
Chris@473 236
Chris@473 237 m_uninstalledTransformsMutex.unlock();
Chris@457 238 return TransformUnknown;
Chris@457 239 }
Chris@457 240
Chris@457 241
Chris@487 242 std::vector<TransformDescription::Type>
Chris@330 243 TransformFactory::getAllTransformTypes()
Chris@330 244 {
Chris@460 245 populateTransforms();
Chris@330 246
Chris@487 247 std::set<TransformDescription::Type> types;
Chris@1546 248 for (auto i = m_transforms.begin(); i != m_transforms.end(); ++i) {
Chris@330 249 types.insert(i->second.type);
Chris@330 250 }
Chris@330 251
Chris@487 252 std::vector<TransformDescription::Type> rv;
Chris@1546 253 for (auto i = types.begin(); i != types.end(); ++i) {
Chris@330 254 rv.push_back(*i);
Chris@330 255 }
Chris@330 256
Chris@330 257 return rv;
Chris@330 258 }
Chris@330 259
Chris@330 260 std::vector<QString>
Chris@487 261 TransformFactory::getTransformCategories(TransformDescription::Type transformType)
Chris@330 262 {
Chris@460 263 populateTransforms();
Chris@330 264
Chris@1546 265 std::set<QString, std::function<bool(QString, QString)>>
Chris@1546 266 categories(TransformDescription::compareUserStrings);
Chris@1546 267
Chris@1546 268 for (auto i = m_transforms.begin(); i != m_transforms.end(); ++i) {
Chris@330 269 if (i->second.type == transformType) {
Chris@330 270 categories.insert(i->second.category);
Chris@330 271 }
Chris@330 272 }
Chris@330 273
Chris@330 274 bool haveEmpty = false;
Chris@330 275
Chris@330 276 std::vector<QString> rv;
Chris@1546 277 for (auto i = categories.begin(); i != categories.end(); ++i) {
Chris@330 278 if (*i != "") rv.push_back(*i);
Chris@330 279 else haveEmpty = true;
Chris@330 280 }
Chris@330 281
Chris@330 282 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 283
Chris@330 284 return rv;
Chris@330 285 }
Chris@330 286
Chris@330 287 std::vector<QString>
Chris@487 288 TransformFactory::getTransformMakers(TransformDescription::Type transformType)
Chris@330 289 {
Chris@460 290 populateTransforms();
Chris@330 291
Chris@1546 292 std::set<QString, std::function<bool(QString, QString)>>
Chris@1546 293 makers(TransformDescription::compareUserStrings);
Chris@1546 294
Chris@1546 295 for (auto i = m_transforms.begin(); i != m_transforms.end(); ++i) {
Chris@330 296 if (i->second.type == transformType) {
Chris@330 297 makers.insert(i->second.maker);
Chris@330 298 }
Chris@330 299 }
Chris@330 300
Chris@330 301 bool haveEmpty = false;
Chris@330 302
Chris@330 303 std::vector<QString> rv;
Chris@1546 304 for (auto i = makers.begin(); i != makers.end(); ++i) {
Chris@330 305 if (*i != "") rv.push_back(*i);
Chris@330 306 else haveEmpty = true;
Chris@330 307 }
Chris@330 308
Chris@330 309 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 310
Chris@330 311 return rv;
Chris@330 312 }
Chris@330 313
Chris@487 314 QString
Chris@487 315 TransformFactory::getTransformTypeName(TransformDescription::Type type) const
Chris@487 316 {
Chris@487 317 switch (type) {
Chris@487 318 case TransformDescription::Analysis: return tr("Analysis");
Chris@487 319 case TransformDescription::Effects: return tr("Effects");
Chris@487 320 case TransformDescription::EffectsData: return tr("Effects Data");
Chris@487 321 case TransformDescription::Generator: return tr("Generator");
Chris@487 322 case TransformDescription::UnknownType: return tr("Other");
Chris@487 323 }
Chris@489 324 return tr("Other");
Chris@487 325 }
Chris@487 326
Chris@330 327 void
Chris@330 328 TransformFactory::populateTransforms()
Chris@330 329 {
Chris@460 330 MutexLocker locker(&m_transformsMutex,
Chris@460 331 "TransformFactory::populateTransforms");
Chris@460 332 if (m_transformsPopulated) {
Chris@460 333 return;
Chris@460 334 }
Chris@460 335
Chris@330 336 TransformDescriptionMap transforms;
Chris@330 337
Chris@330 338 populateFeatureExtractionPlugins(transforms);
Chris@576 339 if (m_exiting) return;
Chris@330 340 populateRealTimePlugins(transforms);
Chris@576 341 if (m_exiting) return;
Chris@330 342
Chris@330 343 // disambiguate plugins with similar names
Chris@330 344
Chris@330 345 std::map<QString, int> names;
Chris@330 346 std::map<QString, QString> pluginSources;
Chris@330 347 std::map<QString, QString> pluginMakers;
Chris@330 348
Chris@330 349 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 350 i != transforms.end(); ++i) {
Chris@330 351
Chris@330 352 TransformDescription desc = i->second;
Chris@330 353
Chris@330 354 QString td = desc.name;
Chris@330 355 QString tn = td.section(": ", 0, 0);
Chris@330 356 QString pn = desc.identifier.section(":", 1, 1);
Chris@330 357
Chris@330 358 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330 359 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330 360 ++names[tn];
Chris@330 361 }
Chris@330 362 } else {
Chris@330 363 ++names[tn];
Chris@330 364 pluginSources[tn] = pn;
Chris@330 365 pluginMakers[tn] = desc.maker;
Chris@330 366 }
Chris@330 367 }
Chris@330 368
Chris@330 369 std::map<QString, int> counts;
Chris@330 370 m_transforms.clear();
Chris@330 371
Chris@330 372 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 373 i != transforms.end(); ++i) {
Chris@330 374
Chris@330 375 TransformDescription desc = i->second;
Chris@1429 376 QString identifier = desc.identifier;
Chris@330 377 QString maker = desc.maker;
Chris@330 378
Chris@330 379 QString td = desc.name;
Chris@330 380 QString tn = td.section(": ", 0, 0);
Chris@330 381 QString to = td.section(": ", 1);
Chris@330 382
Chris@1429 383 if (names[tn] > 1) {
Chris@330 384 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@1429 385 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@1429 386 }
Chris@330 387
Chris@330 388 if (to != "") {
Chris@330 389 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330 390 } else {
Chris@330 391 desc.name = tn;
Chris@330 392 }
Chris@330 393
Chris@1429 394 m_transforms[identifier] = desc;
Chris@1429 395 }
Chris@457 396
Chris@457 397 m_transformsPopulated = true;
Chris@330 398 }
Chris@330 399
Chris@330 400 void
Chris@330 401 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330 402 {
Chris@1225 403 FeatureExtractionPluginFactory *factory =
Chris@1225 404 FeatureExtractionPluginFactory::instance();
Chris@1227 405
Chris@1227 406 QString errorMessage;
Chris@1227 407 std::vector<QString> plugs = factory->getPluginIdentifiers(errorMessage);
Chris@1227 408 if (errorMessage != "") {
Chris@1227 409 m_errorString = tr("Failed to list Vamp plugins: %1").arg(errorMessage);
Chris@1227 410 }
Chris@1225 411
Chris@576 412 if (m_exiting) return;
Chris@330 413
Chris@1546 414 for (int i = 0; in_range_for(plugs, i); ++i) {
Chris@330 415
Chris@1429 416 QString pluginId = plugs[i];
Chris@330 417
Chris@1223 418 piper_vamp::PluginStaticData psd = factory->getPluginStaticData(pluginId);
Chris@330 419
Chris@1223 420 if (psd.pluginKey == "") {
Chris@1223 421 cerr << "WARNING: TransformFactory::populateTransforms: No plugin static data available for instance " << pluginId << endl;
Chris@1223 422 continue;
Chris@1223 423 }
Chris@1223 424
Chris@1223 425 QString pluginName = QString::fromStdString(psd.basic.name);
Chris@330 426 QString category = factory->getPluginCategory(pluginId);
Chris@1223 427
Chris@1223 428 const auto &basicOutputs = psd.basicOutputInfo;
Chris@330 429
Chris@1223 430 for (const auto &o: basicOutputs) {
Chris@330 431
Chris@1223 432 QString outputName = QString::fromStdString(o.name);
Chris@330 433
Chris@1429 434 QString transformId = QString("%1:%2")
Chris@1223 435 .arg(pluginId).arg(QString::fromStdString(o.identifier));
Chris@330 436
Chris@1429 437 QString userName;
Chris@330 438 QString friendlyName;
Chris@1223 439 //!!! return to this QString units = outputs[j].unit.c_str();
Chris@1223 440 QString description = QString::fromStdString(psd.basic.description);
Chris@1223 441 QString maker = QString::fromStdString(psd.maker);
Chris@330 442 if (maker == "") maker = tr("<unknown maker>");
Chris@330 443
Chris@443 444 QString longDescription = description;
Chris@443 445
Chris@443 446 if (longDescription == "") {
Chris@1223 447 if (basicOutputs.size() == 1) {
Chris@443 448 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@330 449 .arg(pluginName).arg(maker);
Chris@330 450 } else {
Chris@443 451 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@1223 452 .arg(outputName).arg(pluginName).arg(maker);
Chris@330 453 }
Chris@330 454 } else {
Chris@1223 455 if (basicOutputs.size() == 1) {
Chris@443 456 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@443 457 .arg(longDescription).arg(pluginName).arg(maker);
Chris@330 458 } else {
Chris@443 459 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@1223 460 .arg(longDescription).arg(outputName).arg(pluginName).arg(maker);
Chris@330 461 }
Chris@330 462 }
Chris@330 463
Chris@1429 464 if (basicOutputs.size() == 1) {
Chris@1429 465 userName = pluginName;
Chris@330 466 friendlyName = pluginName;
Chris@1429 467 } else {
Chris@1429 468 userName = QString("%1: %2").arg(pluginName).arg(outputName);
Chris@1223 469 friendlyName = outputName;
Chris@1429 470 }
Chris@330 471
Chris@1223 472 bool configurable = (!psd.programs.empty() ||
Chris@1223 473 !psd.parameters.empty());
Chris@330 474
Chris@600 475 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@686 476 cerr << "Feature extraction plugin transform: " << transformId << " friendly name: " << friendlyName << endl;
Chris@600 477 #endif
Chris@330 478
Chris@1429 479 transforms[transformId] =
Chris@487 480 TransformDescription(TransformDescription::Analysis,
Chris@332 481 category,
Chris@332 482 transformId,
Chris@332 483 userName,
Chris@332 484 friendlyName,
Chris@332 485 description,
Chris@443 486 longDescription,
Chris@332 487 maker,
Chris@1223 488 //!!! units,
Chris@1223 489 "",
Chris@332 490 configurable);
Chris@1429 491 }
Chris@330 492 }
Chris@330 493 }
Chris@330 494
Chris@330 495 void
Chris@330 496 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
Chris@330 497 {
Chris@330 498 std::vector<QString> plugs =
Chris@1429 499 RealTimePluginFactory::getAllPluginIdentifiers();
Chris@576 500 if (m_exiting) return;
Chris@330 501
Chris@330 502 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@330 503
Chris@1546 504 for (int i = 0; in_range_for(plugs, i); ++i) {
Chris@330 505
Chris@1429 506 QString pluginId = plugs[i];
Chris@330 507
Chris@330 508 RealTimePluginFactory *factory =
Chris@330 509 RealTimePluginFactory::instanceFor(pluginId);
Chris@330 510
Chris@1429 511 if (!factory) {
Chris@1429 512 cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId << endl;
Chris@1429 513 continue;
Chris@1429 514 }
Chris@330 515
Chris@330 516 const RealTimePluginDescriptor *descriptor =
Chris@330 517 factory->getPluginDescriptor(pluginId);
Chris@330 518
Chris@330 519 if (!descriptor) {
Chris@1429 520 cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId << endl;
Chris@1429 521 continue;
Chris@1429 522 }
Chris@1429 523
Chris@330 524 //!!! if (descriptor->controlOutputPortCount == 0 ||
Chris@330 525 // descriptor->audioInputPortCount == 0) continue;
Chris@330 526
Chris@843 527 // cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << endl;
Chris@1429 528
Chris@1429 529 QString pluginName = descriptor->name.c_str();
Chris@330 530 QString category = factory->getPluginCategory(pluginId);
Chris@330 531 bool configurable = (descriptor->parameterCount > 0);
Chris@330 532 QString maker = descriptor->maker.c_str();
Chris@330 533 if (maker == "") maker = tr("<unknown maker>");
Chris@330 534
Chris@330 535 if (descriptor->audioInputPortCount > 0) {
Chris@330 536
Chris@930 537 for (int j = 0; j < (int)descriptor->controlOutputPortCount; ++j) {
Chris@330 538
Chris@330 539 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
Chris@330 540 QString userName;
Chris@330 541 QString units;
Chris@330 542 QString portName;
Chris@330 543
Chris@930 544 if (j < (int)descriptor->controlOutputPortNames.size() &&
Chris@330 545 descriptor->controlOutputPortNames[j] != "") {
Chris@330 546
Chris@330 547 portName = descriptor->controlOutputPortNames[j].c_str();
Chris@330 548
Chris@330 549 userName = tr("%1: %2")
Chris@330 550 .arg(pluginName)
Chris@330 551 .arg(portName);
Chris@330 552
Chris@330 553 if (unitRE.indexIn(portName) >= 0) {
Chris@330 554 units = unitRE.cap(1);
Chris@330 555 }
Chris@330 556
Chris@330 557 } else if (descriptor->controlOutputPortCount > 1) {
Chris@330 558
Chris@330 559 userName = tr("%1: Output %2")
Chris@330 560 .arg(pluginName)
Chris@330 561 .arg(j + 1);
Chris@330 562
Chris@330 563 } else {
Chris@330 564
Chris@330 565 userName = pluginName;
Chris@330 566 }
Chris@330 567
Chris@330 568 QString description;
Chris@330 569
Chris@330 570 if (portName != "") {
Chris@330 571 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
Chris@330 572 .arg(portName)
Chris@330 573 .arg(pluginName)
Chris@330 574 .arg(maker);
Chris@330 575 } else {
Chris@330 576 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
Chris@330 577 .arg(j + 1)
Chris@330 578 .arg(pluginName)
Chris@330 579 .arg(maker);
Chris@330 580 }
Chris@330 581
Chris@330 582 transforms[transformId] =
Chris@487 583 TransformDescription(TransformDescription::EffectsData,
Chris@332 584 category,
Chris@332 585 transformId,
Chris@332 586 userName,
Chris@332 587 userName,
Chris@443 588 "",
Chris@332 589 description,
Chris@332 590 maker,
Chris@332 591 units,
Chris@332 592 configurable);
Chris@330 593 }
Chris@330 594 }
Chris@330 595
Chris@330 596 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
Chris@330 597
Chris@330 598 if (descriptor->audioOutputPortCount > 0) {
Chris@330 599
Chris@330 600 QString transformId = QString("%1:A").arg(pluginId);
Chris@487 601 TransformDescription::Type type = TransformDescription::Effects;
Chris@330 602
Chris@330 603 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
Chris@330 604 .arg(pluginName)
Chris@330 605 .arg(maker);
Chris@330 606
Chris@330 607 if (descriptor->audioInputPortCount == 0) {
Chris@487 608 type = TransformDescription::Generator;
Chris@330 609 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
Chris@330 610 .arg(pluginName)
Chris@330 611 .arg(maker);
Chris@330 612 }
Chris@330 613
Chris@330 614 transforms[transformId] =
Chris@330 615 TransformDescription(type,
Chris@332 616 category,
Chris@332 617 transformId,
Chris@332 618 pluginName,
Chris@332 619 pluginName,
Chris@443 620 "",
Chris@332 621 description,
Chris@332 622 maker,
Chris@332 623 "",
Chris@332 624 configurable);
Chris@330 625 }
Chris@330 626 }
Chris@330 627 }
Chris@330 628 }
Chris@330 629
Chris@457 630 void
Chris@457 631 TransformFactory::populateUninstalledTransforms()
Chris@457 632 {
Chris@576 633 if (m_exiting) return;
Chris@576 634
Chris@460 635 populateTransforms();
Chris@576 636 if (m_exiting) return;
Chris@460 637
Chris@460 638 MutexLocker locker(&m_uninstalledTransformsMutex,
Chris@460 639 "TransformFactory::populateUninstalledTransforms");
Chris@460 640 if (m_uninstalledTransformsPopulated) return;
Chris@460 641
Chris@461 642 PluginRDFIndexer::getInstance()->indexConfiguredURLs();
Chris@576 643 if (m_exiting) return;
Chris@457 644
Chris@457 645 //!!! This will be amazingly slow
Chris@457 646
Chris@457 647 QStringList ids = PluginRDFIndexer::getInstance()->getIndexedPluginIds();
Chris@457 648
Chris@457 649 for (QStringList::const_iterator i = ids.begin(); i != ids.end(); ++i) {
Chris@457 650
Chris@457 651 PluginRDFDescription desc(*i);
Chris@457 652
Chris@457 653 QString name = desc.getPluginName();
Chris@600 654 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@600 655 if (name == "") {
Chris@810 656 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@810 657 << "No name available for plugin " << *i
Chris@810 658 << ", skipping" << endl;
Chris@600 659 continue;
Chris@600 660 }
Chris@600 661 #endif
Chris@457 662
Chris@457 663 QString description = desc.getPluginDescription();
Chris@457 664 QString maker = desc.getPluginMaker();
Chris@462 665 QString infoUrl = desc.getPluginInfoURL();
Chris@457 666
Chris@457 667 QStringList oids = desc.getOutputIds();
Chris@457 668
Chris@457 669 for (QStringList::const_iterator j = oids.begin(); j != oids.end(); ++j) {
Chris@457 670
Chris@457 671 TransformId tid = Transform::getIdentifierForPluginOutput(*i, *j);
Chris@457 672
Chris@457 673 if (m_transforms.find(tid) != m_transforms.end()) {
Chris@600 674 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 675 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@687 676 << tid << " is installed; adding info url if appropriate, skipping rest" << endl;
Chris@600 677 #endif
Chris@468 678 if (infoUrl != "") {
Chris@468 679 if (m_transforms[tid].infoUrl == "") {
Chris@468 680 m_transforms[tid].infoUrl = infoUrl;
Chris@468 681 }
Chris@468 682 }
Chris@457 683 continue;
Chris@457 684 }
Chris@457 685
Chris@600 686 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 687 cerr << "TransformFactory::populateUninstalledTransforms: "
Chris@687 688 << "adding " << tid << endl;
Chris@600 689 #endif
Chris@457 690
Chris@457 691 QString oname = desc.getOutputName(*j);
Chris@457 692 if (oname == "") oname = *j;
Chris@457 693
Chris@457 694 TransformDescription td;
Chris@487 695 td.type = TransformDescription::Analysis;
Chris@457 696 td.category = "";
Chris@457 697 td.identifier = tid;
Chris@457 698
Chris@457 699 if (oids.size() == 1) {
Chris@457 700 td.name = name;
Chris@457 701 } else if (name != "") {
Chris@457 702 td.name = tr("%1: %2").arg(name).arg(oname);
Chris@457 703 }
Chris@457 704
Chris@462 705 QString longDescription = description;
Chris@462 706 //!!! basically duplicated from above
Chris@462 707 if (longDescription == "") {
Chris@462 708 if (oids.size() == 1) {
Chris@462 709 longDescription = tr("Extract features using \"%1\" plugin (from %2)")
Chris@462 710 .arg(name).arg(maker);
Chris@462 711 } else {
Chris@462 712 longDescription = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
Chris@462 713 .arg(oname).arg(name).arg(maker);
Chris@462 714 }
Chris@462 715 } else {
Chris@462 716 if (oids.size() == 1) {
Chris@462 717 longDescription = tr("%1 using \"%2\" plugin (from %3)")
Chris@462 718 .arg(longDescription).arg(name).arg(maker);
Chris@462 719 } else {
Chris@462 720 longDescription = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
Chris@462 721 .arg(longDescription).arg(oname).arg(name).arg(maker);
Chris@462 722 }
Chris@462 723 }
Chris@462 724
Chris@457 725 td.friendlyName = name; //!!!???
Chris@457 726 td.description = description;
Chris@462 727 td.longDescription = longDescription;
Chris@457 728 td.maker = maker;
Chris@462 729 td.infoUrl = infoUrl;
Chris@457 730 td.units = "";
Chris@457 731 td.configurable = false;
Chris@457 732
Chris@457 733 m_uninstalledTransforms[tid] = td;
Chris@457 734 }
Chris@574 735
Chris@576 736 if (m_exiting) return;
Chris@457 737 }
Chris@457 738
Chris@457 739 m_uninstalledTransformsPopulated = true;
Chris@460 740
Chris@600 741 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@843 742 cerr << "populateUninstalledTransforms exiting" << endl;
Chris@600 743 #endif
Chris@457 744 }
Chris@350 745
Chris@350 746 Transform
Chris@1047 747 TransformFactory::getDefaultTransformFor(TransformId id, sv_samplerate_t rate)
Chris@350 748 {
Chris@350 749 Transform t;
Chris@350 750 t.setIdentifier(id);
Chris@1047 751 if (rate != 0) t.setSampleRate(rate);
Chris@350 752
Chris@1264 753 SVDEBUG << "TransformFactory::getDefaultTransformFor: identifier \""
Chris@1264 754 << id << "\"" << endl;
Chris@1264 755
Chris@351 756 Vamp::PluginBase *plugin = instantiateDefaultPluginFor(id, rate);
Chris@350 757
Chris@350 758 if (plugin) {
Chris@366 759 t.setPluginVersion(QString("%1").arg(plugin->getPluginVersion()));
Chris@350 760 setParametersFromPlugin(t, plugin);
Chris@350 761 makeContextConsistentWithPlugin(t, plugin);
Chris@350 762 delete plugin;
Chris@350 763 }
Chris@350 764
Chris@350 765 return t;
Chris@350 766 }
Chris@350 767
Chris@350 768 Vamp::PluginBase *
Chris@351 769 TransformFactory::instantiatePluginFor(const Transform &transform)
Chris@351 770 {
Chris@1264 771 SVDEBUG << "TransformFactory::instantiatePluginFor: identifier \""
Chris@1264 772 << transform.getIdentifier() << "\"" << endl;
Chris@1264 773
Chris@351 774 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@1047 775 (transform.getIdentifier(), transform.getSampleRate());
Chris@508 776
Chris@351 777 if (plugin) {
Chris@351 778 setPluginParameters(transform, plugin);
Chris@351 779 }
Chris@508 780
Chris@351 781 return plugin;
Chris@351 782 }
Chris@351 783
Chris@351 784 Vamp::PluginBase *
Chris@1047 785 TransformFactory::instantiateDefaultPluginFor(TransformId identifier,
Chris@1047 786 sv_samplerate_t rate)
Chris@350 787 {
Chris@350 788 Transform t;
Chris@350 789 t.setIdentifier(identifier);
Chris@1047 790 if (rate == 0) rate = 44100.0;
Chris@350 791 QString pluginId = t.getPluginIdentifier();
Chris@350 792
Chris@1582 793 Vamp::PluginBase *plugin = nullptr;
Chris@350 794
Chris@350 795 if (t.getType() == Transform::FeatureExtraction) {
Chris@350 796
Chris@1264 797 SVDEBUG << "TransformFactory::instantiateDefaultPluginFor: identifier \""
Chris@1264 798 << identifier << "\" is a feature extraction transform" << endl;
Chris@1139 799
Chris@1225 800 FeatureExtractionPluginFactory *factory =
Chris@1225 801 FeatureExtractionPluginFactory::instance();
Chris@350 802
Chris@439 803 if (factory) {
Chris@1047 804 plugin = factory->instantiatePlugin(pluginId, rate);
Chris@439 805 }
Chris@350 806
Chris@1139 807 } else if (t.getType() == Transform::RealTimeEffect) {
Chris@1139 808
Chris@1264 809 SVDEBUG << "TransformFactory::instantiateDefaultPluginFor: identifier \""
Chris@1264 810 << identifier << "\" is a real-time transform" << endl;
Chris@350 811
Chris@350 812 RealTimePluginFactory *factory =
Chris@350 813 RealTimePluginFactory::instanceFor(pluginId);
Chris@439 814
Chris@439 815 if (factory) {
Chris@439 816 plugin = factory->instantiatePlugin(pluginId, 0, 0, rate, 1024, 1);
Chris@439 817 }
Chris@1139 818
Chris@1139 819 } else {
Chris@1264 820 SVDEBUG << "TransformFactory: ERROR: transform id \""
Chris@1264 821 << identifier << "\" is of unknown type" << endl;
Chris@350 822 }
Chris@350 823
Chris@350 824 return plugin;
Chris@350 825 }
Chris@350 826
Chris@350 827 Vamp::Plugin *
Chris@350 828 TransformFactory::downcastVampPlugin(Vamp::PluginBase *plugin)
Chris@350 829 {
Chris@350 830 Vamp::Plugin *vp = dynamic_cast<Vamp::Plugin *>(plugin);
Chris@350 831 if (!vp) {
Chris@443 832 // cerr << "makeConsistentWithPlugin: not a Vamp::Plugin" << endl;
Chris@350 833 vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin); //!!! why?
Chris@350 834 }
Chris@350 835 if (!vp) {
Chris@443 836 // cerr << "makeConsistentWithPlugin: not a Vamp::PluginHostAdapter" << endl;
Chris@350 837 vp = dynamic_cast<Vamp::HostExt::PluginWrapper *>(plugin); //!!! no, I mean really why?
Chris@350 838 }
Chris@350 839 if (!vp) {
Chris@443 840 // cerr << "makeConsistentWithPlugin: not a Vamp::HostExt::PluginWrapper" << endl;
Chris@350 841 }
Chris@350 842 return vp;
Chris@350 843 }
Chris@350 844
Chris@330 845 bool
Chris@330 846 TransformFactory::haveTransform(TransformId identifier)
Chris@330 847 {
Chris@460 848 populateTransforms();
Chris@330 849 return (m_transforms.find(identifier) != m_transforms.end());
Chris@330 850 }
Chris@330 851
Chris@330 852 QString
Chris@330 853 TransformFactory::getTransformName(TransformId identifier)
Chris@330 854 {
Chris@330 855 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@1429 856 return m_transforms[identifier].name;
Chris@330 857 } else return "";
Chris@330 858 }
Chris@330 859
Chris@330 860 QString
Chris@330 861 TransformFactory::getTransformFriendlyName(TransformId identifier)
Chris@330 862 {
Chris@330 863 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@1429 864 return m_transforms[identifier].friendlyName;
Chris@330 865 } else return "";
Chris@330 866 }
Chris@330 867
Chris@330 868 QString
Chris@330 869 TransformFactory::getTransformUnits(TransformId identifier)
Chris@330 870 {
Chris@330 871 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@1429 872 return m_transforms[identifier].units;
Chris@330 873 } else return "";
Chris@330 874 }
Chris@330 875
Chris@472 876 QString
Chris@472 877 TransformFactory::getTransformInfoUrl(TransformId identifier)
Chris@472 878 {
Chris@472 879 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@1429 880 return m_transforms[identifier].infoUrl;
Chris@472 881 } else return "";
Chris@472 882 }
Chris@472 883
Chris@350 884 Vamp::Plugin::InputDomain
Chris@350 885 TransformFactory::getTransformInputDomain(TransformId identifier)
Chris@350 886 {
Chris@350 887 Transform transform;
Chris@350 888 transform.setIdentifier(identifier);
Chris@350 889
Chris@1264 890 SVDEBUG << "TransformFactory::getTransformInputDomain: identifier \""
Chris@1264 891 << identifier << "\"" << endl;
Chris@1264 892
Chris@350 893 if (transform.getType() != Transform::FeatureExtraction) {
Chris@350 894 return Vamp::Plugin::TimeDomain;
Chris@350 895 }
Chris@350 896
Chris@350 897 Vamp::Plugin *plugin =
Chris@351 898 downcastVampPlugin(instantiateDefaultPluginFor(identifier, 0));
Chris@350 899
Chris@350 900 if (plugin) {
Chris@350 901 Vamp::Plugin::InputDomain d = plugin->getInputDomain();
Chris@350 902 delete plugin;
Chris@350 903 return d;
Chris@350 904 }
Chris@350 905
Chris@350 906 return Vamp::Plugin::TimeDomain;
Chris@350 907 }
Chris@350 908
Chris@330 909 bool
Chris@330 910 TransformFactory::isTransformConfigurable(TransformId identifier)
Chris@330 911 {
Chris@330 912 if (m_transforms.find(identifier) != m_transforms.end()) {
Chris@1429 913 return m_transforms[identifier].configurable;
Chris@330 914 } else return false;
Chris@330 915 }
Chris@330 916
Chris@330 917 bool
Chris@330 918 TransformFactory::getTransformChannelRange(TransformId identifier,
Chris@330 919 int &min, int &max)
Chris@330 920 {
Chris@330 921 QString id = identifier.section(':', 0, 2);
Chris@330 922
Chris@1225 923 if (RealTimePluginFactory::instanceFor(id)) {
Chris@350 924
Chris@330 925 const RealTimePluginDescriptor *descriptor =
Chris@330 926 RealTimePluginFactory::instanceFor(id)->
Chris@330 927 getPluginDescriptor(id);
Chris@330 928 if (!descriptor) return false;
Chris@330 929
Chris@330 930 min = descriptor->audioInputPortCount;
Chris@330 931 max = descriptor->audioInputPortCount;
Chris@330 932
Chris@330 933 return true;
Chris@1225 934
Chris@1225 935 } else {
Chris@1225 936
Chris@1225 937 auto psd = FeatureExtractionPluginFactory::instance()->
Chris@1225 938 getPluginStaticData(id);
Chris@1225 939 if (psd.pluginKey == "") return false;
Chris@1225 940
Chris@1225 941 min = (int)psd.minChannelCount;
Chris@1225 942 max = (int)psd.maxChannelCount;
Chris@1225 943
Chris@1225 944 return true;
Chris@330 945 }
Chris@330 946
Chris@330 947 return false;
Chris@330 948 }
Chris@332 949
Chris@332 950 void
Chris@332 951 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 952 Vamp::PluginBase *plugin)
Chris@332 953 {
Chris@332 954 Transform::ParameterMap pmap;
Chris@332 955
Chris@350 956 //!!! record plugin & API version
Chris@350 957
Chris@350 958 //!!! check that this is the right plugin!
Chris@350 959
Chris@332 960 Vamp::PluginBase::ParameterList parameters =
Chris@332 961 plugin->getParameterDescriptors();
Chris@332 962
Chris@332 963 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 964 i != parameters.end(); ++i) {
Chris@332 965 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@810 966 // cerr << "TransformFactory::setParametersFromPlugin: parameter "
Chris@583 967 // << i->identifier << " -> value " <<
Chris@687 968 // pmap[i->identifier.c_str()] << endl;
Chris@332 969 }
Chris@332 970
Chris@332 971 transform.setParameters(pmap);
Chris@332 972
Chris@332 973 if (plugin->getPrograms().empty()) {
Chris@332 974 transform.setProgram("");
Chris@332 975 } else {
Chris@332 976 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 977 }
Chris@332 978
Chris@332 979 RealTimePluginInstance *rtpi =
Chris@332 980 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 981
Chris@332 982 Transform::ConfigurationMap cmap;
Chris@332 983
Chris@332 984 if (rtpi) {
Chris@332 985
Chris@332 986 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 987 rtpi->getConfigurePairs();
Chris@332 988
Chris@332 989 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 990 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 991 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 992 }
Chris@332 993 }
Chris@332 994
Chris@332 995 transform.setConfiguration(cmap);
Chris@332 996 }
Chris@332 997
Chris@332 998 void
Chris@350 999 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 1000 Vamp::PluginBase *plugin)
Chris@350 1001 {
Chris@350 1002 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 1003
Chris@350 1004 //!!! check that this is the right plugin!
Chris@350 1005
Chris@350 1006 RealTimePluginInstance *rtpi =
Chris@350 1007 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 1008
Chris@350 1009 if (rtpi) {
Chris@350 1010 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 1011 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 1012 i != cmap.end(); ++i) {
Chris@350 1013 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 1014 }
Chris@350 1015 }
Chris@350 1016
Chris@350 1017 if (transform.getProgram() != "") {
Chris@350 1018 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 1019 }
Chris@350 1020
Chris@350 1021 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 1022
Chris@350 1023 Vamp::PluginBase::ParameterList parameters =
Chris@350 1024 plugin->getParameterDescriptors();
Chris@350 1025
Chris@350 1026 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 1027 i != parameters.end(); ++i) {
Chris@350 1028 QString key = i->identifier.c_str();
Chris@350 1029 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 1030 if (pmi != pmap.end()) {
Chris@350 1031 plugin->setParameter(i->identifier, pmi->second);
Chris@350 1032 }
Chris@350 1033 }
Chris@350 1034 }
Chris@350 1035
Chris@350 1036 void
Chris@332 1037 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 1038 Vamp::PluginBase *plugin)
Chris@332 1039 {
Chris@350 1040 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 1041
Chris@332 1042 if (!vp) {
Chris@332 1043 // time domain input for real-time effects plugin
Chris@332 1044 if (!transform.getBlockSize()) {
Chris@332 1045 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 1046 transform.setBlockSize(transform.getStepSize());
Chris@332 1047 } else {
Chris@332 1048 transform.setStepSize(transform.getBlockSize());
Chris@332 1049 }
Chris@332 1050 } else {
Chris@332 1051 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 1052 if (!transform.getStepSize()) {
Chris@1039 1053 transform.setStepSize((int)vp->getPreferredStepSize());
Chris@332 1054 }
Chris@332 1055 if (!transform.getBlockSize()) {
Chris@1039 1056 transform.setBlockSize((int)vp->getPreferredBlockSize());
Chris@332 1057 }
Chris@332 1058 if (!transform.getBlockSize()) {
Chris@332 1059 transform.setBlockSize(1024);
Chris@332 1060 }
Chris@332 1061 if (!transform.getStepSize()) {
Chris@332 1062 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@443 1063 // cerr << "frequency domain, step = " << blockSize/2 << endl;
Chris@332 1064 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 1065 } else {
Chris@443 1066 // cerr << "time domain, step = " << blockSize/2 << endl;
Chris@332 1067 transform.setStepSize(transform.getBlockSize());
Chris@332 1068 }
Chris@332 1069 }
Chris@332 1070 }
Chris@332 1071 }
Chris@332 1072
Chris@350 1073 QString
Chris@350 1074 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 1075 {
Chris@350 1076 QString xml;
Chris@350 1077
Chris@1264 1078 SVDEBUG << "TransformFactory::getPluginConfigurationXml: identifier \""
Chris@1264 1079 << t.getIdentifier() << "\"" << endl;
Chris@1264 1080
Chris@351 1081 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1082 (t.getIdentifier(), 0);
Chris@350 1083 if (!plugin) {
Chris@1264 1084 SVDEBUG << "TransformFactory::getPluginConfigurationXml: "
Chris@1264 1085 << "Unable to instantiate plugin for transform \""
Chris@1264 1086 << t.getIdentifier() << "\"" << endl;
Chris@350 1087 return xml;
Chris@332 1088 }
Chris@332 1089
Chris@351 1090 setPluginParameters(t, plugin);
Chris@351 1091
Chris@350 1092 QTextStream out(&xml);
Chris@350 1093 PluginXml(plugin).toXml(out);
Chris@350 1094 delete plugin;
Chris@332 1095
Chris@350 1096 return xml;
Chris@350 1097 }
Chris@332 1098
Chris@350 1099 void
Chris@350 1100 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 1101 QString xml)
Chris@350 1102 {
Chris@1264 1103 SVDEBUG << "TransformFactory::setParametersFromPluginConfigurationXml: identifier \""
Chris@1264 1104 << t.getIdentifier() << "\"" << endl;
Chris@1264 1105
Chris@351 1106 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1107 (t.getIdentifier(), 0);
Chris@350 1108 if (!plugin) {
Chris@1264 1109 SVDEBUG << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@1264 1110 << "Unable to instantiate plugin for transform \""
Chris@1264 1111 << t.getIdentifier() << "\"" << endl;
Chris@350 1112 return;
Chris@332 1113 }
Chris@332 1114
Chris@350 1115 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 1116 setParametersFromPlugin(t, plugin);
Chris@350 1117 delete plugin;
Chris@332 1118 }
Chris@332 1119
Chris@443 1120 TransformFactory::SearchResults
Chris@443 1121 TransformFactory::search(QString keyword)
Chris@443 1122 {
Chris@443 1123 QStringList keywords;
Chris@443 1124 keywords << keyword;
Chris@443 1125 return search(keywords);
Chris@443 1126 }
Chris@443 1127
Chris@443 1128 TransformFactory::SearchResults
Chris@443 1129 TransformFactory::search(QStringList keywords)
Chris@443 1130 {
Chris@460 1131 populateTransforms();
Chris@443 1132
Chris@447 1133 if (keywords.size() > 1) {
Chris@447 1134 // Additional score for all keywords in a row
Chris@447 1135 keywords.push_back(keywords.join(" "));
Chris@447 1136 }
Chris@447 1137
Chris@443 1138 SearchResults results;
Chris@457 1139 TextMatcher matcher;
Chris@443 1140
Chris@443 1141 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@443 1142 i != m_transforms.end(); ++i) {
Chris@443 1143
Chris@457 1144 TextMatcher::Match match;
Chris@443 1145
Chris@457 1146 match.key = i->first;
Chris@443 1147
Chris@487 1148 matcher.test(match, keywords,
Chris@487 1149 getTransformTypeName(i->second.type),
Chris@487 1150 tr("Plugin type"), 5);
Chris@487 1151
Chris@457 1152 matcher.test(match, keywords, i->second.category, tr("Category"), 20);
Chris@457 1153 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6);
Chris@457 1154 matcher.test(match, keywords, i->second.name, tr("Name"), 30);
Chris@457 1155 matcher.test(match, keywords, i->second.description, tr("Description"), 20);
Chris@457 1156 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10);
Chris@457 1157 matcher.test(match, keywords, i->second.units, tr("Units"), 10);
Chris@457 1158
Chris@457 1159 if (match.score > 0) results[i->first] = match;
Chris@457 1160 }
Chris@457 1161
Chris@460 1162 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@460 1163 // uninstalled transforms are being populated; this may take some time,
Chris@484 1164 // and they aren't critical, but we will speed them up if necessary
Chris@1264 1165 SVDEBUG << "TransformFactory::search: Uninstalled transforms mutex is held, skipping" << endl;
Chris@484 1166 m_populatingSlowly = false;
Chris@460 1167 return results;
Chris@460 1168 }
Chris@460 1169
Chris@460 1170 if (!m_uninstalledTransformsPopulated) {
Chris@1264 1171 SVDEBUG << "WARNING: TransformFactory::search: Uninstalled transforms are not populated yet" << endl
Chris@1264 1172 << "and are not being populated either -- was the thread not started correctly?" << endl;
Chris@460 1173 m_uninstalledTransformsMutex.unlock();
Chris@460 1174 return results;
Chris@460 1175 }
Chris@460 1176
Chris@460 1177 m_uninstalledTransformsMutex.unlock();
Chris@457 1178
Chris@457 1179 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 1180 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 1181
Chris@457 1182 TextMatcher::Match match;
Chris@457 1183
Chris@457 1184 match.key = i->first;
Chris@457 1185
Chris@487 1186 matcher.test(match, keywords,
Chris@487 1187 getTransformTypeName(i->second.type),
Chris@487 1188 tr("Plugin type"), 2);
Chris@487 1189
Chris@457 1190 matcher.test(match, keywords, i->second.category, tr("Category"), 10);
Chris@457 1191 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3);
Chris@457 1192 matcher.test(match, keywords, i->second.name, tr("Name"), 15);
Chris@457 1193 matcher.test(match, keywords, i->second.description, tr("Description"), 10);
Chris@457 1194 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5);
Chris@457 1195 matcher.test(match, keywords, i->second.units, tr("Units"), 5);
Chris@443 1196
Chris@443 1197 if (match.score > 0) results[i->first] = match;
Chris@443 1198 }
Chris@443 1199
Chris@443 1200 return results;
Chris@443 1201 }
Chris@443 1202