annotate transform/TransformFactory.cpp @ 875:3e6ed8a8577b tonioni

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