annotate transform/TransformFactory.cpp @ 1247:8f076d02569a piper

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