annotate transform/TransformFactory.cpp @ 822:54829c1e155e tonioni

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