annotate transform/TransformFactory.cpp @ 1223:c2207877689d piper

Avoid instantiating all plugins (in piper client) on startup, using plugin static data instead. Problem of where to get the units field from is still pending.
author Chris Cannam
date Thu, 20 Oct 2016 14:06:58 +0100
parents 6b1af0f05f06
children ba16388b937d
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@330 19 #include "plugin/RealTimePluginFactory.h"
Chris@332 20 #include "plugin/RealTimePluginInstance.h"
Chris@330 21 #include "plugin/PluginXml.h"
Chris@330 22
Chris@475 23 #include <vamp-hostsdk/Plugin.h>
Chris@475 24 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@475 25 #include <vamp-hostsdk/PluginWrapper.h>
Chris@330 26
Chris@457 27 #include "rdf/PluginRDFIndexer.h"
Chris@457 28 #include "rdf/PluginRDFDescription.h"
Chris@457 29
Chris@446 30 #include "base/XmlExportable.h"
Chris@446 31
Chris@330 32 #include <iostream>
Chris@330 33 #include <set>
Chris@330 34
Chris@330 35 #include <QRegExp>
Chris@350 36 #include <QTextStream>
Chris@330 37
Chris@460 38 #include "base/Thread.h"
Chris@460 39
Chris@810 40 //#define DEBUG_TRANSFORM_FACTORY 1
Chris@810 41
Chris@330 42 TransformFactory *
Chris@330 43 TransformFactory::m_instance = new TransformFactory;
Chris@330 44
Chris@330 45 TransformFactory *
Chris@330 46 TransformFactory::getInstance()
Chris@330 47 {
Chris@330 48 return m_instance;
Chris@330 49 }
Chris@330 50
Chris@574 51 void
Chris@574 52 TransformFactory::deleteInstance()
Chris@574 53 {
Chris@690 54 SVDEBUG << "TransformFactory::deleteInstance called" << endl;
Chris@574 55 delete m_instance;
Chris@574 56 m_instance = 0;
Chris@574 57 }
Chris@574 58
Chris@457 59 TransformFactory::TransformFactory() :
Chris@457 60 m_transformsPopulated(false),
Chris@477 61 m_uninstalledTransformsPopulated(false),
Chris@574 62 m_thread(0),
Chris@976 63 m_exiting(false),
Chris@976 64 m_populatingSlowly(false)
Chris@457 65 {
Chris@457 66 }
Chris@457 67
Chris@330 68 TransformFactory::~TransformFactory()
Chris@330 69 {
Chris@574 70 m_exiting = true;
Chris@574 71 if (m_thread) {
Chris@600 72 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@690 73 SVDEBUG << "TransformFactory::~TransformFactory: waiting on thread" << endl;
Chris@600 74 #endif
Chris@574 75 m_thread->wait();
Chris@574 76 delete m_thread;
Chris@600 77 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@690 78 SVDEBUG << "TransformFactory::~TransformFactory: waited and done" << endl;
Chris@600 79 #endif
Chris@574 80 }
Chris@330 81 }
Chris@330 82
Chris@477 83 void
Chris@477 84 TransformFactory::startPopulationThread()
Chris@477 85 {
Chris@482 86 m_uninstalledTransformsMutex.lock();
Chris@477 87
Chris@482 88 if (m_thread) {
Chris@482 89 m_uninstalledTransformsMutex.unlock();
Chris@482 90 return;
Chris@482 91 }
Chris@482 92 m_thread = new UninstalledTransformsPopulateThread(this);
Chris@477 93
Chris@482 94 m_uninstalledTransformsMutex.unlock();
Chris@482 95
Chris@477 96 m_thread->start();
Chris@477 97 }
Chris@477 98
Chris@481 99 void
Chris@481 100 TransformFactory::UninstalledTransformsPopulateThread::run()
Chris@481 101 {
Chris@481 102 m_factory->m_populatingSlowly = true;
Chris@481 103 sleep(1);
Chris@481 104 m_factory->populateUninstalledTransforms();
Chris@481 105 }
Chris@481 106
Chris@330 107 TransformList
Chris@350 108 TransformFactory::getAllTransformDescriptions()
Chris@330 109 {
Chris@460 110 populateTransforms();
Chris@330 111
Chris@330 112 std::set<TransformDescription> dset;
Chris@330 113 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 114 i != m_transforms.end(); ++i) {
Chris@600 115 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 116 cerr << "inserting transform into set: id = " << i->second.identifier << endl;
Chris@600 117 #endif
Chris@330 118 dset.insert(i->second);
Chris@330 119 }
Chris@330 120
Chris@330 121 TransformList list;
Chris@330 122 for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@330 123 i != dset.end(); ++i) {
Chris@600 124 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 125 cerr << "inserting transform into list: id = " << i->identifier << endl;
Chris@600 126 #endif
Chris@330 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@457 159 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 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@457 164 dset.insert(i->second);
Chris@457 165 }
Chris@457 166
Chris@457 167 TransformList list;
Chris@457 168 for (std::set<TransformDescription>::const_iterator i = dset.begin();
Chris@457 169 i != dset.end(); ++i) {
Chris@600 170 #ifdef DEBUG_TRANSFORM_FACTORY
Chris@810 171 cerr << "inserting transform into uninstalled list: id = " << i->identifier << endl;
Chris@600 172 #endif
Chris@457 173 list.push_back(*i);
Chris@457 174 }
Chris@457 175
Chris@457 176 return list;
Chris@457 177 }
Chris@457 178
Chris@457 179 TransformDescription
Chris@457 180 TransformFactory::getUninstalledTransformDescription(TransformId id)
Chris@457 181 {
Chris@479 182 m_populatingSlowly = false;
Chris@460 183 populateUninstalledTransforms();
Chris@457 184
Chris@457 185 if (m_uninstalledTransforms.find(id) == m_uninstalledTransforms.end()) {
Chris@457 186 return TransformDescription();
Chris@457 187 }
Chris@457 188
Chris@457 189 return m_uninstalledTransforms[id];
Chris@457 190 }
Chris@457 191
Chris@485 192 bool
Chris@485 193 TransformFactory::haveUninstalledTransforms(bool waitForCheckToComplete)
Chris@485 194 {
Chris@485 195 if (waitForCheckToComplete) {
Chris@485 196 populateUninstalledTransforms();
Chris@485 197 } else {
Chris@485 198 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@485 199 return false;
Chris@485 200 }
Chris@485 201 if (!m_uninstalledTransformsPopulated) {
Chris@485 202 m_uninstalledTransformsMutex.unlock();
Chris@485 203 return false;
Chris@485 204 }
Chris@485 205 m_uninstalledTransformsMutex.unlock();
Chris@485 206 }
Chris@485 207
Chris@485 208 return !m_uninstalledTransforms.empty();
Chris@485 209 }
Chris@485 210
Chris@457 211 TransformFactory::TransformInstallStatus
Chris@457 212 TransformFactory::getTransformInstallStatus(TransformId id)
Chris@457 213 {
Chris@460 214 populateTransforms();
Chris@457 215
Chris@457 216 if (m_transforms.find(id) != m_transforms.end()) {
Chris@457 217 return TransformInstalled;
Chris@457 218 }
Chris@473 219
Chris@473 220 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@473 221 // uninstalled transforms are being populated; this may take some time,
Chris@473 222 // and they aren't critical
Chris@473 223 return TransformUnknown;
Chris@473 224 }
Chris@473 225
Chris@473 226 if (!m_uninstalledTransformsPopulated) {
Chris@473 227 m_uninstalledTransformsMutex.unlock();
Chris@479 228 m_populatingSlowly = false;
Chris@473 229 populateUninstalledTransforms();
Chris@473 230 m_uninstalledTransformsMutex.lock();
Chris@473 231 }
Chris@473 232
Chris@457 233 if (m_uninstalledTransforms.find(id) != m_uninstalledTransforms.end()) {
Chris@482 234 m_uninstalledTransformsMutex.unlock();
Chris@457 235 return TransformNotInstalled;
Chris@457 236 }
Chris@473 237
Chris@473 238 m_uninstalledTransformsMutex.unlock();
Chris@457 239 return TransformUnknown;
Chris@457 240 }
Chris@457 241
Chris@457 242
Chris@487 243 std::vector<TransformDescription::Type>
Chris@330 244 TransformFactory::getAllTransformTypes()
Chris@330 245 {
Chris@460 246 populateTransforms();
Chris@330 247
Chris@487 248 std::set<TransformDescription::Type> types;
Chris@330 249 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 250 i != m_transforms.end(); ++i) {
Chris@330 251 types.insert(i->second.type);
Chris@330 252 }
Chris@330 253
Chris@487 254 std::vector<TransformDescription::Type> rv;
Chris@487 255 for (std::set<TransformDescription::Type>::iterator i = types.begin(); i != types.end(); ++i) {
Chris@330 256 rv.push_back(*i);
Chris@330 257 }
Chris@330 258
Chris@330 259 return rv;
Chris@330 260 }
Chris@330 261
Chris@330 262 std::vector<QString>
Chris@487 263 TransformFactory::getTransformCategories(TransformDescription::Type transformType)
Chris@330 264 {
Chris@460 265 populateTransforms();
Chris@330 266
Chris@330 267 std::set<QString> categories;
Chris@330 268 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 269 i != m_transforms.end(); ++i) {
Chris@330 270 if (i->second.type == transformType) {
Chris@330 271 categories.insert(i->second.category);
Chris@330 272 }
Chris@330 273 }
Chris@330 274
Chris@330 275 bool haveEmpty = false;
Chris@330 276
Chris@330 277 std::vector<QString> rv;
Chris@330 278 for (std::set<QString>::iterator i = categories.begin();
Chris@330 279 i != categories.end(); ++i) {
Chris@330 280 if (*i != "") rv.push_back(*i);
Chris@330 281 else haveEmpty = true;
Chris@330 282 }
Chris@330 283
Chris@330 284 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 285
Chris@330 286 return rv;
Chris@330 287 }
Chris@330 288
Chris@330 289 std::vector<QString>
Chris@487 290 TransformFactory::getTransformMakers(TransformDescription::Type transformType)
Chris@330 291 {
Chris@460 292 populateTransforms();
Chris@330 293
Chris@330 294 std::set<QString> makers;
Chris@330 295 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@330 296 i != m_transforms.end(); ++i) {
Chris@330 297 if (i->second.type == transformType) {
Chris@330 298 makers.insert(i->second.maker);
Chris@330 299 }
Chris@330 300 }
Chris@330 301
Chris@330 302 bool haveEmpty = false;
Chris@330 303
Chris@330 304 std::vector<QString> rv;
Chris@330 305 for (std::set<QString>::iterator i = makers.begin();
Chris@330 306 i != makers.end(); ++i) {
Chris@330 307 if (*i != "") rv.push_back(*i);
Chris@330 308 else haveEmpty = true;
Chris@330 309 }
Chris@330 310
Chris@330 311 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
Chris@330 312
Chris@330 313 return rv;
Chris@330 314 }
Chris@330 315
Chris@487 316 QString
Chris@487 317 TransformFactory::getTransformTypeName(TransformDescription::Type type) const
Chris@487 318 {
Chris@487 319 switch (type) {
Chris@487 320 case TransformDescription::Analysis: return tr("Analysis");
Chris@487 321 case TransformDescription::Effects: return tr("Effects");
Chris@487 322 case TransformDescription::EffectsData: return tr("Effects Data");
Chris@487 323 case TransformDescription::Generator: return tr("Generator");
Chris@487 324 case TransformDescription::UnknownType: return tr("Other");
Chris@487 325 }
Chris@489 326 return tr("Other");
Chris@487 327 }
Chris@487 328
Chris@330 329 void
Chris@330 330 TransformFactory::populateTransforms()
Chris@330 331 {
Chris@460 332 MutexLocker locker(&m_transformsMutex,
Chris@460 333 "TransformFactory::populateTransforms");
Chris@460 334 if (m_transformsPopulated) {
Chris@460 335 return;
Chris@460 336 }
Chris@460 337
Chris@330 338 TransformDescriptionMap transforms;
Chris@330 339
Chris@330 340 populateFeatureExtractionPlugins(transforms);
Chris@576 341 if (m_exiting) return;
Chris@330 342 populateRealTimePlugins(transforms);
Chris@576 343 if (m_exiting) return;
Chris@330 344
Chris@330 345 // disambiguate plugins with similar names
Chris@330 346
Chris@330 347 std::map<QString, int> names;
Chris@330 348 std::map<QString, QString> pluginSources;
Chris@330 349 std::map<QString, QString> pluginMakers;
Chris@330 350
Chris@330 351 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 352 i != transforms.end(); ++i) {
Chris@330 353
Chris@330 354 TransformDescription desc = i->second;
Chris@330 355
Chris@330 356 QString td = desc.name;
Chris@330 357 QString tn = td.section(": ", 0, 0);
Chris@330 358 QString pn = desc.identifier.section(":", 1, 1);
Chris@330 359
Chris@330 360 if (pluginSources.find(tn) != pluginSources.end()) {
Chris@330 361 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
Chris@330 362 ++names[tn];
Chris@330 363 }
Chris@330 364 } else {
Chris@330 365 ++names[tn];
Chris@330 366 pluginSources[tn] = pn;
Chris@330 367 pluginMakers[tn] = desc.maker;
Chris@330 368 }
Chris@330 369 }
Chris@330 370
Chris@330 371 std::map<QString, int> counts;
Chris@330 372 m_transforms.clear();
Chris@330 373
Chris@330 374 for (TransformDescriptionMap::iterator i = transforms.begin();
Chris@330 375 i != transforms.end(); ++i) {
Chris@330 376
Chris@330 377 TransformDescription desc = i->second;
Chris@330 378 QString identifier = desc.identifier;
Chris@330 379 QString maker = desc.maker;
Chris@330 380
Chris@330 381 QString td = desc.name;
Chris@330 382 QString tn = td.section(": ", 0, 0);
Chris@330 383 QString to = td.section(": ", 1);
Chris@330 384
Chris@330 385 if (names[tn] > 1) {
Chris@330 386 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
Chris@330 387 tn = QString("%1 [%2]").arg(tn).arg(maker);
Chris@330 388 }
Chris@330 389
Chris@330 390 if (to != "") {
Chris@330 391 desc.name = QString("%1: %2").arg(tn).arg(to);
Chris@330 392 } else {
Chris@330 393 desc.name = tn;
Chris@330 394 }
Chris@330 395
Chris@330 396 m_transforms[identifier] = desc;
Chris@330 397 }
Chris@457 398
Chris@457 399 m_transformsPopulated = true;
Chris@330 400 }
Chris@330 401
Chris@330 402 void
Chris@330 403 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
Chris@330 404 {
Chris@330 405 std::vector<QString> plugs =
Chris@330 406 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
Chris@576 407 if (m_exiting) return;
Chris@330 408
Chris@930 409 for (int i = 0; i < (int)plugs.size(); ++i) {
Chris@330 410
Chris@330 411 QString pluginId = plugs[i];
Chris@330 412
Chris@330 413 FeatureExtractionPluginFactory *factory =
Chris@330 414 FeatureExtractionPluginFactory::instanceFor(pluginId);
Chris@330 415
Chris@330 416 if (!factory) {
Chris@845 417 cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId << endl;
Chris@330 418 continue;
Chris@330 419 }
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@350 797 FeatureExtractionPluginFactory *factory =
Chris@350 798 FeatureExtractionPluginFactory::instanceFor(pluginId);
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@330 917 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@330 918
Chris@330 919 Vamp::Plugin *plugin =
Chris@330 920 FeatureExtractionPluginFactory::instanceFor(id)->
Chris@350 921 instantiatePlugin(id, 44100);
Chris@330 922 if (!plugin) return false;
Chris@330 923
Chris@1039 924 min = (int)plugin->getMinChannelCount();
Chris@1039 925 max = (int)plugin->getMaxChannelCount();
Chris@330 926 delete plugin;
Chris@330 927
Chris@330 928 return true;
Chris@330 929
Chris@330 930 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@330 931
Chris@350 932 // don't need to instantiate
Chris@350 933
Chris@330 934 const RealTimePluginDescriptor *descriptor =
Chris@330 935 RealTimePluginFactory::instanceFor(id)->
Chris@330 936 getPluginDescriptor(id);
Chris@330 937 if (!descriptor) return false;
Chris@330 938
Chris@330 939 min = descriptor->audioInputPortCount;
Chris@330 940 max = descriptor->audioInputPortCount;
Chris@330 941
Chris@330 942 return true;
Chris@330 943 }
Chris@330 944
Chris@330 945 return false;
Chris@330 946 }
Chris@332 947
Chris@332 948 void
Chris@332 949 TransformFactory::setParametersFromPlugin(Transform &transform,
Chris@332 950 Vamp::PluginBase *plugin)
Chris@332 951 {
Chris@332 952 Transform::ParameterMap pmap;
Chris@332 953
Chris@350 954 //!!! record plugin & API version
Chris@350 955
Chris@350 956 //!!! check that this is the right plugin!
Chris@350 957
Chris@332 958 Vamp::PluginBase::ParameterList parameters =
Chris@332 959 plugin->getParameterDescriptors();
Chris@332 960
Chris@332 961 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@332 962 i != parameters.end(); ++i) {
Chris@332 963 pmap[i->identifier.c_str()] = plugin->getParameter(i->identifier);
Chris@810 964 // cerr << "TransformFactory::setParametersFromPlugin: parameter "
Chris@583 965 // << i->identifier << " -> value " <<
Chris@687 966 // pmap[i->identifier.c_str()] << endl;
Chris@332 967 }
Chris@332 968
Chris@332 969 transform.setParameters(pmap);
Chris@332 970
Chris@332 971 if (plugin->getPrograms().empty()) {
Chris@332 972 transform.setProgram("");
Chris@332 973 } else {
Chris@332 974 transform.setProgram(plugin->getCurrentProgram().c_str());
Chris@332 975 }
Chris@332 976
Chris@332 977 RealTimePluginInstance *rtpi =
Chris@332 978 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@332 979
Chris@332 980 Transform::ConfigurationMap cmap;
Chris@332 981
Chris@332 982 if (rtpi) {
Chris@332 983
Chris@332 984 RealTimePluginInstance::ConfigurationPairMap configurePairs =
Chris@332 985 rtpi->getConfigurePairs();
Chris@332 986
Chris@332 987 for (RealTimePluginInstance::ConfigurationPairMap::const_iterator i
Chris@332 988 = configurePairs.begin(); i != configurePairs.end(); ++i) {
Chris@332 989 cmap[i->first.c_str()] = i->second.c_str();
Chris@332 990 }
Chris@332 991 }
Chris@332 992
Chris@332 993 transform.setConfiguration(cmap);
Chris@332 994 }
Chris@332 995
Chris@332 996 void
Chris@350 997 TransformFactory::setPluginParameters(const Transform &transform,
Chris@350 998 Vamp::PluginBase *plugin)
Chris@350 999 {
Chris@350 1000 //!!! check plugin & API version (see e.g. PluginXml::setParameters)
Chris@350 1001
Chris@350 1002 //!!! check that this is the right plugin!
Chris@350 1003
Chris@350 1004 RealTimePluginInstance *rtpi =
Chris@350 1005 dynamic_cast<RealTimePluginInstance *>(plugin);
Chris@350 1006
Chris@350 1007 if (rtpi) {
Chris@350 1008 const Transform::ConfigurationMap &cmap = transform.getConfiguration();
Chris@350 1009 for (Transform::ConfigurationMap::const_iterator i = cmap.begin();
Chris@350 1010 i != cmap.end(); ++i) {
Chris@350 1011 rtpi->configure(i->first.toStdString(), i->second.toStdString());
Chris@350 1012 }
Chris@350 1013 }
Chris@350 1014
Chris@350 1015 if (transform.getProgram() != "") {
Chris@350 1016 plugin->selectProgram(transform.getProgram().toStdString());
Chris@350 1017 }
Chris@350 1018
Chris@350 1019 const Transform::ParameterMap &pmap = transform.getParameters();
Chris@350 1020
Chris@350 1021 Vamp::PluginBase::ParameterList parameters =
Chris@350 1022 plugin->getParameterDescriptors();
Chris@350 1023
Chris@350 1024 for (Vamp::PluginBase::ParameterList::const_iterator i = parameters.begin();
Chris@350 1025 i != parameters.end(); ++i) {
Chris@350 1026 QString key = i->identifier.c_str();
Chris@350 1027 Transform::ParameterMap::const_iterator pmi = pmap.find(key);
Chris@350 1028 if (pmi != pmap.end()) {
Chris@350 1029 plugin->setParameter(i->identifier, pmi->second);
Chris@350 1030 }
Chris@350 1031 }
Chris@350 1032 }
Chris@350 1033
Chris@350 1034 void
Chris@332 1035 TransformFactory::makeContextConsistentWithPlugin(Transform &transform,
Chris@332 1036 Vamp::PluginBase *plugin)
Chris@332 1037 {
Chris@350 1038 const Vamp::Plugin *vp = downcastVampPlugin(plugin);
Chris@332 1039
Chris@332 1040 if (!vp) {
Chris@332 1041 // time domain input for real-time effects plugin
Chris@332 1042 if (!transform.getBlockSize()) {
Chris@332 1043 if (!transform.getStepSize()) transform.setStepSize(1024);
Chris@332 1044 transform.setBlockSize(transform.getStepSize());
Chris@332 1045 } else {
Chris@332 1046 transform.setStepSize(transform.getBlockSize());
Chris@332 1047 }
Chris@332 1048 } else {
Chris@332 1049 Vamp::Plugin::InputDomain domain = vp->getInputDomain();
Chris@332 1050 if (!transform.getStepSize()) {
Chris@1039 1051 transform.setStepSize((int)vp->getPreferredStepSize());
Chris@332 1052 }
Chris@332 1053 if (!transform.getBlockSize()) {
Chris@1039 1054 transform.setBlockSize((int)vp->getPreferredBlockSize());
Chris@332 1055 }
Chris@332 1056 if (!transform.getBlockSize()) {
Chris@332 1057 transform.setBlockSize(1024);
Chris@332 1058 }
Chris@332 1059 if (!transform.getStepSize()) {
Chris@332 1060 if (domain == Vamp::Plugin::FrequencyDomain) {
Chris@443 1061 // cerr << "frequency domain, step = " << blockSize/2 << endl;
Chris@332 1062 transform.setStepSize(transform.getBlockSize()/2);
Chris@332 1063 } else {
Chris@443 1064 // cerr << "time domain, step = " << blockSize/2 << endl;
Chris@332 1065 transform.setStepSize(transform.getBlockSize());
Chris@332 1066 }
Chris@332 1067 }
Chris@332 1068 }
Chris@332 1069 }
Chris@332 1070
Chris@350 1071 QString
Chris@350 1072 TransformFactory::getPluginConfigurationXml(const Transform &t)
Chris@332 1073 {
Chris@350 1074 QString xml;
Chris@350 1075
Chris@351 1076 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1077 (t.getIdentifier(), 0);
Chris@350 1078 if (!plugin) {
Chris@810 1079 cerr << "TransformFactory::getPluginConfigurationXml: "
Chris@350 1080 << "Unable to instantiate plugin for transform \""
Chris@686 1081 << t.getIdentifier() << "\"" << endl;
Chris@350 1082 return xml;
Chris@332 1083 }
Chris@332 1084
Chris@351 1085 setPluginParameters(t, plugin);
Chris@351 1086
Chris@350 1087 QTextStream out(&xml);
Chris@350 1088 PluginXml(plugin).toXml(out);
Chris@350 1089 delete plugin;
Chris@332 1090
Chris@350 1091 return xml;
Chris@350 1092 }
Chris@332 1093
Chris@350 1094 void
Chris@350 1095 TransformFactory::setParametersFromPluginConfigurationXml(Transform &t,
Chris@350 1096 QString xml)
Chris@350 1097 {
Chris@351 1098 Vamp::PluginBase *plugin = instantiateDefaultPluginFor
Chris@351 1099 (t.getIdentifier(), 0);
Chris@350 1100 if (!plugin) {
Chris@810 1101 cerr << "TransformFactory::setParametersFromPluginConfigurationXml: "
Chris@350 1102 << "Unable to instantiate plugin for transform \""
Chris@686 1103 << t.getIdentifier() << "\"" << endl;
Chris@350 1104 return;
Chris@332 1105 }
Chris@332 1106
Chris@350 1107 PluginXml(plugin).setParametersFromXml(xml);
Chris@350 1108 setParametersFromPlugin(t, plugin);
Chris@350 1109 delete plugin;
Chris@332 1110 }
Chris@332 1111
Chris@443 1112 TransformFactory::SearchResults
Chris@443 1113 TransformFactory::search(QString keyword)
Chris@443 1114 {
Chris@443 1115 QStringList keywords;
Chris@443 1116 keywords << keyword;
Chris@443 1117 return search(keywords);
Chris@443 1118 }
Chris@443 1119
Chris@443 1120 TransformFactory::SearchResults
Chris@443 1121 TransformFactory::search(QStringList keywords)
Chris@443 1122 {
Chris@460 1123 populateTransforms();
Chris@443 1124
Chris@447 1125 if (keywords.size() > 1) {
Chris@447 1126 // Additional score for all keywords in a row
Chris@447 1127 keywords.push_back(keywords.join(" "));
Chris@447 1128 }
Chris@447 1129
Chris@443 1130 SearchResults results;
Chris@457 1131 TextMatcher matcher;
Chris@443 1132
Chris@443 1133 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
Chris@443 1134 i != m_transforms.end(); ++i) {
Chris@443 1135
Chris@457 1136 TextMatcher::Match match;
Chris@443 1137
Chris@457 1138 match.key = i->first;
Chris@443 1139
Chris@487 1140 matcher.test(match, keywords,
Chris@487 1141 getTransformTypeName(i->second.type),
Chris@487 1142 tr("Plugin type"), 5);
Chris@487 1143
Chris@457 1144 matcher.test(match, keywords, i->second.category, tr("Category"), 20);
Chris@457 1145 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 6);
Chris@457 1146 matcher.test(match, keywords, i->second.name, tr("Name"), 30);
Chris@457 1147 matcher.test(match, keywords, i->second.description, tr("Description"), 20);
Chris@457 1148 matcher.test(match, keywords, i->second.maker, tr("Maker"), 10);
Chris@457 1149 matcher.test(match, keywords, i->second.units, tr("Units"), 10);
Chris@457 1150
Chris@457 1151 if (match.score > 0) results[i->first] = match;
Chris@457 1152 }
Chris@457 1153
Chris@460 1154 if (!m_uninstalledTransformsMutex.tryLock()) {
Chris@460 1155 // uninstalled transforms are being populated; this may take some time,
Chris@484 1156 // and they aren't critical, but we will speed them up if necessary
Chris@810 1157 cerr << "TransformFactory::search: Uninstalled transforms mutex is held, skipping" << endl;
Chris@484 1158 m_populatingSlowly = false;
Chris@460 1159 return results;
Chris@460 1160 }
Chris@460 1161
Chris@460 1162 if (!m_uninstalledTransformsPopulated) {
Chris@843 1163 cerr << "WARNING: TransformFactory::search: Uninstalled transforms are not populated yet" << endl
Chris@460 1164 << "and are not being populated either -- was the thread not started correctly?" << endl;
Chris@460 1165 m_uninstalledTransformsMutex.unlock();
Chris@460 1166 return results;
Chris@460 1167 }
Chris@460 1168
Chris@460 1169 m_uninstalledTransformsMutex.unlock();
Chris@457 1170
Chris@457 1171 for (TransformDescriptionMap::const_iterator i = m_uninstalledTransforms.begin();
Chris@457 1172 i != m_uninstalledTransforms.end(); ++i) {
Chris@457 1173
Chris@457 1174 TextMatcher::Match match;
Chris@457 1175
Chris@457 1176 match.key = i->first;
Chris@457 1177
Chris@487 1178 matcher.test(match, keywords,
Chris@487 1179 getTransformTypeName(i->second.type),
Chris@487 1180 tr("Plugin type"), 2);
Chris@487 1181
Chris@457 1182 matcher.test(match, keywords, i->second.category, tr("Category"), 10);
Chris@457 1183 matcher.test(match, keywords, i->second.identifier, tr("System Identifier"), 3);
Chris@457 1184 matcher.test(match, keywords, i->second.name, tr("Name"), 15);
Chris@457 1185 matcher.test(match, keywords, i->second.description, tr("Description"), 10);
Chris@457 1186 matcher.test(match, keywords, i->second.maker, tr("Maker"), 5);
Chris@457 1187 matcher.test(match, keywords, i->second.units, tr("Units"), 5);
Chris@443 1188
Chris@443 1189 if (match.score > 0) results[i->first] = match;
Chris@443 1190 }
Chris@443 1191
Chris@443 1192 return results;
Chris@443 1193 }
Chris@443 1194